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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

Objective-C中的associated object释放时机问题

發布時間:2024/8/23 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Objective-C中的associated object释放时机问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

如果對象A持有對象B,B作為A的associated object,并且表面上B沒有其他被強引用的地方,那么對象A被釋放時,對象B一定會同時釋放嗎?大部分情況下是,但真有不是的時候。最近實現代碼的時候不小心就碰到了這樣的特殊情況。

需求

需要監聽對象A釋放(dealloc)并執行對象A的a方法。此時引入對象B,并作為對象A的associated object。A釋放時觸發B釋放,在B的dealloc方法中執行A的a方法。對象B需要一個指向對象A的屬性,并聲明為unsafe_unretained(或assign),因為weak指針此時已經失效了。

示例代碼

@interface MyObject1 : NSObject @end@implementation MyObject1 - (void)foo {NSLog(@"success"); } @end@interface MyObject2 : NSObject @property (nonatomic, unsafe_unretained) MyObject1 *obj1; @end@implementation MyObject2 - (void)dealloc {[self.obj1 foo]; } + (instancetype)create {return [[self class] new]; } @end@implementation ViewController + (void)load {[self fun1]; } + (void)fun1 {MyObject1 *mo1 = [MyObject1 new];@synchronized (self) {MyObject2 *mo2 = [MyObject2 create];mo2.obj1 = mo1;objc_setAssociatedObject(mo1, @selector(viewDidLoad), mo2, OBJC_ASSOCIATION_RETAIN_NONATOMIC);} } @end

問題

運行時出現崩潰,unsafe_unretained指針已經野了,和預期的不一樣。堆棧是這樣的:

觀察崩潰的堆棧,發現mo2對象是被自動釋放池釋放了。因為mo1對象是在函數退出時就立即釋放,這樣導致mo1比mo2先被銷毀,mo2訪問了無效指針導致了崩潰。

這個問題和@synchronized有關系,但目前我還不知道它和arc之間有什么聯系。下面給出另一個case,修改一行代碼就不會崩潰了:

+ (void)fun2 {MyObject1 *mo1 = [MyObject1 new];MyObject2 *mo2 = [MyObject2 create];@synchronized (self) {mo2.obj1 = mo1;objc_setAssociatedObject(mo1, @selector(viewDidLoad), mo2, OBJC_ASSOCIATION_RETAIN_NONATOMIC);} }

實際上只是把mo2的聲明移動到了@synchronized外面,堆棧變成了這樣:

這時,mo2的釋放發生在調用方法的結束時。

分析

使用Hooper查看匯編代碼,觀察fun1和fun2的不同。節選出關鍵部分:

核心在于:fun1中,創建mo2后調用了retain,fun2中,調用的則是objc_retainAutoreleasedReturnValue。

我們再來看看create方法:

關鍵的一行在最后,調用了objc_autoreleaseReturnValue。

關于objc_retainAutoreleasedReturnValue和objc_autoreleaseReturnValue,請移步?https://www.jianshu.com/p/2f05060fa377?。大意是,這兩個方法成對出現時,可以優化掉[[obj autorelease] retain]這種騷操作。

結論

在fun1中,由于沒有objc_retainAutoreleasedReturnValue,取而代之的是retain,導致對象被放入自動釋放池。對于@synchronized為什么會造成不同,我還沒有那么深入。

因為全局自動釋放池會延遲對象的釋放,如果代碼非常依賴對象的釋放時機則會比較危險。我認為這樣做是最保險的,創建一個局部自動釋放池,保證局部變量在函數結束時立即釋放:

+ (void)fun3 {MyObject1 *mo1 = [MyObject1 new];@autoreleasepool {@synchronized (self) {MyObject2 *mo2 = [MyObject2 create];mo2.obj1 = mo1;objc_setAssociatedObject(mo1, @selector(viewDidLoad), mo2, OBJC_ASSOCIATION_RETAIN_NONATOMIC);}} }


原文鏈接
本文為云棲社區原創內容,未經允許不得轉載。

總結

以上是生活随笔為你收集整理的Objective-C中的associated object释放时机问题的全部內容,希望文章能夠幫你解決所遇到的問題。

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