關(guān)于block使用的5點(diǎn)注意事項(xiàng)

1啄枕、在使用block前需要對(duì)block指針做判空處理。

不判空直接使用族沃,一旦指針為空直接產(chǎn)生崩潰射亏。

復(fù)制代碼

if (!self.isOnlyNet) {

? ?if (succBlock == NULL) { //后面使用block之前要先做判空處理

? ? ? ?return;

? ?}

? ?id data = [NSKeyedUnarchiver unarchiveObjectWithFile:[self favoriteFile]];

? ?if ([data isKindOfClass:[NSMutableArray class]]) {

? ? ? ?succBlock(data,YES);

? ?}else{

? ? ? ?succBlock(nil,YES);

? ?}

}

復(fù)制代碼

2、在MRC的編譯環(huán)境下竭业,block如果作為成員參數(shù)要copy一下將棧上的block拷貝到堆上(示例見(jiàn)下及舍,原因參考)

3咐柜、在block使用之后要對(duì)拙友,block指針做賦空值處理,如果是MRC的編譯環(huán)境下牍蜂,要先release掉block對(duì)象。

block作為類(lèi)對(duì)象的成員變量从绘,使用block的人有可能用類(lèi)對(duì)象參與block中的運(yùn)算而產(chǎn)生循環(huán)引用陕截。

將block賦值為空艘策,是解掉循環(huán)引用的重要方法。(不能只在dealloc里面做賦空值操作驯妄,這樣已經(jīng)產(chǎn)生的循環(huán)引用不會(huì)被破壞掉)

復(fù)制代碼

typedef void(^SuccBlock)(id data);

@interface NetworkClass {

? ?SuccessBlock _sucBlock;

}

@property (nonatomic,assign)BOOL propertyUseInCallBack;

- (void) requestWithSucBlock: (SuccessBlock) callbackBlock;

@end

@implementation NetworkClass

- (void) requestWithSucBlock: (SuccessBlock) callbackBlock {

? ?_sucBlock = callbackBlock;//MRC下:_sucBlock = [callbackBlock copy]; 不copy block會(huì)在棧上被回收。

}

- (void) netwrokDataBack: (id) data {

? ?if (data != nil && _sucBlock != NULL) {

? ? ? ?_sucBlock(data);

? ?}

? ?//MRC下:要先將[_sucBlock release];(之前copy過(guò))

? ?_sucBlock = nil; //Importent: 在使用之后將Block賦空值微猖,解引用 !!!

}

@end

//=======================以下是使用方===========================

@implementation UserCode

- (void) temporaryNetworkCall

{

? ?NetworkClass *netObj = [[NetworkClass alloc] init];

? ?netObj.propertyUseInCallBack = NO;

? ?[netObj requestWithSucBlock: ^(id data) {

? ? ? ?//由于block里面引用netObj的指針?biāo)赃@里產(chǎn)生了循環(huán)引用,且由于這個(gè)block是作為參數(shù)傳入對(duì)象的犁珠,編譯器不會(huì)報(bào)錯(cuò)犁享。

? ? ? ?//因此,NetworkClass使用完block之后一定要將作為成員變量的block賦空值窑眯。

? ? ? ?if (netObj.propertyUseInCallBack == YES) {

? ? ? ? ? ?//Do Something...

? ? ? ?}

? ?}];

}

@end

復(fù)制代碼

還有一種改法,在block接口設(shè)計(jì)時(shí)卷要,將可能需要的變量作為形參傳到block中僧叉,從設(shè)計(jì)上解決循環(huán)引用的問(wèn)題隘道。

如果上面Network類(lèi)設(shè)計(jì)成這個(gè)樣子:

復(fù)制代碼

@class NetowrkClass;

typedef void(^SuccBlock)(NetworkClass *aNetworkObj, id data);

@interface NetworkClass

//...

@end

@implementation NetworkClass

@end

@implementation UserCode

- (void) temporaryNetworkCall

{

? ?NetworkClass *netObj = [[NetworkClass alloc] init];

? ?netObj.propertyUseInCallBack = NO;

? ?[netObj requestWithSucBlock: ^(NetworkClass *aNetworkObj, id data) {

? ? ? ?//這里參數(shù)中已經(jīng)有netObj的對(duì)象了谭梗,使用者不用再?gòu)腷lock外引用指針了激捏。

? ? ? ?if (aNetworkObj.propertyUseInCallBack == YES) {

? ? ? ? ? ?//Do Something...

? ? ? ?}

? ?}];

}

@end

復(fù)制代碼

4远舅、使用方將self或成員變量加入block之前要先將self變?yōu)開(kāi)_weak

5图柏、在多線程環(huán)境下(block中的weakSelf有可能被析構(gòu)的情況下)任连,需要先將self轉(zhuǎn)為strong指針,避免在運(yùn)行到某個(gè)關(guān)鍵步驟時(shí)self對(duì)象被析構(gòu)余佃。

第四椭懊、第五條合起來(lái)有個(gè)名詞叫weak–strong dance氧猬,來(lái)自于2011 WWDC Session #322 (Objective-C Advancements in Depth)

以下代碼來(lái)自AFNetworking,堪稱(chēng)使用weak–strong dance的經(jīng)典。

復(fù)制代碼

__weak __typeof(self)weakSelf = self;

