iOS Block用法

ios4.0系統(tǒng)已開始支持block,在編程過程中忍燥,block被Obj-C看成是對象墓卦,它封裝了一段代碼掷贾,這段代碼可以在任何時(shí)候執(zhí)行睛榄。Block可以作為函數(shù)參數(shù)或者函數(shù)的返回值,而其本身又可以帶輸入?yún)?shù)或返回值想帅。它和傳統(tǒng)的函數(shù)指針很類似场靴,但是有區(qū)別:block是inline的,并且它對局部變量是只讀的港准。

1旨剥、block的定義

// 聲明和實(shí)現(xiàn)寫在一起,就像變量的聲明實(shí)現(xiàn) int a = 10;

int(^aBlock)(int,int) = ^(int num1,int num2) {

return num1 * num2;

};

?// 聲明和實(shí)現(xiàn)分開浅缸,就像變量先聲明后實(shí)現(xiàn)

int a;

a = 10;

?int(^cBlock)(int,int);

?cBlock = ^(int num1,int num2)

?{

?return num1 * num2;

?};

其中轨帜,定義了一個(gè)名字為aBlock的block對象,并攜帶了相關(guān)信息:

1衩椒、aBlock 有兩個(gè)形式參數(shù)蚌父,分別為int類型;

2毛萌、aBlock 的返回值為int 類型苟弛;

3、等式右邊就是block的具體實(shí)現(xiàn)阁将;

4嗡午、^ 帶邊block聲明和實(shí)現(xiàn)的標(biāo)示(關(guān)鍵字);

當(dāng)然冀痕,你可以定義其他形式的block。e.g:無返回值狸演,無形式參數(shù)等言蛇;

void(^bBlock)() = ^()

{

int a =10;

printf(num = %d,a);

};


2、block 訪問權(quán)限

block可以訪問局部變量宵距,但是不能修改腊尚。

int a =10;

int(^dBlock)(int) = ^(int num)

{

a++;//not work!

return num * a;

};

此處不能修改的原因是在編譯期間確定的满哪,編譯器編譯的時(shí)候把a(bǔ)的值復(fù)制到block作為一個(gè)新變量(假設(shè)是a'= 10)婿斥,此時(shí)a'和a是沒有關(guān)系的。

這個(gè)地方就是函數(shù)中的值傳遞哨鸭。如果要修改就要加關(guān)鍵字:__block或者static

__block int a =7;

int(^dBlock)(int) = ^(int num)

{

a++;// work民宿!

return num * a;

};


3、block的調(diào)用

block調(diào)用就像調(diào)用函數(shù)一樣像鸡。

int c = aBlock(10,10);

bBlock();


4活鹰、block 的應(yīng)用

假設(shè)我們熟悉代理遞值的話,對代理我們可能又愛有恨!我們先建立模型A頁面 push B頁面志群,如果把A頁面的值傳遞到B頁面着绷,屬性和單例傳值可以搞定!但是如果Pop過程中把B頁面的值傳遞到A頁面锌云,那就可以用單例或者代理了荠医!說到代理,我們要先聲明協(xié)議桑涎,創(chuàng)建代理彬向,很是麻煩。常常我們傳遞一個(gè)數(shù)值需要在兩個(gè)頁面間寫很多代碼石洗,這些代碼改變頁面的整體順序幢泼,可讀性也打了折扣。所以讲衫,此時(shí)缕棵,block是一種優(yōu)化方案!

block傳值得例子

一涉兽、在第二個(gè)視圖控制器的.h文件中定義聲明Block屬性

typedef void (^ReturnTextBlock)(NSString *showText);

@interface TextFieldViewController : UIViewController

@property (nonatomic, copy) ReturnTextBlock returnTextBlock;

- (void)returnText:(ReturnTextBlock)block;

@end

第一行代碼是為要聲明的Block重新定義了一個(gè)名字

ReturnTextBlock

這樣招驴,下面在使用的時(shí)候就會(huì)很方便。

第三行是定義的一個(gè)Block屬性

第四行是一個(gè)在第一個(gè)界面?zhèn)鬟M(jìn)來一個(gè)Block語句塊的函數(shù)枷畏,不用也可以别厘,不過加上會(huì)減少代碼的書寫量

二、實(shí)現(xiàn)第二個(gè)視圖控制器的方法

- (void)returnText:(ReturnTextBlock)block?

{

self.returnTextBlock = block;

}

?- (void)viewWillDisappear:(BOOL)animated?

