Block塊

1、Blocks簡(jiǎn)介
Block字面意思就是代碼塊(含義) iOS4.0缩多、Mac OS X 10.6開始Apple引入的特性(引入時(shí)間)
Block是Objective C語(yǔ)言中的對(duì)象 但是與NSObject有所區(qū)別 Block是特殊的Objective C對(duì)象 (block是OC的特殊對(duì)象)

Block 對(duì)象提供了一個(gè)使用 C 語(yǔ)言和 C 派生語(yǔ)言(如 Objective-C 和 C++)來(lái)創(chuàng)建表達(dá)式作為一個(gè)特別的函數(shù)嗦董。(block特殊之處)
在其他語(yǔ)言和環(huán)境中,一個(gè)block對(duì)象有時(shí)候被稱為“閉包(closure)”曹宴。在這里,它們通常被口語(yǔ)化為”塊(blocks)”,除非在某些范圍它們?nèi)菀缀蜆?biāo)準(zhǔn) C 表達(dá)式的塊代碼混淆。
對(duì)于閉包(closure),有很多定義往弓,其中閉包就是能夠讀取其它函數(shù)內(nèi)部變量的函數(shù)

“^”符號(hào)可以稱為caret ['k?r?t] 也叫脫字符 插入符

block.png

返回值(^塊對(duì)象名稱)(參數(shù)列表類型) = ^(參數(shù)列表){塊對(duì)象中的代碼};

2粒梦、用處

1)簡(jiǎn)單的回調(diào)過(guò)程亮航,不用再實(shí)現(xiàn)并調(diào)用某個(gè)函數(shù) (UIView動(dòng)畫)
2)代碼簡(jiǎn)潔,減少冗余代碼
3)與GCD結(jié)合使用 爽爆了

使用:UIView動(dòng)畫匀们、presentViewController缴淋、ASI

3、聲明和創(chuàng)建Block
聲明Block引用 無(wú)參無(wú)返回 無(wú)參有返回 有參無(wú)返回 有參有返回

定義Block

使用Block

typedef聲明 簡(jiǎn)稱typedef 為現(xiàn)有類型創(chuàng)建一個(gè)新的名字泄朴,或稱為類型別名重抖,在結(jié)構(gòu)體定義,還有一些數(shù)組等地方都會(huì)用到

返回值或參數(shù)為Block的

snippet 代碼片段

4祖灰、Block對(duì)變量存取管理
1)局部變量
局部變量钟沛,在Block中只讀。Block定義時(shí)copy變量的值局扶,在Block中作為常量使用恨统,所以即使變量的值在Block外改變,也不影響它在Block中的值

2)__Block修飾的變量
如果要在block內(nèi)修改block外聲明的局部變量三妈,那么一定要對(duì)該變量加__block標(biāo)記

3)Static修飾符的或全局變量
因?yàn)槿肿兞炕蜢o態(tài)變量在內(nèi)存中的地址是固定的畜埋,Block在讀取該變量值的時(shí)候是直接從其所在內(nèi)存讀出,獲取到的是最新值畴蒲,而不是在定義時(shí)copy的常量.

Block變量悠鞍,被__Block修飾的變量稱作Block變量。 基本類型的Block變量等效于全局變量或靜態(tài)變量 但對(duì)象的block變量不會(huì)

5模燥、Block的內(nèi)存管理
非ARC下
Block是默認(rèn)建立在棧上, 所以如果離開方法作用域, Block就會(huì)被丟棄

Block的copy咖祭、retain、release操作 不同于NSObject的copy蔫骂、retain么翰、release操作:

只要實(shí)現(xiàn)一個(gè)對(duì)周圍變量沒(méi)有引用的Block,就會(huì)顯示為是NSGlobalBlock
如果其中加入了對(duì)局部變量的引用辽旋,就是NSStackBlock
如果你對(duì)一個(gè)NSStackBlock對(duì)象使用了Block_copy()或者發(fā)送了copy消息硬鞍,就會(huì)得到NSMallocBlock

