1. 程式人生 > >oc block 中直接引用成員變數 迴圈引用

oc block 中直接引用成員變數 迴圈引用

問題的答案是一定會發生迴圈引用。

那解決方式:

 __weak typeof(self) wself = self;
用wself訪問成員變數就好。

既然發生了迴圈引用一定是retain了self了,那又是為什麼block不retain成員變數指標會retain self 呢?

原因是oc是動態語言,例項變數的地址可能被其他例項變數佔用,直接引用的話容易出問題。

retain self的好處是當類的定義變了,其儲存的偏移量也變了,偏移量會在執行時查詢,這樣的話無論何時訪問總能得到正確的地址,甚至可以在執行時新增變數。

  1. struct objc_class {  
  2.     Class isa  OBJC_ISA_AVAILABILITY;  
  3. #if !__OBJC2__
  4.     Class super_class                                        OBJC2_UNAVAILABLE;  
  5.     constcharchar *name                                         OBJC2_UNAVAILABLE;  
  6.     long version                                             OBJC2_UNAVAILABLE;  
  7.     long info                                                OBJC
    2_UNAVAILABLE;  
  8.     long instance_size                                       OBJC2_UNAVAILABLE;  
  9.     structobjc_ivar_list *ivars                             OBJC2_UNAVAILABLE;  
  10.     structobjc_method_list **methodLists                    OBJC2_UNAVAILABLE;  
  11.     structobjc_cache *cache                                 OBJC
    2_UNAVAILABLE;  
  12.     structobjc_protocol_list *protocols                     OBJC2_UNAVAILABLE;  
  13. #endif
  14. } OBJC2_UNAVAILABLE;  

其中objc_ivar_list結構體儲存著objc_ivar陣列列表,而objc_ivar結構體儲存了類的單個成員變數的資訊。

Ivar 在objc中被定義為:

  1. typedefstructobjc_ivar *Ivar;  

它是一個指向objc_ivar結構體的指標,結構體有如下定義:

  1. struct objc_ivar {  
  2.     charchar *ivar_name                                          OBJC2_UNAVAILABLE;  
  3.     charchar *ivar_type                                          OBJC2_UNAVAILABLE;  
  4.     int ivar_offset                                          OBJC2_UNAVAILABLE;  
  5. #ifdef __LP64__
  6.     int space                                                OBJC2_UNAVAILABLE;  
  7. #endif
  8. }                                                            OBJC2_UNAVAILABLE;  

這裡我們注意第三個成員 ivar_offset。它表示基地址偏移位元組。