日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Objective C ARC 使用及原理

發布時間:2024/4/14 编程问答 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Objective C ARC 使用及原理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Objective C ARC 使用及原理

手把手教你ARC?,里面介紹了ARC的一些特性, 還有將非ARC工程轉換成ARC工程的方法

ARC 蘋果官方文檔

下面用我自己的話介紹一下ARC,并將看文檔過程中的疑問和答案寫下來。下面有些是翻譯,但不是全部,請一定要看一遍官方文檔

  • 不考慮 iOS4 的 ARC 規則

簡單地說,ARC在編譯時刻為代碼在合適的位置加上retain 和 release. 復雜點,它還提供其它一些功能,還為解決一些問題,添加了一些關鍵字和功能,后面會說。

ARC強制要求的新規則

  • 不可以調用dealloc, 不可以實現或者調用retain, release, retainCount, autorelease.
  • 不可以使用NSAllocateObject, NSDeallocateObject
  • 在C 結構體里不可以使用 Objective C 對象,比如下面是不允許的:

    struct A {NSString *string;};
  • id 和 void * 之間沒有自然的轉換

    id 指的是 Objective C 對象
    void * 指的是 C指針, CGColorRef這種東西
    id 和 void *之間賦值要添加 __bridge 系列關鍵字(后面說)

  • 不可以使用 NSAutoreleasePool 用 @autoreleasepool 替代

  • 不可以使用 memory zones (NSZone). (表示沒認真用過)
  • 不可以給屬性取new開頭的名字, 除非給它起個不是new開頭的getter. (原因不明)

    // Won't work@property NSString *newTitle;// words:@property (getter=theNewTitle) NSString *newTitle;

屬性聲明

引入了weak, strong, unsafe_unretained, 去掉了retain, 保留了assign 其余不變

  • strong 相當于 MRC(Manual Reference Counting) 的 retain
  • weak 相當于 MRC 的 assign 但是 在指向的對象被銷毀的時候,指針會被設置成0
  • assign 屬性 如果是Objective C 對象,在沒有特殊處理的時候,相當于strong

    下面代碼在 MRC 情況下是弱引用的

    @interface MyClass : Superclass {id thing; // Weak reference.}// ...@end@implementation MyClass- (id)thing {return thing;} - (void)setThing:(id)newThing {thing = newThing;}// ...@end

    但是在 ARC 情況下則不是 id thing; 被轉換成了 id __strong thing;
    所以要把上面代碼的 id thing; 改為 id __weak thing; 才接近原來assign的意思.

  • unsafe_unretained 和原來的 assign行為最像.

  • 對于手動寫 setter getter 又設置了修飾符的情況,我沒有研究

在這里我想到好多問題

  • 聲明了屬性@property (weak) NSString *member 對應的成員變量 NSString *_member (成員變量里沒有寫__weak)會怎樣

    答案是編譯出錯
  • 屬性@property (weak) NSString *member 和 成員變量 NSString *_member123 (成員變量里沒有寫__weak) @synthesize 在一起會怎樣

    答案是寫著的時候xcode就顯示出了錯誤
  • 其余問題可以從上面兩個問題和答案推導.

  • 變量修飾符

    下面的變量表示Objective C對象變量

    • __strong

      默認,變量在,對象在

    • __weak

      對象在,變量可以安全使用對象, 對象銷毀,變量被設置為nil

    • __unsafe_unretained

      對象在不在和變量無關, 變量在不在和對象無關,如果對象被銷毀了,還通過變量想使用對象,會崩潰,是不安全的。(意會)

    • __autorelease

      表示指向的對象是autorelease的, 例子如下

      In non-ARC Programming, the save function looks like this:- (BOOL)save:(NSError * __autoreleasing *)myError {*myError = [[[NSError alloc] initWith…] autorelease]}In ARC Programming, the save function looks like this:- (BOOL)save:(NSError * __autoreleasing *)myError {*myError = [[NSError alloc] initWith…];}

      ARC代碼

      NSError *error;BOOL OK = [myObject performOperationWithError:&error];

      被轉換成

      NSError * __strong error;NSError * __autoreleasing tmp = error;BOOL OK = [myObject performOperationWithError:&tmp];error = tmp;

      其實可以直接使用 NSError * __autoreleasing error; 來增加效率。

    ARC根據上面那些修飾符自動生成額外的代碼。

    對于 __strong

    NSNumber * __strong number = [NSNumber numberWithInt:13];

    將會被編譯成

    NSNumber * number = [[NSNumber numberWithInt:13] retain]; …… // 在 number 所在的定義域外, 或者 number = nil 的時候。 [number release];

    __weak 后面再說

    __unsafe_unretained 應該是什么都不干 (猜測)

    對于 __autorelease

    NSNumber * __autorelease number = [[NSNumber alloc] initWithInt:13];

    將會被編譯成

    NSNumber * number = [[[NSNumber alloc] initWithInt:13] autorelease];

    修飾符還可以告訴編譯器代碼的行為

    例如

    NSError * __autoreleasing tmp = error; BOOL OK = [myObject performOperationWithError:&tmp];

    myObject 的 performOperationWithError 使用的可能是 MRC 的代碼, 也可能是 ARC的代碼, 但它參數返回的肯定是一個autorelease的對象。 有了 __autoreleasing 修飾, 編譯器可以知道從 performOperationWithError 方法獲得 tmp 后不需要處理它的內存問題。

    __weak 的實現

    __weak 指針在對象被銷毀的時候會被設置成 nil, 這個功能很好很強大, 避免了很多問題, 但看上去不是在某處插入個 [obj release]; obj = nil; 就可以實現了的。

    具體實現在?How does the ARC's zeroing weak pointer behavior implemented?有說。

    這里簡單介紹一下:

    ARC 的 NSObject 里大概添加了一個 weak 指針的數組,當對象銷毀的時候,把數組里的變量都設置為 nil (表述不嚴謹,大概就是這個意思)

    防止循環引用和長時間過程中被銷毀(下面可能存在誤導,要批判地看!)

    在 MRC 中 __block id x = y; block 將不會 [x retain]; 在block執行完之后也不會 [x release];

    在 ARC 中 __block id x = y; 應該等于 __strong __block id x = y; 這樣會有一個retain的過程,在block被銷毀的時候 [x release]。

    從上面可以知道使用 __block id x = y; 而x如果擁有block的copy, 不進行處理會造成循環引用。

    于是 apple 告訴我們可以這樣寫:

    MyViewController * __block myController = [[MyViewController alloc] init…]; // ... myController.completionHandler = ^(NSInteger result) {[myController dismissViewControllerAnimated:YES completion:nil];myController = nil; };

    但對于多次調用的情況,上面無法達到目的??梢杂?weak 關鍵字來替代?block (注意是替代,不是合在一起用,我對合在一起用沒研究)

    MyViewController *myController = [[MyViewController alloc] init…]; // ... MyViewController * __weak weakMyViewController = myController;myController.completionHandler = ^(NSInteger result) {[weakMyViewController dismissViewControllerAnimated:YES completion:nil]; };

    上面還是會造成問題, 如果block的代碼會執行很長時間, 在那段時間 weakMyViewController 被銷毀了, 那么它就變成了 nil. 程序不是崩潰就是得到錯誤的結果, 這樣是不行的,apple 也提供了解決方法

    MyViewController *myController = [[MyViewController alloc] init…]; // ... MyViewController * __weak weakMyController = myController; myController.completionHandler = ^(NSInteger result) {MyViewController *strongMyController = weakMyController;if (strongMyController) {// ...[strongMyController dismissViewControllerAnimated:YES completion:nil];// ...}else {// Probably nothing...} };

    到此表面問題基本解決。

    一個古怪的行為

    有代碼如下:

    @interface AA : NSObject @property (strong) NSString *string; @end@implementation AA - (void)dealloc {NSLog(@"%@ dealloc", self.string); } @end- (void)testArcSimple {AA * __strong aa_weak_holder = [[AA alloc] init];AA * __weak aa_weak = aa_weak_holder;aa_weak_holder.string = @"aa_weak";void (^aBlock)(void) = ^(){NSLog(@"block : %@", aa_weak.string);};aa_weak_holder = nil;aBlock(); }

    上面的輸出是

    block : aa_weak aa_weak dealloc // 這個log出現在一個runloop的最后

    而下面這段代碼:

    AA * __strong aa_weak_holder = [[AA alloc] init]; aa_weak_holder.string = @"weak"; AA * __weak aa_weak = aa_weak_holder; aa_weak_holder = nil; NSLog(@"aa : %@", aa_weak);

    輸出為

    weak dealloc aa : (null)

    猜測是 aa_weak 在

    void (^aBlock)(void) = ^(){NSLog(@"block : %@", aa_weak.string);};

    的位置 [[aa_weak retain] autorelease] 了一遍。表示不懂。

    Toll-Free Bridging

    • __bridge : Objective-C 和 Core Foundation 之間的轉換, 擁有權不變。
    • __bridge_retained : 從 Objective-C 到 Core Foundation 的轉換,由程序員負責把得到的 CFxxxRef 銷毀
    • __bridge_transfer : 從 Core Foundation 到 Objective-C 的轉換,由ARC負責把得到的 id 銷毀

    __bridge_retained 的作用等于 CFBridgingRetain
    __bridge_transfer 的作用等于 CFBridgingRelease

    Cocoa 方法返回的 CF 對象

    比如 [[UIColor greenColor] CGColor]; 編譯器知道返回的 CFxxxRef 是不是需要 release 的, 當需要把它在此轉換成 Cocoa 對象的時候, 不必用 __bridge __bridge_transfer 這樣的修飾符, 但需要顯式寫出要轉換成的類型, 比如:

    UIColor *color = (id)[UIColor greenColor].CGColor; // 雖然這樣比較無聊。?

    ?

    ****************

    來自楊先生的分享...

    ****************

    posted on 2015-08-11 21:12 yanshanLove 閱讀(...) 評論(...) 編輯 收藏

    轉載于:https://www.cnblogs.com/Lxiaolong/p/4722351.html

    超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生

    總結

    以上是生活随笔為你收集整理的Objective C ARC 使用及原理的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。