關(guān)于block使用的一些總結(jié)

網(wǎng)上已經(jīng)有很多討論block底層實(shí)現(xiàn)原理的文章儒溉,這里不討論實(shí)現(xiàn)悄晃,只討論block使用中的一些問(wèn)題徽诲。

一轴咱、聲明block屬性時(shí)應(yīng)該使用什么關(guān)鍵字傻谁?

答案:copy

以下內(nèi)容翻譯自官方文檔:
定義一個(gè)跟蹤block的屬性的語(yǔ)法:

@interface XYZObject : NSObject
@property (copy) void (^blockProperty)(void);
@end

注意:你應(yīng)該指定copy作為屬性關(guān)鍵字畸颅,因?yàn)閴K需要被拷貝以跟蹤它在原始范圍外捕獲的狀態(tài)狂芋。由于使用自動(dòng)引用計(jì)數(shù)時(shí)(Automatic Reference Counting)這是自動(dòng)發(fā)生的微谓,所以你不需要擔(dān)心這些纽门,但是屬性關(guān)鍵字的最佳做法是展示結(jié)果行為薛耻。更多關(guān)于block的信息,參閱Blocks Programming Topics赏陵。

上面這一段翻譯的官方文檔原文地址:Programming with Objective-C/Working with Blocks

注意:copy對(duì)屬性也是強(qiáng)引用饼齿,只不過(guò)這個(gè)強(qiáng)引用指向的是賦值給屬性的那個(gè)對(duì)象的一份拷貝。官方文檔copy關(guān)鍵字的使用有詳細(xì)說(shuō)明蝙搔,詳情參閱文檔《Programming with Objective-C》中Encapsulating Data主題的Copy Properties Maintain Their Own Copies章節(jié)

二缕溉、block循環(huán)引用

循環(huán)引用的產(chǎn)生

以下內(nèi)容翻譯自官方文檔:
block對(duì)任何捕獲的對(duì)象保持強(qiáng)應(yīng)用,包括self吃型,這意味著如果一個(gè)對(duì)象對(duì)一個(gè)捕獲了self的block保持了copy屬性(上面第一個(gè)問(wèn)題中解釋過(guò)证鸥,官方文檔建議block屬性使用copy關(guān)鍵字,且copy屬性self對(duì)屬性也是強(qiáng)引用,詳情請(qǐng)翻看問(wèn)題一):

@interface XYZBlockKeeper : NSObject
@property (copy) void (^block)(void);
@end
@implementation XYZBlockKeeper
- (void)configureBlock {
    self.block = ^{
        [self doSomething];// 捕獲對(duì)self的強(qiáng)引用(capturing a strong reference to self)
                               // 創(chuàng)建了一個(gè)強(qiáng)引用循環(huán)(creates a strong reference cycle)
    };
}
...
@end

解決方法:
避免這個(gè)問(wèn)題的最好方法是捕獲對(duì)self的弱引用枉层,如下:

- (void)configureBlock {
    XYZBlockKeeper * __weak weakSelf = self;
    self.block = ^{
        [weakSelf doSomething];   // 捕獲弱引用以避免循環(huán)引用(capture the weak reference to avoid the reference cycle)
    }
}

通過(guò)捕獲指向self的弱指針泉褐,block就不會(huì)與XYZBlockKeeper對(duì)象保持強(qiáng)關(guān)系。如果對(duì)象在block調(diào)用前解除分配鸟蜡,weakSelf指針將被簡(jiǎn)單地置為nil膜赃。

官方文檔地址:Programming with Objective-C/Working with Blocks

調(diào)用的方法中有block參數(shù),會(huì)不會(huì)導(dǎo)致循環(huán)引用矩欠?

問(wèn)題描述:如果self或self.property調(diào)用的方法中有個(gè)block參數(shù)财剖,在這個(gè)block參數(shù)中使用了self,會(huì)不會(huì)導(dǎo)致循環(huán)引用癌淮?
這里的方法其實(shí)有兩種情況:self中的方法和self中屬性對(duì)象中的方法

self自己的方法使用block作為參數(shù)躺坟,這個(gè)block中使用了self,會(huì)不會(huì)導(dǎo)致循環(huán)引用乳蓄?

代碼如下:

- (void)doSomething {
    [self testWithBlock:^{
        [self testMethod];
    }];
}

- (void)testWithBlock:(void(^)())block {
    block();
}

- (void)testMethod {
    NSLog(@"test");
}

答案:此時(shí)block只是一個(gè)臨時(shí)變量咪橙,self并沒(méi)有對(duì)其持有,所有不會(huì)產(chǎn)生循環(huán)引用虚倒。

self的屬性對(duì)象中的方法美侦,使用block作為參數(shù),block中使用了self魂奥,會(huì)不會(huì)產(chǎn)生循環(huán)引用菠剩?

這里也有兩種情況:1、屬性對(duì)象持有了傳入的block參數(shù) 2耻煤、屬性對(duì)象未持有傳入的block參數(shù)