1)NSGlobalBlock:retain、copy、release操作都無(wú)效固该;
2)NSStackBlock:retain锅减、release操作無(wú)效,必須注意的是伐坏,NSStackBlock在函數(shù)返回后怔匣,Block內(nèi)存將被回收。即使retain也沒(méi)用桦沉。容易犯的錯(cuò)誤是[mutableAarry addObject:stackBlock]每瞒,(補(bǔ):在ARC中不用擔(dān)心此問(wèn)題,因?yàn)锳RC中會(huì)默認(rèn)將實(shí)例化的Block拷貝到堆上)在函數(shù)出棧后纯露,從mutableAarry中取到的stackBlock已經(jīng)被回收剿骨,變成了野指針。正確的做法是先將[stackBlock copy]到堆上埠褪,然后加入數(shù)組:[mutableAarry addObject:[[stackBlock copy] autorelease]]浓利。支持copy,copy之后生成新的NSMallocBlock類型對(duì)象钞速。
3)NSMallocBlock支持retain贷掖、release,雖然retainCount始終是1渴语,但內(nèi)存管理器中仍然會(huì)增加苹威、減少計(jì)數(shù)。copy之后不會(huì)生成新的對(duì)象驾凶,只是增加了一次引用牙甫,類似retain;
4)Block_copy與copy等效调违,Block_release與release等效窟哺;
5)對(duì)Block不管是retain、copy翰萨、release都不會(huì)改變引用計(jì)數(shù)retainCount,retainCount始終是1糕殉;
6)盡量不要對(duì)Block使用retain操作,不方便管理亩鬼。

Block的使用:UIView動(dòng)畫、presentViewController阿蝶、ASI

6雳锋、Block對(duì)objc對(duì)象的內(nèi)存管理
staticObj、instanceObj羡洁、localObj玷过、blockObj多種類型obj對(duì)象
主要是block被copy時(shí)其塊中用到的變量的引用計(jì)數(shù)
1)非ARC
staticObj在內(nèi)存中的位置是確定的,所以Block copy時(shí)引用計(jì)數(shù)不會(huì)改變。
instanceObj在Block copy時(shí)并沒(méi)有直接讓instanceObj對(duì)象本身引用計(jì)數(shù)加1辛蚊,但卻讓self引用計(jì)數(shù)加1粤蝎。所以在Block中可以直接讀寫instanceObj變量。
localObj在Block copy時(shí)袋马,系統(tǒng)自動(dòng)增加其引用計(jì)數(shù)初澎。
blockObj在Block copy時(shí)引用計(jì)數(shù)也不會(huì)改變。
使用__block避免循環(huán)引用 __block 類 *對(duì)象 = self

void(^block)(void)= ^{
[blockSelf doSomething];
};

Tips:
內(nèi)存主要分為
1.棧 - 由編譯器自動(dòng)分配釋放 里面的變量通常是局部變量 函數(shù)參數(shù)等
2.堆 - 一般由程序員分配釋放虑凛,若程序員不釋放碑宴,程序結(jié)束時(shí)可能由OS回收 alloc
3.全局區(qū)(靜態(tài)區(qū) static),全局變量和靜態(tài)變量的存儲(chǔ)是放在一塊的桑谍,初始化的全局變量和靜態(tài)變量在一塊區(qū)域延柠,未初始化的全局變量和未初始化的靜態(tài)變量在相鄰的另一塊區(qū)域。- 程序結(jié)束釋放 static
People *p; People *p2 = nil;
4.另外還有一個(gè)專門放常量的地方锣披。- 程序結(jié)束釋放 NSString *lastName = @“xue”;
lastName = @“dkjs”;
5贞间、方法區(qū)


Block的寫法:

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

int(^myBlock1)(int) = ^(int num){
    returen num;
}
//block的調(diào)用
myBlock1(3);

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

//block的聲明  如果沒(méi)有參數(shù)聲明時(shí)必須寫(void) 實(shí)現(xiàn)的時(shí)候可以寫(void)也可以不寫
void(^myblock2)(void) =^(void){
    NSLog(@"我是joye");
};
myblock2();

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

 //無(wú)返回值 有3個(gè)參數(shù)的block 多個(gè)參數(shù)要以逗號(hào)分隔
  void (^myblock3)(int,float,NSString*) =^(int a,float b,NSString*name){
    NSLog(@"%d----%f----%@",a,b,name);
};
myblock3(5,6.0,@"張三");

