亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > iOS > 正文

Objective-C學習之ARC的實現方法

2020-07-26 02:35:51
字體:
來源:轉載
供稿:網友

前言

在ARC出現以前,程序員們只能靠retain/relese/autorelease來確保對象們恰好“堅持”到被需要的那一刻。如果忘了retain,或者多次release某個對象,程序就會發生內存泄漏的問題,甚至直接崩潰。

在Xcode 4.2中,除了語法檢查外,Apple的新LLVM編譯器還將內存管理的苦差事接了過來,它會檢查代碼,決定何時釋放對象。Apple的文檔里是這么定義ARC的:

“自動引用計數(ARC)是一個編譯器級的功能,它能簡化Cocoa應用中對象生命周期管理(內存管理)的流程?!?/p>

ARC使內存管理在大部分時候變得如同小事一樁,但我們仍要在決定自己的類如何管理其它對象的引用時承擔一些責任。

蘋果的官方說明中稱,ARC是“由編譯器進行內存管理”的,但是實際上只有編譯其是無法完全勝任的,再次基礎上還需要Objective-C運行時庫的協助。

也就是說,ARC由以下工具、庫來實現。

  • clang(LLVM編輯器)
  • objc4 Objective-C 運行時庫

__strong 修飾符

{ id __strong obj = [[NSObject alloc] init];}

~~本人是c/cpp小白,沒有編譯成功,沒看到匯編輸出TAT~~

以上代碼編譯器的模擬代碼:

/** 編譯器的模擬代碼 */id obj = objc_msgSend(NSObject, @selector(alloc));objc_msgSend(obj,@selector(init));objc_release(obj);

如上所示,調用了2次objc_msgSend方法,變量的作用域結束時通過objc_release釋放對象。雖然ARC有效時不能使用release方法,但由此可知編譯器自動插入了release。

使用alloc/new/copy/mutableCopy以外的方法時:

{ id __strong obj = [NSMutableArray array];}

編譯器的模擬代碼如下:

/** 編譯器的模擬代碼 */id obj = objc_msgSend(NSMutableArray,@selector(array));objc_retainAutoreleasedReturnValue(obj);objc_release(obj);

其中的objc_retainAutoreleasedReturnValue函數主要用于優化程序運行,它用于自己持有(retain)對象的函數,但它持有的對象應為返回注冊在autoreleasepool中對象的方法,或是函數的返回值。在調用alloc/new/copy/mutableCopy以外的方法,由編譯器插入該函數。

與 objc_retainAutoreleaseReturnValue函數相對的函數為objc_autoreleaseReturnValue函數。它用于alloc/new/copy/mutableCopy方法以外的NSMutableArray類的array類方法等返回對象的實現上。

+ (id) array{ return [[NSArray alloc] init];}

轉換后

+ (id) array{ id obj = objc_msgSend(NSArray,@selector(alloc)); objc_msgSend(obj,@selector(init)); return objc_autoreleaseReturnValue(obj);}

返回注冊到autoreleasepool中對象的方法使用了objc_autoreleaseReturValue函數返回注冊到autoreleasepool中的對象。但是objc_autoreleaseReturValue函數同objc_autorelease函數不同,一般不僅限于注冊對象到autoreleasepool中。

objc_autoreleaseReturValue函數會檢查使用該函數的方法或函數調用方的執行命令列表。如果方法或函數的調用方在調用了方法或函數后緊接著調用objc_retainAutoreleasedReturnValue()函數,那么就不將返回的對象注冊到autoreleasepool中,而直接傳遞到方法或函數的調用方。objc_retainAutoreleasedReturnValue函數與objc_retain函數不同,它即便不注冊到autoreleasepool中而返回對象,也能夠正確地獲取對象。

通過objc_autoreleaseReturnValue函數和objc_retainAutoreleasedReturnValue函數的協作,可以不講對象注冊到autoreleasepool中而直接傳遞,這一過程達到了最優化。

