Block詳解

1??Block的修飾

ARC情況下(

ARC是iOS 5推出的新功能亩鬼,全稱(chēng)叫 ARC(Automatic Reference Counting)本谜。簡(jiǎn)單地說(shuō)纹冤,就是代碼中自動(dòng)加入了retain/release清酥,原先需要手動(dòng)添加的用來(lái)處理內(nèi)存管理的引用計(jì)數(shù)的代碼可以自動(dòng)地由編譯器完成了雄可。

該機(jī)能在 iOS 5/ Mac OS X 10.7 開(kāi)始導(dǎo)入凿傅,利用 Xcode4.2 可以使用該機(jī)能。簡(jiǎn)單地理解ARC数苫,就是通過(guò)指定的語(yǔ)法聪舒,讓編譯器(LLVM 3.0)在編譯代碼時(shí),自動(dòng)生成實(shí)例的引用計(jì)數(shù)管理部分代碼虐急。有一點(diǎn)箱残,ARC并不是GC,它只是一種代碼靜態(tài)分析(Static Analyzer)工具止吁。

1.如果用copy修飾Block被辑,該Block就會(huì)存儲(chǔ)在堆空間。則會(huì)對(duì)Block的內(nèi)部對(duì)象進(jìn)行強(qiáng)引用敬惦,導(dǎo)致循環(huán)引用盼理。內(nèi)存無(wú)法釋放。

解決方法:

新建一個(gè)指針(__weak typeof(Target) weakTarget = Target )指向Block代碼塊里的對(duì)象俄删,然后用weakTarget進(jìn)行操作宏怔。就可以解決循環(huán)引用問(wèn)題奏路。

2.如果用weak修飾Block,該Block就會(huì)存放在楇铮空間鸽粉。不會(huì)出現(xiàn)循環(huán)引用問(wèn)題。

MRC情況下

用copy修飾后妨猩,如果要在Block內(nèi)部使用對(duì)象潜叛,則需要進(jìn)行(__block typeof(Target) blockTarget = Target )處理秽褒。在Block里面用blockTarget進(jìn)行操作壶硅。

2??Block的定義格式

返回值類(lèi)型(^block變量名)(形參列表) = ^(形參列表) {

};

默認(rèn)情況下,Block內(nèi)部不能修改外面的局部變量

Block內(nèi)部可以修改使用__block修飾的局部變量

3??Block的模式

1.無(wú)參數(shù)無(wú)返回值的Block

2.有參數(shù)無(wú)返回值的Block

3.有參數(shù)有返回值的Block

4??Block簡(jiǎn)單用法舉例

①無(wú)參數(shù)無(wú)返回值的Block

/**

*? 無(wú)參數(shù)無(wú)返回值的Block

*/

-(void)func1{

? ? /**

? ? *? void :就是無(wú)返回值

? ? *? emptyBlock:就是該block的名字

? ? *? ():這里相當(dāng)于放參數(shù)。由于這里是無(wú)參數(shù)销斟,所以就什么都不寫(xiě)

? ? */

? ? void (^emptyBlock)() = ^(){

? ? ? ? NSLog(@"無(wú)參數(shù),無(wú)返回值的Block");

? ? };

? ? emptyBlock();

}

②有參數(shù)無(wú)返回值的Block

/**

? ? *? 調(diào)用這個(gè)block進(jìn)行兩個(gè)參數(shù)相加

? ? *

? ? *? @param int 參數(shù)A

? ? *? @param int 參數(shù)B

? ? *

? ? *? @return 無(wú)返回值

? ? */

? ? void (^sumBlock)(int ,int ) = ^(int a,int b){

? ? ? ? NSLog(@"%d + %d = %d",a,b,a+b);

? ? };

? ? /**

? ? *? 調(diào)用這個(gè)sumBlock的Block庐椒,得到的結(jié)果是20

? ? */

? ? sumBlock(10,10);

③有參數(shù)有返回值的Block

/**

? ? *? 有參數(shù)有返回值

? ? *

? ? *? @param NSString 字符串1

? ? *? @param NSString 字符串2

? ? *

? ? *? @return 返回拼接好的字符串3

? ? */? ?

? ? NSString* (^logBlock)(NSString *,NSString *) = ^(NSString * str1,NSString *str2){

? ? ? ? return [NSString stringWithFormat:@"%@%@",str1,str2];

? ? };

? ? //調(diào)用logBlock,輸出的是 我是Block

? ? NSLog(@"%@", logBlock(@"我是",@"Block"));

5??Block結(jié)合typedef使用

自己定義一個(gè)Block類(lèi)型,用定義的類(lèi)型去創(chuàng)建Block蚂踊,更加簡(jiǎn)單便捷约谈。

這里舉例一個(gè)Block回調(diào)修改上一下界面的背景顏色。

ViewController1 控制器1犁钟,ViewController2 控制器2

控制器1跳轉(zhuǎn)到控制器2棱诱,然后在控制器2觸發(fā)事件回調(diào)修改控制器1的背景顏色為紅色。

ViewController2的實(shí)現(xiàn)

#import

@interface ViewController2 : UIViewController

/**

*? 定義了一個(gè)changeColor的Block涝动。這個(gè)changeColor必須帶一個(gè)參數(shù)迈勋,這個(gè)參數(shù)的類(lèi)型必須為id類(lèi)型的

*? 無(wú)返回值

*? @param id

*/

typedef void(^changeColor)(id);

/**

*? 用上面定義的changeColor聲明一個(gè)Block,聲明的這個(gè)Block必須遵守聲明的要求。

*/

@property (nonatomic, copy) changeColor backgroundColor;

@end

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{

? ? //聲明一個(gè)顏色

? ? UIColor *color = [UIColor redColor];

? ? //用剛剛聲明的那個(gè)Block去回調(diào)修改上一界面的背景色

? ? self.backgroundColor(color);

}

ViewController1的實(shí)現(xiàn)

-(void)touchesBegan:(NSSet?*)touches?withEvent:(UIEvent?*)event{

ViewController2?*vc?=[[ViewController2?alloc]init];

//?回調(diào)修改顏色

vc.backgroundColor?=?^(UIColor?*color){

self.view.backgroundColor?=?color;

};

[self.navigationController?pushViewController:vc?animated:YES];

}

=========================================================================================

1.block簡(jiǎn)介

在 iOS中醋粟, block一共分三種靡菇。

(1)全局靜態(tài) block,不會(huì)訪問(wèn)任何外部變量米愿,執(zhí)行完就銷(xiāo)毀厦凤。

^{

? ? ? ? NSLog(@"Hello World!");

? ? }();

(2)保存在棧中的 block,當(dāng)函數(shù)返回時(shí)會(huì)被銷(xiāo)毀育苟,和第一種的區(qū)別就是調(diào)用了外部變量较鼓。

? ? [UIView animateWithDuration:3 animations:^{


? ? ? ? self.view.backgroundColor = [UIColor redColor];

? ? }];

(3)保存在堆中的 block,當(dāng)引用計(jì)數(shù)為 0 時(shí)會(huì)被銷(xiāo)毀违柏。例如按鈕的點(diǎn)擊事件笨腥,一直存在,即使執(zhí)行過(guò)勇垛,也不銷(xiāo)毀脖母,因?yàn)榘粹o還可能被點(diǎn)擊,持有按鈕的View被銷(xiāo)毀闲孤,它才會(huì)被銷(xiāo)毀谆级。