4.要定義block的全局變量的方法
#import <UIKit/UIKit.h> //用其代表在.h 文件中
@interface AppDelegate : UIResponder <UIApplicationDelegate>
{
void(^myblock4)(void);
UILabel *(^myblock5)(void);
}
@end
#import "AppDelegate.h" //用其代表在.m 文件中
myblock4= ^{
NSLog(@"123456");
};
myblock4();
myblock5 =^{
UILabel *label =[[UILabel alloc] init];
return label;
};
UILabel *label = myblock5();
5.當(dāng)多次重復(fù)輸入格式相同的塊時(shí) 可以給這個(gè)類型起一個(gè)別名 方便創(chuàng)建相同類型的block 在.h中聲明

//類型定義  相當(dāng)于給某種類型 起了一個(gè)別名 方便我們創(chuàng)建相同類型block

#import <UIKit/UIKit.h>
typedef void(^totalBlock)(void);
@interface AppDelegate : UIResponder <UIApplicationDelegate>
{
    totalBlock myblock6;
}
#import "AppDelegate.h"
//使用類型定義創(chuàng)建全局block
myblock6 =^{

};
myblock6();

6.類型定義 如果參數(shù)的位置不同 不能使用同一個(gè)block創(chuàng)建

#import <UIKit/UIKit.h>
//類型定義只能使用定義好的類型 如果參數(shù)位置不一樣 也不能使用同一個(gè)block創(chuàng)建
typedef NSString*(^totalBlock1)(NSString*,int);
typedef NSString*(^totalBlock2)(int, NSString*);
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@end
#import "AppDelegate.h"
totalBlock1 myblock7 =^(NSString *name,int a){
    return name;
};
myblock7(@"joye",1)

block內(nèi)存管理

1.在Block內(nèi)部 使用 外部 局部變量 如果一個(gè)外部局部變量沒(méi)有經(jīng)過(guò)__block描述 就在內(nèi)部使用 那么當(dāng)前變量就會(huì)被copy一份新值

int a = 100;
a = 200;
void(^myBlock)(void)=^{
    NSLog(@"%d",a);
};
a = 300;
a = 400;
myBlock();

//輸出結(jié)果 a 的值為200

2.如果不想在block內(nèi)部copy 要用__block描述

__block int b = 1111;
b = 2222;
void (^myBlock2)(void)=^{
    NSLog(@"%d",b);
};
b = 3333;
myBlock2();
//輸出結(jié)果 a 的值為 3333

3.block 使用全局變量 那么不會(huì)進(jìn)行copy

{
  int c;
}

c = 1000;
c = 2000;
void(^myBlock3)(void)=^{
    NSLog(@"%d",c);
};
c = 3000;
myBlock3();

//輸出的 c 的值為3000

4.被static描述變量是 不copy 使用原值

static int d = 123;
d = 321;
void(^myBlock4)(void)=^{
    NSLog(@"%d",d);
};
d = 456;
myBlock4();

//輸出的 d 的值為123

要在 block 內(nèi)部 修改外部局部變量 要加 ____block__ 或 ____weak__ 描述
在 block 內(nèi)部修改全局變量和靜態(tài)變量 不用加 ____block__

__block int e = 666;
void(^myBlock5)(void)=^{
    NSLog(@"%d",e);
    e = 999;
};
myBlock5();

總結(jié):當(dāng)變量被 __block 或者 static 描述 或者使用的變量是全局變量時(shí) 在block內(nèi)部使用都不進(jìn)行copy 而是使用原值


內(nèi)存相關(guān)

內(nèi)存分區(qū):
棧:不需要程序員進(jìn)行管理 基本數(shù)據(jù)類型
堆:需要程序員進(jìn)行管理 對(duì)象類型
全局區(qū)(靜態(tài)區(qū)) 全局和靜態(tài)變量
常量區(qū) NSString*str = @“123”;
方法區(qū)

//默認(rèn)是在棧區(qū)創(chuàng)建Block,出了當(dāng)前方法block會(huì)被系統(tǒng)釋放
//__NSGlobalBlock__ 是在沒(méi)有使用任何外部變量時(shí)block的類型
//__NSStackBlock__ 使用了外部變量后block的類型
//不管是 __NSGlobalBlock__ 還是 __NSStackBlock__ 都在棧區(qū)
//__NSGlobalBlock__ 使用retain copy release等內(nèi)存管理的關(guān)鍵字 都是無(wú)效的
//__NSStackBlock__ 使用retain release依然無(wú)效 但是使用copy有效