__weak 修飾符

  • 若附有__weak修飾符的變量所引用的對象被廢棄,則將nil賦值給該變量。
  • 使用附有__weak修飾符的變量,即是使用注冊到了autoreleasepool中的對象。
{ id __weak obj1 = obj;}
/** 編譯器的模擬代碼 */id obj1;objc_initWeak(&obj1,obj);objc_destroyWeak(&obj1);

通過objc_initWeak函數初始化附有__weak修飾符的變量,在變量作用域結束時通過objc_destroyWeak函數釋放該變量。
如以下源碼所示,objc_initWeak函數將附有__weak修飾符的變量初始化為0后,會將賦值的對象作為參數調用objc_storeWeak函數。

obj1 = 0;objc_storeWeak(&obj1,obj);

objc_destroyWeak函數將0作為參數調用objc_storeWeak函數。

objc_storeWeak(&obj1,0);

即前面的源代碼和以下代碼相同:

id obj1;obj1 = 0;objc_storeWeak(&obj1,obj);objc_storeWeak(&obj1,0);

objc_weakStore函數把第二參數的復制對象的地址作為鍵值,將第一參數的附有__weak修飾符的變量的地址注冊到weak表中,如果第二參數為0,則把變量的地址從weak表中刪除。

weak表與引用計數表相同,作為散列表被實現。如果使用weak表,將廢棄對象的地址作為鍵值進行檢索,能高速地獲取對應的附有__weak修飾符的變量的地址。另外,由于一個對象可以同時賦值給多個附有__weak修飾符的變量中,所以對于一個鍵值,可注冊多個變量的地址。

釋放對象時,廢棄誰都不持有的對象,通過objc_release函數釋放。

  • objc_release
  • 因為計數為0,所以執行dealloc
  • _objc_rootDealloc
  • object_dispose
  • objc_destructInstanse
  • objc_clear_deallocating

對象被廢棄時最后調用的objc_clear_deallocating函數動作如下:

  • 從weak表中獲取廢棄對象的地址為鍵值的記錄。
  • 將包含在記錄中的所有附有__weak修飾符變量的地址,賦值為nil
  • 從weak表中刪除該記錄。
  • 從引用計數表中刪除廢棄對象的地址作為鍵值的記錄。

根據以上步驟,前面說的如果附有__weak修飾符的變量所引用的對象被廢棄,則將nil賦值給該變量這一功能即被實現。由此可知,如果大量使用附有__weak修飾符的變量,則會消耗相應的CPU資源,對此只在需要避免循環引用的時候使用__weak修飾符。

使用__weak修飾符時,以下代碼會引起編譯器警告

{ id __weak obj = [[NSObject alloc] init]; NSLog(@"obj = %@",obj);}

編譯結果如下:

Assigning retained object to weak variable; object will be released after assignment

編譯器模擬代碼如下:

id obj;id temp = objc_msgSend(NSObject,@selector(alloc));objc_msgSend(temp,@selector(init));objc_initWeak(&obj,temp);objc_release(temp);objc_destroyWeak(&obj);

運行結果如下:

2017-12-07 19:37:24.075939+0800 ImageOrientation[10963:3581164] obj = (null)

使用附有__weak修飾符的變量,即是使用注冊到autoreleasepool中的對象。

{ id __weak obj1 = obj; NSLog(@"%@",obj1);}

該代碼可以轉換為如下形式:

/** 編譯器模擬代碼*/id obj1;objc_initWeak(&obj1,obj);id temp = objc_loadWeakRetained(&obj1);objc_autorelease(temp);NSLog(@"%@",obj1);objc_destroyWeak(&obj1);

與賦值時相比,在使用附有__weak修飾符變量的情形下,增加了對objc_loadWeakRetained函數和objc_autorelease函數的調用。這些函數的動作如下:

  • objc_loadWeakRetained函數取出附有__weak修飾符變量所引用的對象并retain
  • objc_autorelease函數將對象注冊到autoreleasepool中。

