本文授權轉載,作者:Martin_Joy(微博)
關於 NSString 的疑問
NSString *str = @"Joy"; NSLog(@"%lu",[str retainCount]); NSLog(@"地址:%p",str);
打印結果:
2016-06-15 10:22:17.084 OCTestProject[2592:327118] 計數:18446744073709551615 2016-06-15 10:22:17.085 OCTestProject[2592:327118] 地址:0x1045077d0
會發現引用計數是一個很大的值,為什麼?這是一個放在常量區的字符串常量,返回的結果是UINT_MAX值
關於 release 之後仍然為1的疑問
Student *stu = [[Student alloc] init]; NSLog(@"%lu",[stu retainCount]); [stu release]; NSLog(@"%lu",[stu retainCount]);
打印結果:
2016-06-15 12:07:50.608 OCTestProject[3437:361531] 1 2016-06-15 12:07:50.609 OCTestProject[3437:361531] 1
有人告訴我,是autoreleasepool的原因!!明確的說,和autoreleasepool完全沒關系。
向一個被回收的對象發送retaincount消息,輸出結果不確定,如果這塊內存被復用了,那麼這裡就會造成程序崩潰。最後一次release之後,系統知道這塊內存要進行回收了,但是只是進行一個標記,並不會將retaincount減去1,也沒必要這麼做了。直接標記,可以減少一次內存操作,加速對對象的回收,何樂而不為
什麼對象自動加入到 autoreleasepool中
雖然在程序入口,已經幫我們加上了 autoreleasepool,但是並不是說大括號內的所有
對象都會交給autoreleasepool來處理
第一種
當使用alloc/new/copy/mutableCopy開始的方法進行初始化時,會生成並持有對象(也就是不需要pool管理,系統會自動的幫他在合適位置release)。例如:
NSObject *stu = [[NSObject alloc] init];
那麼對於其他情況,例如
id obj = [NSMutableArray array];
這種情況會自動將返回值的對象注冊到autorealeasepool,代碼等效於:
@autorealsepool{ id __autorealeasing obj = [NSMutableArray array]; }
第二種
__weak修飾符只持有對象的弱引用,而在訪問引用對象的過程中,該對象可能被廢棄。那麼如果把對象注冊到autorealeasepool中,那麼在@autorealeasepool塊結束之前都能確保對象的存在。
id __weak obj1 = obj0; NSLog(@"class=%@",[obj1 class]);
對應的模擬源碼為
id __weak obj1 = obj0; id __autorealeasing tmp = obj1; NSLog(@"class=%@",[tmp class]);
第三種
id的指針或對象的指針在沒有顯式指定時會被附加上__autorealeasing修飾符
+ (nullable instancetype)stringWithContentsOfURL:(NSURL *)url encoding:(NSStringEncoding)enc error:(NSError **)error;
等價於
NSString *str = [NSString stringWithContentsOfURL: encoding: error:<#(NSError * _Nullable __autoreleasing * _Nullable)#>]