-
(void
)viewdidload
nslog
(@"2222 %@"
,strong_animal)
;//2222
nslog
(@"2222 %@"
,weak_animal)
;//2222 (null)
nslog
(@"2222 %@"
,unsafe_animal)
;//crash
}
如果用__unsafe_unretained
,當物件釋放後,在訪問指標會crash。
如果用__weak
,當物件釋放後,再訪問weak_animal
指標為nil
。
我們來看看物件釋放時發生了什麼?
還會發現
void objc_object::
sidetable_cleardeallocating()
table.refcnts.
erase
(it);}
table.
unlock()
;}||
void
weak_clear_no_lock
(weak_table_t *weak_table, id referent_id)
weak_referrer_t *referrers;
size_t count;
if(entry-
>
out_of_line()
)else
for(size_t i =
0; i < count;
++i)
elseif(
*referrer)}}
weak_entry_remove
(weak_table, entry)
;}
裡面有幾個結構: sidetables,sidetable ,weak_table
1:sidetables
是乙個64個元素長度的hash陣列,裡面儲存了sidetable。sidetables的hash鍵值就是乙個物件obj的位址。sidetabls可以通過全域性的靜態函式獲取:sidetable& table = sidetables()[this];
static stripedmap
&sidetables()
2:sidetable
主要存放了oc物件的引用計數和弱引用相關資訊
struct sidetable
~sidetable()
//省略其他資訊....
};
refcountmap
refcnts
以disguisedptr為key的hash表,用來儲存oc物件的引用計數(僅在未開啟isa優化 或 在isa優化情況下isa_t的引用計數溢位時才會用到)。
weak_table_t
weak_table
儲存物件弱引用指標的hash表。是oc weak功能實現的核心資料結構。
struct weak_table_t
;
weak_entry_t *weak_entries;
這是乙個hash陣列。通過物件的位址,算出hash值,對應到具體的桶,每個桶裡面放的是乙個weak指標的陣列。清除的時候就是遍歷裡面的的weak指標,全部置為nil;
void
weak_clear_no_lock
(weak_table_t *weak_table, id referent_id)
// .....}}
}
總結構大致如下
iOS weak的底層實現
weak底層千千萬,吾竟裝作看不見.weak基本用法 weak是弱引用,用weak描述修飾或者所引用物件的計數器不會加一,並且會在引用的物件被釋放的時候自動被設定為nil,大大避免了野指標訪問壞記憶體引起崩潰的情況,另外weak還可以用於解決迴圈引用。weak原理概括 weak表其實是乙個hash ...
iOS weak 記憶體釋放問題
我們都知道weak 關鍵字可以解決記憶體不釋放問題,但是使用上有些講究。看 import uikit var str hello,playground class name class person let person person person.test 執行之後,控制台並沒有輸出name de...
iOS weak學習碰到的疑問
weak弱引用並不持有物件,所以賦值給 weak修飾符的變數也不會改變計數器的值.main.m id strongobj3 nil id weak obj1 nil id weak obj1 obj 編譯器的模擬 例如以下 id obj1 objc iniitweak obj1,obj objc d...