在使用block
時,除了使用__weak
修飾符避免迴圈引用外,還有一點經常容易忘記。蘋果把它稱為:「strong-weak dance」。
這是一種 強引用 --> 弱引用 --> 強引用 的變換過程。在弄明白為什麼要如此大費周章之前,我們首先來看看一般的寫法會有什麼問題。
__weak myviewcontroller *wself = self;
self.completionhandler = ^(nsinteger result) ;
複製**
這種寫法可以避免迴圈引用,但是我們要考慮這樣的問題:
假設block
被放在子執行緒中執行,而且執行過程中self
在主線程被釋放了。由於wself
是乙個弱引用,因此會自動變為nil
。而在 kvo 中,這會導致崩潰。
解決以上問題的方法很簡單,新增一行**即可:
__weak myviewcontroller *wself = self;
self.completionhandler = ^(nsinteger result) ;
複製**
這樣一來,self
所指向物件的引用計數變成 2,即使主線程中的self
因為超出作用於而釋放,物件的引用計數依然為 1,避免了物件的銷毀。
在和小夥伴的討論過程中,他提出了幾個問題。雖然都不難,但是有利於把各種知識融會貫通起來。
q:下面這行**,將乙個弱引用的指標賦值給強引用的指標,可以起到強引用效果麼?
__strong __typeof(wself) sself = wself;
複製**
a:會的。引用計數描述的是物件而不是指標。這句話的意思是:
sself 強引用 wself 指向的那個物件因此物件的引用計數會增加乙個。
q:block
內部定義了sself
,會不會因此強引用了sself
?
a:不會。block
只有截獲外部變數時,才會引用它。如果是內部新建乙個,則沒有任何問題。
q:如果在block
內部沒有強引用,而是通過if
判斷,是不是也可以,比如這樣寫:
__weak myviewcontroller *wself = self;
wself.completionhandler = ^(nsinteger result)
};複製**
a:不可以!考慮到多執行緒執行,也許在判斷的時候,self
還沒釋放,但是執行self
裡面的**時,就剛好釋放了。
q:那按照這個說法,block
內部強引用也沒用啊。也許block
執行以前,self
就釋放了。
a:有用!如果在block
執行以前,self
就釋放了,那麼block
的引用計數降為 0,所以自己就會被釋放。這樣它根本就不會被執行。另外,如果執行乙個為nil
的閉包會導致崩潰。
q:如果在執行block
的過程中,block
被釋放了怎麼辦?
這是 reactivecocoa 中定義的乙個巨集。一般可以這樣使用:
@weakify(self);
self.completionhandler = ^(nsinteger result) ;
複製**
這裡的「@」沒有任何用處,僅表示強調,這個巨集實際上包含了乙個空的autoreleasepool
,這也就是為什麼一定要加上「@」。
它的原理還是和之前一樣,生成了一段形如__weak myviewcontroller *wself = self;
這種格式的**:
#define rac_strongify_(index, var) \\
__strong __typeof__(var) var = metamacro_concat(var, _weak_);
複製**
感謝 @cyrus_dev 的提醒,在 swift 中也有 strong-weak dance 的概念。最簡單的方法就是直接沿用 oc 的思路:
self.completionhandler =
};複製**
這種寫法的缺點在於,我們不能寫if let self = self
,因此需要重新定義乙個變數strongself
,命名方式顯得不夠優雅。
除此以外還可以使用 swift 標準庫提供的函式withextendedlifetime
:
self.completionhandler =
};複製**
這種寫法的缺點在於,self
依然是可選型別的,還需要把它解封後才能使用。
最後,還有一種解決方案是自定義withextendedlifetime
函式:
extension
optional}}
複製**
至於這種寫法是否更加優雅,就見仁見智了:
self.completionhandler =
};複製**
the weak/strong dance in swift 對建立游標對理解
步驟 1 首先經過底層的 編寫已經建立起了了python和資料庫之間的溝通橋梁並封裝成了模組,通過pymysql下的conntent 方法與之建立起了連線,例項物件。pymysql.connect 方法返回的是connections模組下的connection 例項,connect 方法傳參就是在給...
對勾函式 對勾函式
對勾函式是一種類似於反比例函式的一般函式。所謂的對勾函式,是形如 f x ax b x 的函式,是 一種教材上沒有但考試老喜歡考的函式,所以更加要注意和學習。一般的函式影象形似兩個中心對稱的 對勾,故名。當x 0 時,f x ax b x 有最小值 這裡為了研究方便,規定a 0 b 0 也就是當 x...
一對多 多對一
pip install djangorestframework 3.9.2 pip install markdown 3.0.1 markdown support for the browsable api.pip install django filter 2.1.0 filtering supp...