属性
1、#import:告诉预处理器,将头文件的内容包含到本文件中,OC中的import能保证同一头文件只会被包含一次;
2、@interface:声明一个类,@end:结束声明;
3、@property:设置成员变量的属性编译器自动生成setter/getter方法;
4、@dynamic:告诉关键字编译器有我们自己实现访问方法;
5、@synthesize:编译器自己实现;
6、readonly:只读,readwrite:读写(默认),writeonly:只写;
7、nonatomic:非原子性访问,对属性赋值时不加锁,多线程并发访问会提高性能,默认为原子性(atomic);
8、atomic:原子性,提供多线程安全;
9、assign:简单赋值,不更改索引记数,适用于基础数据类型(NSInteger,CGFloat)和C数据类型(int,float,double,char等);
10、copy:建立一个引用记数为1的对象,然后释放旧对象,只对遵守NSCopying协议的类型有效,适用于NSString;
11、retain:释放旧的对象,将旧对象的值赋予输入对象,在将引用计数+1,适用于其他NSObject和其子类;
12、copyORretain:
copy实际建立了一个相同的对象,而retain不是:
例:一个NSString对象,地址为0xaabb,内容为@“haha”;
copy到另一个nsstring之后,地址为0xccdd,内容相同,新的对象retain为1,旧的对象没有变化;
retain到另一个nsstring之后,地址相同,内容相同,这个对象的retain+1,
也就是说,retain是指针拷贝,copy是内容拷贝;
retain的set方法是浅复制,copy的set方法是深复制;
13、assign与retain:
①. 接触过C,那么假设你用malloc分配了一块内存,并且把它的地址赋值给了指针a,后来你希望指针b也共享这块内存,于是你又把a赋值给(assign)了b。此时a和b指向同一块内存,请问当a不再需要这块内存,能否直接释放它?答案是否定的,因为a并不知道b是否还在使用这块内存,如果a释放了,那么b在使用这块内存的时候会引起程序crash掉。
②. 了解到1中assign的问题,那么如何解决?最简单的一个方法就是使用引用计数(reference counting),还是上面的那个例子,我们给那块内存设一个引用计数,当内存被分配并且赋值给a时,引用计数是1。当把a赋值给b时引用计数增加到2。这时如果a不再使用这块内存,它只需要把引用计数减1,表明自己不再拥有这块内存。b不再使用这块内存时也把引用计数减1。当引用计数变为0的时候,代表该内存不再被任何指针所引用,系统可以把它直接释放掉。
总结:上面两点其实就是assign和retain的区别,assign就是直接赋值,从而可能引起①中的问题,当数据为int, float等原生类型时,可以使用assign。retain就如②中所述,使用了引用计数,retain引起引用计数加1, release引起引用计数减1,当引用计数为0时,dealloc函数被调用,内存被回收。