__autoreleasing 修飾符

將對象賦值給附有__autoreleasing修飾符的變量等同于MRC時調用對象的autorelease方法。

@autoreleasepool{ id __autoreleasing obj = [[NSObject alloc] init];}

模擬代碼如下:

/** 編譯器的模擬代碼 */id pool = objc_autoreleasePoolPush();id obj = objc_msgSend(NSObject,@selector(alloc));objc_msgSend(obj,@selector(init));objc_autoreleas(obj);objc_autoreleasePoolPop(pool);

alloc/new/copy/mutableCopy之外的方法實現:

@autoreleasepool{ id __autoreleasing obj = [NSMutableArray array];}
/** 編譯器的模擬代碼 */id pool = objc_autoreleasePoolPush();id obj = objc_msgSend(NSMutableArray,@selector(array));objc_retainAutorelesedReturnedValue(obj);objc_autorelease(obj);objc_autoreleasePoolPop(pool);

引用計數

獲取引用計數的函數為CFGetRetainCount

例如:

{ id __strong obj = [[NSObject alloc] init]; NSLog(@"retainCount = %ld",CFGetRetainCount((__bridge CFTypeRef)obj));}

結果為1

{ id __strong obj = [[NSObject alloc] init]; id __weak obj1 = obj; NSLog(@"retainCount = %ld",CFGetRetainCount((__bridge CFTypeRef)obj));}

結果為2

{ id __strong obj = [[NSObject alloc] init]; id __autoreleaing obj1 = obj; NSLog(@"retainCount = %ld",CFGetRetainCount((__bridge CFTypeRef)obj));}

結果為2

{ id __strong obj = [[NSObject alloc] init]; @autoreleasepool{  id __autoreleaing obj1 = obj;  NSLog(@"retainCount = %ld",CFGetRetainCount((__bridge CFTypeRef)obj));} } NSLog(@"retainCount = %ld",CFGetRetainCount((__bridge CFTypeRef)obj));}

