對 Strong Weak Dance的思考

2021-09-11 10:11:05 字數 2931 閱讀 7367

在使用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...