oc採用引用計數器對記憶體進行管理,當乙個物件的引用計數(retaincount)為0,則被釋放。
objective c的引用計數理解起來很容易,當乙個物件被持有的時候計數加一,不再被持有的時候引用計數減一,當引用計數為零的時候,說明這個物件已經無用了,則將其釋放。
oc的記憶體機制可以簡單概括為:誰持有(retain)誰釋放(release)。retain引用計數+1,release反之。
採用引用計數的方式來管理記憶體,分mrc(手動引用計數)和arc(自動引用計數)兩種,其中arc是基於mrc的.
在mrc中, 每當我們使用alloc,new,retain,copy使物件的引用計數增加,都要對應的使用release或者autorelease來使物件的引用計數減少,增加和減少的次數要相等.
記憶體管理的思考方式:
自己生成的物件,自己持有
非自己生成的物件,自己也能持有
不再需要自己持有物件時釋放
非自己持有的物件無法釋放
(1) 自己生成的物件,自己持有
在ios記憶體管理中有四個關鍵字,alloc、new、copy、mutablecopy,自身使用這些關鍵字產生物件,那麼自身就持有了物件
// 使用了alloc分配了記憶體,obj指向了物件,該物件本身引用計數為1,不需要retain
id obj =[[
nsobject alloc]
init];
// 使用了new分配了記憶體,objc指向了物件,該物件本身引用計數為1,不需要retain
id obj =
[nsobject
new]
;
(2) 非自己生成的物件,自己也能持有
// nsmutablearray通過類方法array產生了物件(並沒有使用alloc、new、copy、mutablecopt來產生物件),因此該物件不屬於obj自身產生的
// 因此,需要使用retain方法讓物件計數器+1,從而obj可以持有該物件(儘管該物件不是他產生的)
id obj =
[nsmutablearray array]
;[obj retain]
;
(3) 不再需要自己持有物件時釋放
id obj =
[nsmutablearray array]
;[obj retain]
;// 當obj不在需要持有的物件,那麼,obj應該傳送release訊息
[obj release]
;
(4) 無法釋放非自己持有的物件
// 1. 釋放乙個已經釋放的物件
id obj =[[
nsobject alloc]
init];
// 釋放物件
[obj release]
;// 釋放了物件還進行釋放
[obj release]
;// 應用程式崩潰
//2. 釋放乙個不屬於自己的物件
id obj1 =
[obj object]
;//取得的物件存在,但自己不持有物件
// obj1沒有進行retain操作而進行release操作,使得obj持有物件釋放,造成了野指標錯誤
[obj1 release]
;
在objective c中,有三種型別是arc適用的:
1.block
2.objective 物件,id, class, nserror*等
3.由attribute((nsobject))標記的型別。
像double* ,cfstringref等不是arc適用的,仍然需要手動管理記憶體。
以cf開頭的(core foundation)的物件往往需要手動管理記憶體。
簡單說,強引用持有物件,而弱引用不持有物件。
具體看**?
__strong nsobject
*obj1=[[
nsobject alloc]
init];
__strong nsobject
*obj2=obj1;
nslog
(@"%@,%@"
,obj1,obj2)
;
obj1=
nil;
nslog
(@"%@,%@"
,obj1,obj2)
;//輸出 :
//,//(null),
將obj2宣告改為__weak
__strong nsobject
*obj1=[[
nsobject alloc]
init];
__weak nsobject
*obj2=obj1;
nslog
(@"%@,%@"
,obj1,obj2)
;
obj1=
nil;
nslog
(@"%@,%@"
,obj1,obj2)
;//輸出 :
//,//(null),(null)
因為strong會使retaincount+1,所以第一部分**retaincount是2,obj1置為nil之後retaincount-1,所以retaincount還剩1,因此不影響obj2;
而weak不會retaincount+1,所以整個**段的retaincount一直是1,因此obj置為nil之後retaincount-1,所以retaincount為0,記憶體也跟著釋放了,因此obj2也為空。
(這裡提下weak和mrc時代的assign的區別,兩者都可以用於弱引用,但是記憶體釋放後使用weak會將物件置nil,而assign不會,會造成野指標,現在assign一般只用在基礎型別))
平時一般都是用strong,在造成迴圈引用的時候才會使用weak
當兩個不同的物件各有乙個強引用指向對方時就造成迴圈引用,會導致物件無法釋放,例如我們常用的delegate,見圖:
這就是我們在申明delegate時都是用weak的原因(mrc的話是用assign)
@property (nonatomic,
weak
) id<
delegate
>delegate
block的使用也會照成迴圈引用,比如當乙個物件持有block,而該block又持有該物件時,類似下面的偽**會照成迴圈引用:
[
self block:^]
;
應該改為
__weak typeof
(self
) weakself=
self;[
self block:^]
;
注意:只有該物件持有block,而block裡的**塊又持有該物件時才需要用到weak。:只有該物件持有block,而block裡的**塊又持有該物件時才需要用到weak。
[
uiview animatewithduration:
0.2 animations:^]
;
這種就不會造成迴圈引用。
luhh
2019秋招iOS再戰
先說下我的情況吧,樓主所在的是一所普通的雙非一本學校,也只是普通的本科 在研究生林立的網際網路行業是辣麼的渺小 也是在春招的時候找到了現在的實習公司 哈囉出行。然後也是大概從8月開始進行的乙個提前批簡歷的投遞,然後到現在也就只面了2家,一家是網易,一家是位元組跳動,但是可惜的是一面都沒過,所以在這裡...
秋招材料整理 深度學習基礎
共享隱層,多個任務並行訓練並共享不同任務已學到的特徵表示 1 交替訓練 不同任務,不同的資料集,一次優化一層,每層都有乙個loss,乙個optimiser 2 聯合訓練 不同任務,相同的資料集,一次優化一層,每層都有乙個loss,loss相加,一共乙個optimiser 1 sigmoid y z ...
C C 秋 春招技術崗面試基礎 深淺拷貝
c 的拷貝方式 介紹了深淺拷貝的區別 先看一下下面的 c vc6.0 乙個person類,乙個建構函式 乙個析構函式 乙個char 成員變數,乙個 int成員變數。建構函式 len是字串的長度,然後為指標p分配記憶體空間,長度為len 1,1是為了字串末尾的 0,然後strcpy進行字串拷貝 析構函...