AFNetworkReachabilityStatusBlock callback = ^(AFNetworkReachabilityStatus status) {

? ?__strong __typeof(weakSelf)strongSelf = weakSelf;

? ?strongSelf.networkReachabilityStatus = status;

? ?if (strongSelf.networkReachabilityStatusBlock) {

? ? ? ?strongSelf.networkReachabilityStatusBlock(status);

? ?}

};

復(fù)制代碼

Review一下上面這段代碼毙驯,里面玄機(jī)不少。

第一行:__weak __typeof(self)weakSelf = self;

如之前第四條所說(shuō)丰包,為防止callback內(nèi)部對(duì)self強(qiáng)引用禁熏,weak一下。

其中用到了__typeof(self)邑彪,這里涉及幾個(gè)知識(shí)點(diǎn):

a. __typeof、__typeof__寄症、typeof的區(qū)別

恩~~他們沒(méi)有區(qū)別,但是這牽扯一段往事瘸爽,在早期C語(yǔ)言中沒(méi)有typeof這個(gè)關(guān)鍵字,__typeof剪决、__typeof__是在C語(yǔ)言的擴(kuò)展關(guān)鍵字的時(shí)候出現(xiàn)的。

typeof是現(xiàn)代GNU C++的關(guān)鍵字柑潦,從Objective-C的根源說(shuō),他其實(shí)來(lái)自于C語(yǔ)言渗鬼,所以AFNetworking使用了繼承自C的關(guān)鍵字览露。

b.對(duì)于老的LLVM編譯器上面這句話會(huì)編譯報(bào)錯(cuò)譬胎,所以在很早的ARC使用者中流行__typeof(&*self)這種寫(xiě)法,原因如下

大致說(shuō)法是老LLVM編譯器會(huì)將__typeof轉(zhuǎn)義為 XXX類(lèi)名 *const __strong的__strong和前面的__weak關(guān)鍵字對(duì)指針的修飾又沖突了堰乔,所以加上&*對(duì)指針的修飾。

第三行:__strong __typeof(weakSelf)strongSelf = weakSelf;

按照之前第五條的說(shuō)法給轉(zhuǎn)回strong了镐侯,這里__typeof()里面寫(xiě)的是weakSelf,里面寫(xiě)self也沒(méi)有問(wèn)題苟翻,因?yàn)閠ypeof是編譯時(shí)確定變量類(lèi)型韵卤,所以這里寫(xiě)self 不會(huì)被循環(huán)引用崇猫。

第四、五诅炉、六行贴谎,如果不轉(zhuǎn)成strongSelf而使用weakSelf季稳,后面幾句話中,有可能在第四句執(zhí)行之后self的對(duì)象可能被析構(gòu)掉景鼠,然后后面的StausBlock沒(méi)有執(zhí)行,導(dǎo)致邏輯錯(cuò)誤铛漓。

最后第五行溯香,使用前對(duì)block判空浓恶。

寫(xiě)在最后,閱讀好的開(kāi)源庫(kù)源碼是提高個(gè)人水平的一個(gè)很好途徑包晰,看見(jiàn)不懂的地方去查去摸索會(huì)得到更多。

參考:http://fuckingblocksyntax.com/ 這是個(gè)工具網(wǎng)站伐憾,寫(xiě)block的時(shí)候都會(huì)用到。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末蒸矛,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子胸嘴,更是在濱河造成了極大的恐慌,老刑警劉巖劣像,帶你破解...
    沈念sama閱讀 217,826評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異驾讲,居然都是意外死亡席赂,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)谓晌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人纸肉,你說(shuō)我怎么就攤上這事溺欧。” “怎么了姐刁?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,234評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵烦味,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我谬俄,道長(zhǎng),這世上最難降的妖魔是什么溃论? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,562評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮钥勋,結(jié)果婚禮上炬转,老公的妹妹穿的比我還像新娘返吻。我一直安慰自己,他們只是感情好测僵,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著谢翎,像睡著了一般捍靠。 火紅的嫁衣襯著肌膚如雪森逮。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,482評(píng)論 1 302
  • 那天褒侧,我揣著相機(jī)與錄音,去河邊找鬼闷供。 笑死,一個(gè)胖子當(dāng)著我的面吹牛歪脏,可吹牛的內(nèi)容都是我干的疑俭。 我是一名探鬼主播婿失,決...
    沈念sama閱讀 40,271評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼啄寡,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼哩照!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起葡秒,我...
    開(kāi)封第一講書(shū)人閱讀 39,166評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎眯牧,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體学少,經(jīng)...
    沈念sama閱讀 45,608評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評(píng)論 3 336
  • 正文 我和宋清朗相戀三年版确,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片绒疗。...
    茶點(diǎn)故事閱讀 39,926評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖吓蘑,靈堂內(nèi)的尸體忽然破棺而出惕虑,到底是詐尸還是另有隱情磨镶,我是刑警寧澤,帶...
    沈念sama閱讀 35,644評(píng)論 5 346
  • 正文 年R本政府宣布琳猫,位于F島的核電站,受9級(jí)特大地震影響脐嫂,放射性物質(zhì)發(fā)生泄漏统刮。R本人自食惡果不足惜账千,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧桦山,春花似錦醋旦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,866評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)咧最。三九已至,卻和暖如春矢沿,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背捣鲸。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,991評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留栽惶,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,063評(píng)論 3 370
  • 正文 我出身青樓外厂,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親汁蝶。 傳聞我的和親對(duì)象是個(gè)殘疾皇子渐扮,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容