//__NSMallocBlock__ 當(dāng)block為 __NSStackBlock__ 類型時(shí) 進(jìn)行copy后變成 __NSMallocBlock__ 類型
//__NSMallocBlock__ 是在堆上面創(chuàng)建的 可以對(duì)其retain copy release盈罐,但是進(jìn)行這些內(nèi)存操作后 引用系數(shù)一直為1 但不代表引用計(jì)數(shù)沒(méi)有增加 不建議對(duì)其retain操作
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末榜跌,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子盅粪,更是在濱河造成了極大的恐慌钓葫,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,324評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件票顾,死亡現(xiàn)場(chǎng)離奇詭異础浮,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)奠骄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門豆同,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人含鳞,你說(shuō)我怎么就攤上這事影锈。” “怎么了蝉绷?”我有些...
    開封第一講書人閱讀 162,328評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵鸭廷,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我熔吗,道長(zhǎng)辆床,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,147評(píng)論 1 292
  • 正文 為了忘掉前任桅狠,我火速辦了婚禮讼载,結(jié)果婚禮上轿秧,老公的妹妹穿的比我還像新娘。我一直安慰自己咨堤,他們只是感情好菇篡,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,160評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著吱型,像睡著了一般逸贾。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上津滞,一...
    開封第一講書人閱讀 51,115評(píng)論 1 296
  • 那天铝侵,我揣著相機(jī)與錄音,去河邊找鬼触徐。 笑死咪鲜,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的撞鹉。 我是一名探鬼主播疟丙,決...
    沈念sama閱讀 40,025評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼鸟雏!你這毒婦竟也來(lái)了享郊?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,867評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤孝鹊,失蹤者是張志新(化名)和其女友劉穎炊琉,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體又活,經(jīng)...
    沈念sama閱讀 45,307評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡苔咪,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,528評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了柳骄。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片团赏。...
    茶點(diǎn)故事閱讀 39,688評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖耐薯,靈堂內(nèi)的尸體忽然破棺而出舔清,到底是詐尸還是另有隱情,我是刑警寧澤曲初,帶...
    沈念sama閱讀 35,409評(píng)論 5 343
  • 正文 年R本政府宣布体谒,位于F島的核電站,受9級(jí)特大地震影響复斥,放射性物質(zhì)發(fā)生泄漏营密。R本人自食惡果不足惜械媒,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,001評(píng)論 3 325
  • 文/蒙蒙 一目锭、第九天 我趴在偏房一處隱蔽的房頂上張望评汰。 院中可真熱鬧,春花似錦痢虹、人聲如沸被去。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)惨缆。三九已至,卻和暖如春丰捷,著一層夾襖步出監(jiān)牢的瞬間坯墨,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工病往, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留捣染,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,685評(píng)論 2 368
  • 正文 我出身青樓停巷,卻偏偏與公主長(zhǎng)得像耍攘,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子畔勤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,573評(píng)論 2 353

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

  • iOS代碼塊Block 概述 代碼塊Block是蘋果在iOS4開始引入的對(duì)C語(yǔ)言的擴(kuò)展,用來(lái)實(shí)現(xiàn)匿名函數(shù)的特性,B...
    smile刺客閱讀 2,347評(píng)論 2 26
  • 前言 Blocks是C語(yǔ)言的擴(kuò)充功能蕾各,而Apple 在OS X Snow Leopard 和 iOS 4中引入了這...
    小人不才閱讀 3,768評(píng)論 0 23
  • 《Objective-C高級(jí)編程》這本書就講了三個(gè)東西:自動(dòng)引用計(jì)數(shù)、block庆揪、GCD式曲,偏向于從原理上對(duì)這些內(nèi)容...
    WeiHing閱讀 9,810評(píng)論 10 69
  • 一、Objective-C發(fā)展史 Objective-C從1983年誕生嚷硫,已經(jīng)走過(guò)了30多年的歷程检访。隨著時(shí)間的推移...
    沒(méi)事蹦蹦閱讀 5,830評(píng)論 12 34
  • Block使用場(chǎng)景,可以在兩個(gè)界面的傳值仔掸,也可以對(duì)代碼封裝作為參數(shù)的傳遞等脆贵。用過(guò)GCD就知道Block的精妙之處。...
    Coder_JMicheal閱讀 723評(píng)論 2 1