【iOS开发-34】自己主动释放池@autoreleasepool的使用注意事项以及ARC机制——面试必考内容
自己主动释放池@autorelease面试频率可能会吧release还要高。
(1)在自己主动释放池@autoreleasepool{}中alloc一个对象后(如p1)。仍然须要用[p1 autorelease];不过这个语句和[p1 release];不同。后者表示把p1的retainCount-1,而前者只表示把p1放到自己主动释放池中返回一个self,自己主动释放池结束销毁时,统一对里面的对象引用计数retainCount-1。
(2)@autoreleasepool{}能够任意创建。也能够嵌套使用。
(3)无论这个对象是在自己主动释放池内还是外创建的,仅仅要在自己主动释放池内写一个[p1 autorelease];p1就会被放到自己主动释放池中。
注意autorelease是一个方法。且仅仅有在自己主动释放池中使用才有效。
(4)假设把一个对象反复加到自己主动释放池如[p1 autorelease];[p1 autorelease];。那么会出错。原因是:载入几次。届时自己主动释放池就会用[p1 release];释放几次,可是因为这两个载入的对象事实上是一个对象相同地址,所以第一次自己主动释放正确,第二次自己主动释放时发现已经被释放了。所以p1就变成了野指针。
(5)下面是自己主动释放池嵌套的使用规则和注意点。
#import <Foundation/Foundation.h> #import "Person.h" int main(int argc, const char * argv[]) { Person *p1=[[Person alloc]init]; @autoreleasepool { @autoreleasepool { [p1 autorelease]; }//在运行到此处时,p1被自己主动释放 } //下面代码有错误 @autoreleasepool { [p1 autorelease];//此时p1被增加进来 @autoreleasepool { [p1 autorelease];//被反复载入进来。但仍然同一个 }//此处,p1被自己主动释放了。所以第一次加进来的那个也被释放了。由于是同一个对象 }//所以此处在调用[p1 release];时就出现报错:野指针 return 0; }
(6)@autoreleasepool的应用:假设须要在方法中创建对象。并把这个对象作为返回值,那么能够在这种方法中使用[*** autorelease];把它增加到自己主动释放池中。否则。直接用[*** release];来匹配alloc的话,在该方法中就已经把这个对象alloc和release了一遍相当于释放了。那么所谓的返回对象返回的时一个野指针(没有指向不论什么对象)。当然。调用这种方法的代码页须要写在自己主动释放池作用域内才生效。
(7)接上面。返回对象的那个方法中,创建对象不建议直接用类名,而是用self。否则假设存在子类调用会崩溃。
如Car *car1=[[self alloc]init];
(8)事实上诸如NSString *str1=[NSString stringWithFormat:@"%@",@"hello"];也是调用了一个方法,而且返回了一个字符串对象。
比照(6)和(7)我们得知这个stringWithFormat应该也是顺便返回了一个autorelease。
(9)在ARC机制中。我们用@property声明的成员变量,建议用strong取代之前手动管理内存时的retain。尽管后者仍然能够使用。由于我们在ARC中内存管理就是看是否有强指针指向对象,如有就不回收。如没有就回收。
所以强指针是strong,相反是weak。而基本数据类型我们还是习惯用assign。
(10)尽管Xcode提供了非ARC转换成ARC的,非常少有把整个非ARC转换成ARC的。假设我们导入第三方库时。须要非ARC和ARC共存。即我们系统默认是ARC。我们须要让系统不要去管这个非ARC的第三方库,例如以下设置:双击响应的.m文件。输入-fno-objc-arc回车就可以。
(11)顺便。当出现两个类循环引用的话(也就是A要包括B。B要包括A。即A对象要作为B的变量,B对象要作为A的变量),仅仅须要把一方的strong改成weak。而且在响应的.h文件里把#import ".h"改成Class ***。
假设由于改成Class ***而无法使用那个类的方法的话,仅仅须要在它的.m文件里#import“.h”文件就可以,这个由于不是在.h文件里导入所以不冲突。