#import

typedef void(^ButtonClickBlcok)();

@interface TestView : UIView

@property (nonatomic, copy) ButtonClickBlcok buttonClickBlcok;

@end

#import "TestView.h"

@implementation TestView

- (IBAction)buttonClick:(id)sender {


? ? if (self.buttonClickBlcok) {

? ? ? ? self.buttonClickBlcok();

? ? }

}

@end

2.block優(yōu)點(diǎn)

block的代碼可讀性更好烤礁。因?yàn)閼?yīng)用block和實(shí)現(xiàn)block的地方在一起。代理的聲明和實(shí)現(xiàn)就分開(kāi)來(lái)了肥照,在兩個(gè)類(lèi)中脚仔。代理使用起來(lái)也更麻煩,因?yàn)橐暶鲄f(xié)議舆绎、聲明代理鲤脏、遵守協(xié)議、實(shí)現(xiàn)協(xié)議里的方法吕朵。block不需要聲明猎醇,也不需要遵守,只需要聲明和實(shí)現(xiàn)就可以了努溃。

block是一種輕量級(jí)的回調(diào)硫嘶,可以直接訪問(wèn)上下文,由于block的代碼是內(nèi)聯(lián)的梧税,運(yùn)行效率更高沦疾。block就是一個(gè)對(duì)象,實(shí)現(xiàn)了匿名函數(shù)的功能第队。所以我們可以把block當(dāng)做一個(gè)成員變量哮塞、屬性、參數(shù)使用凳谦,使用起來(lái)非常靈活忆畅。像用AFNetworking請(qǐng)求數(shù)據(jù)和GCD實(shí)現(xiàn)多線程,都使用了block回調(diào)晾蜘。

3.block缺點(diǎn)

blcok的運(yùn)行成本高邻眷。block出棧需要將使用的數(shù)據(jù)從棧內(nèi)存拷貝到堆內(nèi)存,當(dāng)然對(duì)象的話就是引用計(jì)數(shù)加1剔交,使用完或者block置nil后才銷(xiāo)毀肆饶。delegate只是保存了一個(gè)對(duì)象指針(一定要用week修飾delegate,不然也會(huì)循環(huán)引用)岖常,直接回調(diào)驯镊,沒(méi)有額外消耗。就像C的函數(shù)指針竭鞍,只多做了一個(gè)查表動(dòng)作板惑。

block容易造成循環(huán)引用,而且不易察覺(jué)偎快。因?yàn)闉榱薭lcok不被系統(tǒng)回收冯乘,所以我們都用copy關(guān)鍵字修飾,實(shí)行強(qiáng)引用晒夹。block對(duì)捕獲的變量也都是強(qiáng)引用裆馒,所以就會(huì)造成循環(huán)引用姊氓。

#import "ViewController.h"

typedef void(^TestBlock)(void);

@interface ViewController ()

{

? ? void (^_testCycleBlock)(void);

}

@end

@implementation ViewController

- (void)viewDidLoad {


? ? [super viewDidLoad];


? ? __weak ViewController *weakSelf = self;

? ? _testCycleBlock = ^{

? ? ? ? /**

? ? ? ? ? //引發(fā)循環(huán)引用

? ? ? ? ? NSLog(@"%@", self);

? ? ? ? */

? ? ? ? //防止循環(huán)引用

? ? ? ? NSLog(@"%@", weakSelf);

? ? };

}

@end

4.如何使用

優(yōu)先使用block。

如果回調(diào)函數(shù)很多喷好,多余三個(gè)使用代理翔横。

如果回調(diào)的很頻繁,次數(shù)很多梗搅,像UITableview禾唁,每次初始化、滑動(dòng)无切、點(diǎn)擊都會(huì)回調(diào)荡短,使用代理。

??block和代理都各有優(yōu)缺點(diǎn)订雾,所以我們一定要理解區(qū)分使用場(chǎng)景肢预,應(yīng)用適合的回調(diào)方式矛洞。優(yōu)化APP的性能洼哎,提高流暢性,從點(diǎn)滴做起沼本。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末噩峦,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子抽兆,更是在濱河造成了極大的恐慌识补,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,948評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件辫红,死亡現(xiàn)場(chǎng)離奇詭異凭涂,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)贴妻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)切油,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人名惩,你說(shuō)我怎么就攤上這事澎胡。” “怎么了娩鹉?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,490評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵攻谁,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我弯予,道長(zhǎng)戚宦,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,521評(píng)論 1 284
  • 正文 為了忘掉前任锈嫩,我火速辦了婚禮受楼,結(jié)果婚禮上困檩,老公的妹妹穿的比我還像新娘。我一直安慰自己那槽,他們只是感情好悼沿,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,627評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著骚灸,像睡著了一般糟趾。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上甚牲,一...
    開(kāi)封第一講書(shū)人閱讀 49,842評(píng)論 1 290
  • 那天义郑,我揣著相機(jī)與錄音,去河邊找鬼丈钙。 笑死非驮,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的雏赦。 我是一名探鬼主播劫笙,決...
    沈念sama閱讀 38,997評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼星岗!你這毒婦竟也來(lái)了填大?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,741評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤俏橘,失蹤者是張志新(化名)和其女友劉穎允华,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體寥掐,經(jīng)...
    沈念sama閱讀 44,203評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡靴寂,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,534評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了召耘。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片百炬。...
    茶點(diǎn)故事閱讀 38,673評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖怎茫,靈堂內(nèi)的尸體忽然破棺而出收壕,到底是詐尸還是另有隱情,我是刑警寧澤轨蛤,帶...
    沈念sama閱讀 34,339評(píng)論 4 330
  • 正文 年R本政府宣布蜜宪,位于F島的核電站,受9級(jí)特大地震影響祥山,放射性物質(zhì)發(fā)生泄漏圃验。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,955評(píng)論 3 313
  • 文/蒙蒙 一缝呕、第九天 我趴在偏房一處隱蔽的房頂上張望澳窑。 院中可真熱鬧斧散,春花似錦、人聲如沸摊聋。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,770評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)麻裁。三九已至箍镜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間煎源,已是汗流浹背色迂。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,000評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工簸喂, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蝙昙,地道東北人映凳。 一個(gè)月前我還...
    沈念sama閱讀 46,394評(píng)論 2 360
  • 正文 我出身青樓牲平,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親歧杏。 傳聞我的和親對(duì)象是個(gè)殘疾皇子砰碴,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,562評(píng)論 2 349

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

  • 轉(zhuǎn)自李峰峰博客 一棒拂、概述 閉包 = 一個(gè)函數(shù)「或指向函數(shù)的指針」+ 該函數(shù)執(zhí)行的外部的上下文變量「也就是自由變量」...
    Joshua520閱讀 979評(píng)論 0 0
  • 1 Block機(jī)制 (Very Good) Block技巧與底層解析 http://www.reibang.com...
    Kevin_Junbaozi閱讀 4,040評(píng)論 3 48
  • 1.ios高性能編程 (1).內(nèi)層 最小的內(nèi)層平均值和峰值(2).耗電量 高效的算法和數(shù)據(jù)結(jié)構(gòu)(3).初始化時(shí)...
    歐辰_OSR閱讀 29,339評(píng)論 8 265
  • 1姑隅、block簡(jiǎn)介 block字面意思就是代碼塊 iOS4.0 Apple引入的特性 block是Objectiv...
    呆子四二閱讀 1,581評(píng)論 1 6
  • 想法写隶,人人都會(huì)倔撞,人人都有讲仰,但事不可為時(shí),所有的想法就是沒(méi)想法痪蝇,想是想了鄙陡,并且想的還很多,解決的法子又該怎樣去...
    文藝年華閱讀 223評(píng)論 0 0