1具壮、屬性對(duì)象持有了傳入的block參數(shù)

代碼如下:

#import <Foundation/Foundation.h>
typedef void (^BlockType)(void);
@interface AbcObject : NSObject
- (void)methodWithBlock:(BlockType)block;
@end

#import "AbcObject.h"
@interface AbcObject()
//不作為公有屬性,而是在對(duì)外方法接口中把Block傳進(jìn)來(lái)
@property (nonatomic, copy) BlockType block;
@end

@implementation AbcObject
- (void)methodWithBlock:(BlockType)block {
    //self.block留待后面其他地方異步調(diào)用
    //會(huì)產(chǎn)生循環(huán)引用
    self.block = block;

    //比如哈蝇,發(fā)起一個(gè)異步請(qǐng)求
    //...
}

//比如是在一個(gè)請(qǐng)求的回調(diào)中執(zhí)行剛才保存的block
- (void)completionDelegate {
    //調(diào)用剛才保存的block
    if (self.block) {
        self.block();
    }
}
@end
#import "ViewController.h"
#import "AbcObject.h"
@interface ViewController ()
@property (nonatomic, strong) AbcObject *abcObject;
@property (nonatomic, copy) NSString *str;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.str = @"haha";
    
    self.abcObject = [[AbcObject alloc] init];
    [self.abcObject configurePersonBlock:^{
        NSLog(@"printf str:%@", self.str);
        //解決問(wèn)題的辦法是block中使用weakSelf
    }];
]}
@end

如上面的例子棺妓,這里也有兩種情況,如果傳入abcObject對(duì)象的block參數(shù)被abcObject對(duì)象作為屬性存儲(chǔ)起來(lái)以備其他地方的異步調(diào)用炮赦,這種情況self持有了person怜跑,person又持有了傳入的block,block中又引用了self吠勘,間接產(chǎn)生了循環(huán)引用性芬。

2、屬性對(duì)象未持有傳入的block參數(shù)

如果上面的代碼改一下剧防,methodWithBlock中不用屬性持有傳入的block(其余代碼不變):

#import <Foundation/Foundation.h>
typedef void (^ BlockType)(void);
@interface AbcObject : NSObject
- (void)methodWithBlock:(BlockType)block;
@end

#import "AbcObject.h"
@interface AbcObject()
@end

@implementation AbcObject
- (void)methodWithBlock:(BlockType)block {
    //做其他事情
    //...

    //不會(huì)產(chǎn)生循環(huán)引用
    if (block) {
        block();
    }
}
@end

則不會(huì)產(chǎn)生循環(huán)引用批旺。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市诵姜,隨后出現(xiàn)的幾起案子汽煮,更是在濱河造成了極大的恐慌搏熄,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,406評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件暇赤,死亡現(xiàn)場(chǎng)離奇詭異心例,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)鞋囊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,395評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門(mén)止后,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人溜腐,你說(shuō)我怎么就攤上這事译株。” “怎么了挺益?”我有些...
    開(kāi)封第一講書(shū)人閱讀 167,815評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵歉糜,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我望众,道長(zhǎng)匪补,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,537評(píng)論 1 296
  • 正文 為了忘掉前任烂翰,我火速辦了婚禮夯缺,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘甘耿。我一直安慰自己踊兜,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,536評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布佳恬。 她就那樣靜靜地躺著润文,像睡著了一般。 火紅的嫁衣襯著肌膚如雪殿怜。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,184評(píng)論 1 308
  • 那天曙砂,我揣著相機(jī)與錄音头谜,去河邊找鬼。 笑死鸠澈,一個(gè)胖子當(dāng)著我的面吹牛柱告,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播笑陈,決...
    沈念sama閱讀 40,776評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼际度,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了涵妥?” 一聲冷哼從身側(cè)響起乖菱,我...
    開(kāi)封第一講書(shū)人閱讀 39,668評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后窒所,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體鹉勒,經(jīng)...
    沈念sama閱讀 46,212評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,299評(píng)論 3 340
  • 正文 我和宋清朗相戀三年吵取,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了禽额。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,438評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡皮官,死狀恐怖脯倒,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情捺氢,我是刑警寧澤藻丢,帶...
    沈念sama閱讀 36,128評(píng)論 5 349
  • 正文 年R本政府宣布,位于F島的核電站讯沈,受9級(jí)特大地震影響郁岩,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜缺狠,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,807評(píng)論 3 333
  • 文/蒙蒙 一问慎、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧挤茄,春花似錦如叼、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,279評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至歇终,卻和暖如春社证,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背评凝。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,395評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工追葡, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人奕短。 一個(gè)月前我還...
    沈念sama閱讀 48,827評(píng)論 3 376
  • 正文 我出身青樓宜肉,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親翎碑。 傳聞我的和親對(duì)象是個(gè)殘疾皇子谬返,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,446評(píng)論 2 359

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