block里的self、weakSelf、strongSelf


ARC下,關於block里面使用self、weakSelf、strongSelf,理解一直沒有特別的透徹,今天花時間研究了一下,總結如下:
 
其實一共就涉及到兩個問題:
1.是否循環引用了
2.block里面的代碼,不一定執行到哪行時,VC可能就釋放了,self就為nil了,那么你到底想讓代碼在這種情況下如何執行。
 
其實到底用self、weakSelf還是strongSelf,就是上面兩個問題的排列組合
 
有種典型的寫法:
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
__weak __typeof__(self) weakSelf = self;
dispatch_async(queue, ^{
    __typeof__(self) strongSelf = weakSelf;
    [strongSelf assitFunc1];
});

 

首先我的結論是,所有情況下,這么寫是不會出什么問題的(當然也好多情況下不用這么寫),唯一可能出問題的地方就是要保證block里面的代碼能夠被執行到,否則就和循環引用一樣,是不會釋放VC的。什么情況會執行不到?比如queue里面已經有1萬個任務,然后正在串行執行,當然這里說的是理論上,所以一般也不會有這種情況。
 
不會出問題的原因是:不會造成循環引用,因為沒有對self持有(其實是block代碼期間持有了,執行完畢就不持有了);block里的代碼一定會執行,因為strongSelf會保證在block代碼執行完畢之前self不會被釋放(延遲了VC的生命周期),並且執行的時候strongSelf一定不會為nil。所以沒有問題。
 
然后說下weak和strong的作用:
1.weakSelf,不增加self的引用計數,然后你還可以使用它,所以它能防止循環引用(該釋放釋放,和weakSelf怎么用完全沒關系)。
2.strongSelf,在定義的區域內保證指向的內容不被釋放,所以他用在確保代碼執行的時候。(防止self變成nil,延遲self的生命)。
 
到底怎么用有以下情況:
1.不管使用self,還是strongSelf,都延遲了VC釋放的時間,至少要執行完block。
 
2.如果block是臨時的block,例如在ViewDidLoad里面寫上面的代碼。直接使用self就可以達到同樣的效果,不會出現內存泄露,因為雖然block持有self,但是self並沒有持有block,沒有成環。並且注意,self一定會晚於或者等於block執行完畢的時間釋放。就算執行到block中的某行代碼,並不在當前VC了,也不會crash,因為self沒有釋放。
所以好多時候,如果block和self沒有成環,我們就直接使用self就行了。無需定義weakSelf和strongSelf。但是有時候沒有成環,我們依然使用了weakSelf,這時其實可以達到這樣的效果:如果VC釋放了(不在當前頁了),那么由weakSelf方法調用的函數,其實都不執行了,就達到了節省資源的目的,需要注意的是對於nil的處理,避免crash。既用weak又用strong就沒必要了,就和直接使用self時一個效果。
 
3.如果成環了,那么一定會使用weak。至於block里面的代碼是全部使用weak還是全部使用strong,就取決於當self變成nil時,你想讓代碼如何執行,如果無論如何你都想執行block里面的代碼,那么就用strong,如果想要self為nil時,不執行一些代碼,則凡是使用weakSelf的函數都不會被執行,也必須注意可能會crash的地方。
 
結論:
1.不成環,並且想讓block代碼什么情況下都執行:兩種方式:A全部使用self就行;B外面定義weak,block里面用strong,也行,多次一舉。
 
2.不成環,並且想讓block代碼在當前VC釋放的情況下不執行:兩種方式:A外面定義weak,里面使用weak,然后注意nil可能會crash的地方(加判斷);B外面定義weak,block里面使用strong(或者直接使用self),自己加if判斷,否是在當前頁面,不在當前頁面不執行。
 
3.成環,想讓block代碼無論如何都執行:必用weak。block里面用strong。
 
4.成環,想讓block代碼在當前VC釋放的情況下不執行:兩種方式:A必用weak,block里面用strong,則自己加if判斷不在當前頁面就不執行;B,block里面使用weak,注意nil可能導致crash的地方。
 
重點注意:弄清楚block到底被誰持有,例如UIView的animateWithDuration方法,大部分時候寫的dispatch,傳參等,都沒有成環,是不用定義weak和strong的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM