最近做项目发现经常有一些疑惑,发现一些天天写的代码理解的不是很清楚,于是准备对一些问题进行彻底的总结、深究,以此夯实基础!记录在案。
1.@property 的介绍:
- 与@synthesize配对使用,不过后来@synthesize 也省去了。
- @synthesize则是用来生成对应声明方法的实现。现在推荐省去,编译器会自动帮你加上getter 和 setter 方法的实现,并且默认会去访问_age这个成员变量,如果找不到_age这个成员变量,会自动生成一个叫做 _age的私有成员变量。
2.atomic与nonatomic
- atomic的意思就是setter/getter这个函数是一个原子操作。如果有多个线程同时调用setter的话,不会出现某一个线程执行setter全部语句之前,另一个线程开始执行setter情况,相当于函数头尾加了锁一样。
- nonatomic不保证setter/getter的原子性,所以你可能会取到不完整的东西。 比如setter函数里面改变两个成员变量,如果你用nonatomic的话,getter可能会取到只更改了其中一个变量时候的状态,这样取到的东西会有问题。
- atomic:默认是atomic,这个属性是为了保证程序在多线程情况,编译器会自动生成一些互斥加锁代码,避免该变量的读写不同步问题。
- nonatomic:如果该对象无需考虑多线程的情况,请加入这个属性,这样会让编译器少生成一些互斥加锁代码,可以提高效率。另外由于不涉及锁操作,所以它执行相对快点。
- copy
复制内容(深复制)。如果调用copy的是数组,则为指针复制(浅复制),仅仅复制子元素的指针。
@property (nonatomic,copy)NSString *title;
@property (nonatomic, copy) NSMutableArray *myArray;//not recommended
@property (nonatomic, copy) SomeBlockType someBlock;
3.使用规则
assign: 对基本数据类型(NSInteger,CGFloat)和C数据类型(int, float, double, char, 等等)
copy: 对NSString block
retain:对其他NSObject及其子类
weak: 对NSObject对象 、delegate 。修饰的对象在释放之后,指针地址会被置为nil。弱引用
4.区别
4.1 assign与weak区别
- assign适用于基本数据类型,weak是适用于NSObject对象,并且是一个弱引用。
- assign其实也可以用来修饰对象。那么我们为什么不用它修饰对象呢?因为被assign修饰的对象(一般编译的时候会产生警告:Assigning retained object to unsafe property; object will be released after assignment)在释放之后,指针的地址还是存在的,也就是说指针并没有被置为nil,造成野指针。对象一般分配在堆上的某块内存,如果在后续的内存分配中,刚好分到了这块地址,程序就会崩溃掉。
- 那为什么可以用assign修饰基本数据类型?因为基础数据类型一般分配在栈上,栈的内存会由系统自己自动处理,不会造成野指针。
weak修饰的对象在释放之后,指针地址会被置为nil。所以一般弱引用就是用weak。weak使用场景:
- 在ARC中,在有可能出现循环引用的时,往往要让其中一端使用weak来解决,比如: delegate。
- 自身已经对它进行一次强引用,没有必要再强引用一次时也会使用weak。比如:自定义 IBOutlet控件属性一般也使用weak,当然也可以使用strong。
4.2 strong 与copy的区别
strong 与copy都会使引用计数加1,但strong是两个指针指向同一个内存地址,copy会在内存里拷贝一份对象,两个指针指向不同的内存地址。
- 4.3 copy与retain:
- copy其实是建立了一个相同的对象,而retain不是;
- copy是内容拷贝,retain是指针拷贝;
- copy是内容的拷贝 ,对于像NSString,的确是这样;但copy的是一个NSArray 时,只是copy了指向array中相对应元素的指针,这便是所谓的"浅复制”。
4.4 __block与__weak的区别
- __block是用来修饰一个变量,这个变量就可以在block中被修改;__block:使用 __block修饰的变量在block代码块中会被retain(ARC下会retain,MRC下不会retain);
- __weak:使用__weak修饰的变量不会在block代码块中被retain;
- 在ARC下,要避免block出现循环引用 __weak typedof(self)weakSelf = self;
5. block变量定义时为什么用copy?block是放在哪里的?
- block本身是像对象一样可以retain,和release。但是,block在创建的时候,它的内存是分配在栈(stack)上,可能被随时回收,而不是在堆(heap)上。他本身的作于域是属于创建时候的作用域,一旦在创建时候的作用域外面调用block将导致程序崩溃。通过copy可以把block拷贝(copy)到堆,保证block的声明域外使用。
特别注意:在把block放到集合类当中去的时候,如果直接把生成的block放入到集合类中,是无法在其他地方使用block,必须要对block进行copy。
[array addObject:[[^{
NSLog(@"hello!");
} copy] autorelease]];
6.为什么建议UI控件一般使用weak?
首先我们从controller来看,controller是被系统用强指针引用着,所以如果 controller 还存在,里面的子控件也会存在,那么controller 强引用着它的view(从 controller 中它的 view 的属性是 retain 看出来的,retain 就是 MRC 年代的强引用),那么 view 又强引用着它的数组对象subviews,数组对象又引用着它所包含的数组内容,所以当我们创建出来一个UI控件并将其加入到subviews的时候,它就会被一个强指针所引用着,我们可以简化一下这个过程:--> Controller --> View --> Subviews(数组) --> 数组内容(添加到其中的UI控件)
- dealloc 可以做哪些操作
移除观察者observers
注销通知notification
设置非weak的delegate为nil 取消timer
参考与感谢:
http://www.jianshu.com/p/3e0f12e5faaa