?{

?if(self.returnTextBlock !=nil)?

?{

?self.returnTextBlock(self.inputTF.text);

?}

}

其中inputTF是視圖中的UITextField拥诡。

第一個(gè)方法就是定義的那個(gè)方法触趴,把傳進(jìn)來的Block語句塊保存到本類的實(shí)例變量returnTextBlock(.h中定義的屬性)中,然后尋找一個(gè)時(shí)機(jī)調(diào)用渴肉,而這個(gè)時(shí)機(jī)就是上面說到的冗懦,當(dāng)視圖將要消失的時(shí)候,需要重寫:

- (void)viewWillDisappear:(BOOL)animated;

三仇祭、在第一個(gè)視圖中獲得第二個(gè)視圖控制器披蕉,并且用第二個(gè)視圖控制器來調(diào)用定義的屬性

如下方法中書寫:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender

{

// Get the new view controller using [segue destinationViewController].

// Pass the selected object to the new view controller.

TextFieldViewController *tfVC = segue.destinationViewController;

[tfVC returnText:^(NSString *showText) {

self.showLabel.text = showText;

}];

}

可以看到代碼中的注釋,系統(tǒng)告訴我們可以用[segue destinationViewController]來獲得新的視圖控制器乌奇,也就是我們說的第二個(gè)視圖控制器没讲。

這時(shí)候上面(第一步中)定義的那個(gè)方法起作用了,如果你寫一個(gè)[tfVC returnText按回車,系統(tǒng)會(huì)自動(dòng)提示出來一個(gè):

tfVC returnText:<#^(NSString *showText)block#>

的東西礁苗,我們只要在焦點(diǎn)上回車爬凑,就可以快速創(chuàng)建一個(gè)代碼塊了,大家可以試試寂屏。這在寫代碼的時(shí)候是非常方便的贰谣。


5娜搂、 block的內(nèi)存管理

block本身是像對象一樣可以retain,和release吱抚。但是百宇,block在創(chuàng)建的時(shí)候,它的內(nèi)存是分配在棧(stack)上秘豹,而不是在堆(heap)上携御。他本身的作用域是屬于創(chuàng)建時(shí)候的作用域,一旦在創(chuàng)建時(shí)候的作用域外面調(diào)用block將導(dǎo)致程序崩潰既绕。比如下面的例子啄刹。 我在view did load中創(chuàng)建了一個(gè)block:

- (void)viewDidLoad

{

[super viewDidLoad];

int number = 1;

_block = ^(){

NSLog(@number: %d, number);

};

}

并且在一個(gè)按鈕的事件中調(diào)用了這個(gè)block:

- (IBAction)testDidClick:(id)sender {

_block();

}

此時(shí)我按了按鈕之后就會(huì)導(dǎo)致程序崩潰,解決這個(gè)問題的方法就是在創(chuàng)建完block的時(shí)候需要調(diào)用copy的方法凄贩。copy會(huì)把block從棧上移動(dòng)到堆上誓军,那么就可以在其他地方使用這個(gè)block了~ 修改代碼如下:

_block = ^(){

NSLog(@number %d, number);

};

_block = [_block copy];

同理,特別需要注意的地方就是在把block放到集合類當(dāng)中去的時(shí)候疲扎,如果直接把生成的block放入到集合類中昵时,是無法在其他地方使用block,必須要對block進(jìn)行copy椒丧。不過代碼看上去相對奇怪一些:

[array addObject:[[^{

NSLog(@hello!);

} copy] autorelease]];


6壹甥、循環(huán)引用

對于非ARC下, 為了防止循環(huán)引用, 我們使用__block來修飾在Block中使用的對象:

對于ARC下, 為了防止循環(huán)引用, 我們使用__weak來修飾在Block中使用的對象。原理就是:ARC中壶熏,Block中如果引用了__strong修飾符的自動(dòng)變量句柠,則相當(dāng)于Block對該變量的引用計(jì)數(shù)+1。

這一點(diǎn)其實(shí)是在第一點(diǎn)的一個(gè)小的衍生棒假。當(dāng)在block內(nèi)部使用成員變量的時(shí)候溯职,比如

@interface ViewController : UIViewController

{

NSString *_string;

}

@end

在block創(chuàng)建中:

_block = ^(){

NSLog(@string %@, _string);

};

這里的_string相當(dāng)于是self->_string;那么block是會(huì)對內(nèi)部的對象進(jìn)行一次retain帽哑。也就是說缸榄,self會(huì)被retain一次。當(dāng)self釋放的時(shí)候祝拯,需要block釋放后才會(huì)對self進(jìn)行釋放,但是block的釋放又需要等self的dealloc中才會(huì)釋放她肯。如此一來變形成了循環(huán)引用佳头,導(dǎo)致內(nèi)存泄露。

修改方案是新建一個(gè)__block scope的局部變量晴氨,并把self賦值給它康嘉,而在block內(nèi)部則使用這個(gè)局部變量來進(jìn)行取值。因?yàn)開_block標(biāo)記的變量是不會(huì)被自動(dòng)retain的籽前。