結果為2和1

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對武林網的支持。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美亚洲午夜视频在线观看| 国产日本欧美在线观看| 亚洲bt天天射| 久久久久久久爱| 欧美成人国产va精品日本一级| 亚洲女人初尝黑人巨大| 亚洲精品日韩激情在线电影| 国产成人啪精品视频免费网| 日韩成人中文电影| 亚洲精品国产精品自产a区红杏吧| 久久久久久久久久国产| 国产婷婷成人久久av免费高清| 69av在线播放| 国产精品尤物福利片在线观看| 国产精品热视频| 777777777亚洲妇女| 亚洲精品日韩在线| 韩国三级电影久久久久久| 91久久精品日日躁夜夜躁国产| 亚洲最大av网站| 伊人久久大香线蕉av一区二区| 97久久精品人搡人人玩| 亚洲人成在线电影| 夜夜嗨av色一区二区不卡| 亚洲欧洲在线视频| 国产精品旅馆在线| 茄子视频成人在线| 亚洲国产中文字幕在线观看| 亚洲精品999| 狠狠躁天天躁日日躁欧美| 岛国av一区二区在线在线观看| 91po在线观看91精品国产性色| 超薄丝袜一区二区| 亚洲欧美在线看| 国产精品久久久久久久久久东京| 日韩欧美国产免费播放| 国产91色在线免费| 国产精彩精品视频| 欧美乱大交xxxxx另类电影| 日韩在线小视频| 国产97在线亚洲| 国产日韩综合一区二区性色av| 欧美日韩免费区域视频在线观看| 中文字幕欧美精品在线| 国产精品美女在线| 欧美精品在线免费| 91视频九色网站| 久久国产精品亚洲| 久久综合九色九九| 亚洲国产精品资源| 欧美丰满少妇xxxxx做受| 欧美最顶级的aⅴ艳星| 97在线免费观看视频| 日韩欧美亚洲范冰冰与中字| 亚洲国产天堂网精品网站| 久久免费高清视频| 国产成人福利夜色影视| 亚洲人成在线观看网站高清| 中文字幕亚洲字幕| 久久全球大尺度高清视频| 伊是香蕉大人久久| 91成人在线视频| 日韩一二三在线视频播| 亚洲综合精品一区二区| 国产免费一区视频观看免费| 久久午夜a级毛片| 8x海外华人永久免费日韩内陆视频| 欧美日韩中国免费专区在线看| 91在线无精精品一区二区| 中日韩美女免费视频网站在线观看| 午夜精品免费视频| 欧美日韩国产页| 在线亚洲国产精品网| 久久亚洲国产精品| 欧美网站在线观看| 中文字幕av日韩| 91精品国产自产在线老师啪| 成人两性免费视频| 91在线视频九色| 亚洲精品视频中文字幕| 国产精品综合久久久| 国产亚洲免费的视频看| 成人a视频在线观看| 欧美在线观看网站| 日韩av电影手机在线| 亚洲japanese制服美女| 国产精品丝袜高跟| 不卡av在线播放| 国产亚洲aⅴaaaaaa毛片| 国产香蕉精品视频一区二区三区| 国产视频久久久久久久| 国产精品美女久久久久av超清| 国产99久久精品一区二区永久免费| 日韩精品视频在线播放| 亚洲欧美激情精品一区二区| 国产ts一区二区| 国产mv免费观看入口亚洲| 国产精品电影久久久久电影网| 91精品久久久久久久久中文字幕| 91欧美精品成人综合在线观看| 亚洲一区二区三区乱码aⅴ蜜桃女| 久久国产精品影视| 九九九热精品免费视频观看网站| 国产一区二区三区日韩欧美| 成人欧美一区二区三区在线| 国产精品久久国产精品99gif| 欧美美女18p| 久久久久久久亚洲精品| 国产精品国产福利国产秒拍| 国产精品三级在线| 亚洲色图综合久久| 亚洲性av在线| 夜夜狂射影院欧美极品| 精品无码久久久久久国产| 日本中文字幕久久看| 国产成人午夜视频网址| 亚洲理论片在线观看| 国产日韩欧美电影在线观看| 国产午夜精品全部视频播放| 欧美xxxx14xxxxx性爽| 久久九九亚洲综合| 97在线精品视频| 欧美一级在线播放| 国内成人精品一区| 亚洲自拍偷拍网址| 97av在线影院| 国产精品美女免费视频| 亚洲人精品午夜在线观看| 成人国产精品久久久久久亚洲| 欧美在线视频免费| 国产91色在线|| 欧美激情va永久在线播放| www.亚洲一二| 国产一区深夜福利| 精品久久在线播放| 国产精品私拍pans大尺度在线| 精品国产依人香蕉在线精品| 亚洲精品久久视频| 亚洲黄色av女优在线观看| 91精品视频在线| 国产精品高潮呻吟久久av无限| 国产精品无av码在线观看| 日本电影亚洲天堂| 欧美日韩亚洲视频一区| 91在线免费网站| 69视频在线免费观看| 久久久久久网站| 大桥未久av一区二区三区| 92版电视剧仙鹤神针在线观看| 日韩av在线天堂网| 国产精品久久久久久久久久99| 国外日韩电影在线观看| 久久99久久99精品免观看粉嫩| 欧美成人精品在线观看| 伦理中文字幕亚洲| 欧美成人精品在线播放| 日本19禁啪啪免费观看www| 久久久久日韩精品久久久男男| 国产精品美女www| 欧美成人精品一区| 亚洲成人免费在线视频| 亚洲自拍偷拍视频| 日韩av电影在线播放| 久久中国妇女中文字幕|