oc block 中直接引用成員變數 迴圈引用
阿新 • • 發佈:2019-01-26
問題的答案是一定會發生迴圈引用。
那解決方式:
__weak typeof(self) wself = self;
用wself訪問成員變數就好。
既然發生了迴圈引用一定是retain了self了,那又是為什麼block不retain成員變數指標會retain self 呢?
原因是oc是動態語言,例項變數的地址可能被其他例項變數佔用,直接引用的話容易出問題。
retain self的好處是當類的定義變了,其儲存的偏移量也變了,偏移量會在執行時查詢,這樣的話無論何時訪問總能得到正確的地址,甚至可以在執行時新增變數。
- struct objc_class {
-
Class isa OBJC_ISA_AVAILABILITY;
- #if !__OBJC2__
- Class super_class OBJC2_UNAVAILABLE;
- constcharchar *name OBJC2_UNAVAILABLE;
- long version OBJC2_UNAVAILABLE;
-
long info OBJC
- long instance_size OBJC2_UNAVAILABLE;
- structobjc_ivar_list *ivars OBJC2_UNAVAILABLE;
- structobjc_method_list **methodLists OBJC2_UNAVAILABLE;
-
structobjc_cache *cache OBJC
- structobjc_protocol_list *protocols OBJC2_UNAVAILABLE;
- #endif
- } OBJC2_UNAVAILABLE;
其中objc_ivar_list
結構體儲存著objc_ivar
陣列列表,而objc_ivar結構體儲存了類的單個成員變數的資訊。
Ivar
在objc中被定義為:
- typedefstructobjc_ivar *Ivar;
它是一個指向objc_ivar結構體的指標,結構體有如下定義:
- struct objc_ivar {
- charchar *ivar_name OBJC2_UNAVAILABLE;
- charchar *ivar_type OBJC2_UNAVAILABLE;
- int ivar_offset OBJC2_UNAVAILABLE;
- #ifdef __LP64__
- int space OBJC2_UNAVAILABLE;
- #endif
- } OBJC2_UNAVAILABLE;
這裡我們注意第三個成員 ivar_offset
。它表示基地址偏移位元組。