__block ViewController *controller = self;

_block = ^(){

NSLog(@string %@, controller->_string);

};

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末亭珍,一起剝皮案震驚了整個(gè)濱河市敷钾,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌肄梨,老刑警劉巖阻荒,帶你破解...
    沈念sama閱讀 216,843評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異众羡,居然都是意外死亡侨赡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,538評論 3 392
  • 文/潘曉璐 我一進(jìn)店門粱侣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來羊壹,“玉大人,你說我怎么就攤上這事齐婴∮兔ǎ” “怎么了?”我有些...
    開封第一講書人閱讀 163,187評論 0 353
  • 文/不壞的土叔 我叫張陵柠偶,是天一觀的道長情妖。 經(jīng)常有香客問我,道長嚣州,這世上最難降的妖魔是什么鲫售? 我笑而不...
    開封第一講書人閱讀 58,264評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮该肴,結(jié)果婚禮上情竹,老公的妹妹穿的比我還像新娘。我一直安慰自己匀哄,他們只是感情好秦效,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,289評論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著涎嚼,像睡著了一般棘街。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上贤壁,一...
    開封第一講書人閱讀 51,231評論 1 299
  • 那天妈候,我揣著相機(jī)與錄音,去河邊找鬼立哑。 笑死夜惭,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的铛绰。 我是一名探鬼主播诈茧,決...
    沈念sama閱讀 40,116評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼捂掰!你這毒婦竟也來了敢会?” 一聲冷哼從身側(cè)響起曾沈,我...
    開封第一講書人閱讀 38,945評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎鸥昏,沒想到半個(gè)月后塞俱,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,367評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡互广,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,581評論 2 333
  • 正文 我和宋清朗相戀三年敛腌,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片惫皱。...
    茶點(diǎn)故事閱讀 39,754評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡像樊,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出旅敷,到底是詐尸還是另有隱情生棍,我是刑警寧澤,帶...
    沈念sama閱讀 35,458評論 5 344
  • 正文 年R本政府宣布媳谁,位于F島的核電站涂滴,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏晴音。R本人自食惡果不足惜柔纵,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,068評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望锤躁。 院中可真熱鬧搁料,春花似錦、人聲如沸系羞。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,692評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽椒振。三九已至昭伸,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間澎迎,已是汗流浹背庐杨。 一陣腳步聲響...
    開封第一講書人閱讀 32,842評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留夹供,地道東北人辑莫。 一個(gè)月前我還...
    沈念sama閱讀 47,797評論 2 369
  • 正文 我出身青樓,卻偏偏與公主長得像罩引,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子枝笨,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,654評論 2 354

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

  • 《Objective-C高級編程》是一本有趣又難懂的書袁铐,全書就講了引用計(jì)數(shù)揭蜒、Block、GCD三個(gè)概念剔桨,有趣是因?yàn)?..
    kamous閱讀 55,228評論 22 206
  • 前言 Blocks是C語言的擴(kuò)充功能屉更,而Apple 在OS X Snow Leopard 和 iOS 4中引入了這...
    小人不才閱讀 3,768評論 0 23
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)洒缀,斷路器瑰谜,智...
    卡卡羅2017閱讀 134,652評論 18 139
  • 哇!今天好不容易第一次完成了一天走一萬步的目標(biāo)树绩。自從聽說最好的鍛煉就是每天走上一萬步后萨脑,覺得很容易實(shí)現(xiàn)就默默在心里...
    黃云龍閱讀 312評論 0 1
  • 今天周日,兒子睡到十一點(diǎn)才起床饺饭,本來對我還有很大的情緒渤早,我把給他買手機(jī)的事告訴了他,他心情由陰轉(zhuǎn)晴瘫俊,馬上起床吃了早...
    不忘初心堅(jiān)持到底閱讀 164評論 2 1