絕大多數ios開發者用過block
,並且知道用__weak的方式去解決迴圈引用的問題。而高階一些的開發者則了解weak-strong-dance
,那麼什麼是weak-strong-dance
?它能保證block執行是的「安全」嗎?
看看下面兩段**的區別,你就明白什麼是weak-strong-dance
了。
- (void)test ;
}複製**
- (void)test ;
}複製**
也就是在用__weak解決迴圈引用的前提下 ,在block
內部用__strong持有物件,試**決「在多執行緒下,可能weakself指向的物件會在 block 執行前被廢棄,導致各種各樣的問題,比如說kvo,傳入nil可是會crash呢」,如下**
__weak typeof(self) weakself = self;
self.handler = ^;複製**
此時,你可能會這樣認為,self所指向物件的引用計數變成 2,即使主線程中的 self 因為超出作用於而釋放,物件的引用計數依然為 1,避免了物件的銷毀。
它真的能解決在多執行緒下,可能 weakself 指向的物件會在 block 執行前被廢棄而導致的問題嗎?
答案當然是否定的,讓我們來看看demo:
不用weak-strong-dance
:
#import "testblock.h"
@inte***ce testblock ()
@property (nonatomic, strong) dispatch_block_t block;
@end
@implementation testblock
- (void)test ;
}@end複製**
看看用clang改寫後的**,這裡就只貼關鍵**了:
// @inte***ce testblock ()
// @property (nonatomic, strong) dispatch_block_t block;
/* @end */
// @implementation testblock
struct __testblock__test_block_impl_0
};static
void __testblock__test_block_func_0(struct __testblock__test_block_impl_0 *__cself)
static
void __testblock__test_block_copy_0(struct __testblock__test_block_impl_0*dst, struct __testblock__test_block_impl_0*src)
static
void __testblock__test_block_dispose_0(struct __testblock__test_block_impl_0*src)
static struct __testblock__test_block_desc_0 __testblock__test_block_desc_0_data = ;
static
void _i_testblock_test(testblock * self, sel _cmd)
static
void(* _i_testblock_block(testblock * self, sel _cmd) )()
static
void _i_testblock_setblock_(testblock * self, sel _cmd, dispatch_block_t block)
// @end
複製**
**很長,解釋下:
在struct__testblock__test_block_impl_0
裡頭,我們能看到testblock *const __weak weakself;
這代表在block內部是以弱引用的方式捕獲self的,這沒毛病。重點來了,看這一段代表block具體實現的**塊
static
void __testblock__test_block_func_0(struct __testblock__test_block_impl_0 *__cself) 複製**
這裡可以看到如果此時外部廢棄了self,的確會導致block內部訪問成nil的情況。
那麼如果用了weak-strong-dance
呢?
__weak typeof(self) weakself = self;
self.block = ^;複製**
看看clang改寫後會有什麼區別:
struct __testblock__test_block_impl_0
};static
void __testblock__test_block_func_0(struct __testblock__test_block_impl_0 *__cself) 複製**
區別在於在block內多了這麼一行**__attribute__((objc_ownership(strong))) typeof(self) strongself = weakself;
。
所以持有self的行為是在block執行的時候才發生的!
回過頭來看看問題:它真的能解決在多執行緒下,可能 weakself 指向的物件會在 block 執行前被廢棄而導致的問題嗎?
在執行前就廢棄,到了執行的時候,weakself已經是nil了,此時執行__strong typeof(self) strongself = weakself;
根本沒意義吧。
所以在剛才kvo的例子中,該crash還是繼續crash吧。只要在執行__strong typeof(self) strongself = weakself;
前,物件在其他執行緒被廢棄了,weak-strong-dance不能幫上任何忙!
weak-strong-dance
並不能保證block所引用物件的釋放時機在執行之後, 更安全的做法應該是在block內部使用strongself時進行nil檢測,這樣可以避免上述情況。
Docker容器真的安全嗎?
本文基於我今年在dockercon上的演講。它將討論docker容器安全性,我們當前的位置以及發展的方向。這是有關docker安全性的系列文章的一部分 請閱讀第二部分 我聽到並讀到很多人都認為docker容器實際上是沙箱應用程式 意味著他們可以使用docker作為根在自己的系統上執行隨機應用程式。他...
linux真的很安全麼?
寫這篇文章是因為看到了cnbeta上最近接二連三地出現類似這篇的文章。雖然我還是認為此文的作者多少還是有點標題黨,因為那個 a 其實可以是任何東西,這樣就說是 乙個命令 也太無聊了點。但是我在公司的rhel4的伺服器上試驗了之後,確實可以非法提公升許可權。不免有點擔憂。於是我順藤摸瓜,在那個提供ha...
你的登入介面真的安全嗎?
大家學寫程式時,第一行 都是hello world。但是當你開始學習web後台技術時,很多人的第乙個功能就是寫的登入 小聲 別人我不知道,反正我是 但是我在和很多任務作經驗較短的同學面試或溝通的時候,發現很多同學雖然都有在簡歷上寫 負責專案的登入 註冊功能模組的開發和設計工作,但是都只是簡單的實現了...