一、block應(yīng)用范圍
1、動畫的轉(zhuǎn)場
2、網(wǎng)絡(luò)的事件處理
3、兩個對象或者多個對象之間的通訊
4、多線程的處理
(從iOS4.0開始就應(yīng)用得非常廣泛)
二、Block
block和C語言中的函數(shù)(函數(shù)指針)有些類似,但需要編譯器和運行時的堆或棧的支持,主要用在回調(diào)函數(shù)的地方,當(dāng)兩個對象進行通訊需要回調(diào)的時候廣泛應(yīng)用block,在一些小的操作當(dāng)中可以很好代替代理來作為回調(diào)操作的支撐。
三、Block和C語言函數(shù)指針的區(qū)別
/*
C 函數(shù)指針 typedef 定義
typedef int (* SumBlockT)(int a);
*/
int (* AFunc) (int a) //C 函數(shù)指針
/*
Block typedef 定義
typedef int (^ SumBlockT)(int a, int b);
*/
int (^ BFunc) (int a, int b) // Blocks
四、調(diào)用Block
void (^ myblock_1)(void); //申明block,變量是myblocks_1
void (^ myblock_2)(void) = NULL; //申明block,myblocks_2賦值為空
myblock_2 = ^(void)
{
NSLog(@"只是賦值,可以說是這block函數(shù)塊賦值給myblocks_2");
};
myblock_2(); //執(zhí)行myblock_2 ,運行結(jié)果如下。

int (^ myblock_3)(int a,int b) =^(int a, int b)
{
int c = a+b;
return c;
};
int a = myblock_3(10,20);
NSLog(@"%d",a);

_ _block int sum = 0;
int (^myblock4)(int a, int b) =^(int a ,int b){
sum = a+b;
return sum;
};
myblock4(20,30);
NSLog(@"%d",sum);

// 定義block 的 typedef
typedef int (^SumBlock)(int a, int b);
SumBlock myblock5 = ^ (int a,int b){
NSLog(@"%d",a+b);
return 0;
};
myblock5(50,10);
五、兩個代理之間通過Block通訊
Dog 跟 Person 之間的通訊
Dog.h文件
#import <Foundation/Foundation.h>
@interface Dog : NSObject
{
int _ID;
int _barkCount;
NSTimer * timer;//定時器,定時發(fā)送信息
//定義一個block變量
void (^ BarkCallback)(Dog * thisDog,int count);
}
@property (assign)int ID;
//向外暴露一個函數(shù) setBark: ,給 person 對象使用
-(void) setBark:( void (^)(Dog * thisDog,int count))eachBrak;
@end
#pragma mark ----------Dog.m 文件-------------------------------------------
#import "Dog.h"
@implementation Dog
@synthesize ID = _ID;
-(id)init
{
self = [super init];
if (self) {
timer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(updateTimer:) userInfo:nil repeats:YES];
}
return self;
}
-(void)updateTimer:(id)arg
{
_barkCount++;
NSLog(@"dog_ID %d barkCount %d",_ID ,_barkCount);
//給 person 匯報一下
// 調(diào)用 person 里面的 block
if (BarkCallback) {
BarkCallback(self,_barkCount);//調(diào)用從person傳過來的block
}
}
-(void) setBark:( void (^)(Dog * thisDog,int count) )eachBrak
{
BarkCallback = nil;
BarkCallback = [eachBrak copy];
}
-(void)dealloc
{
BarkCallback = nil;
}
@end
#pragma mark ----------Person.h 文件-------------------------------------------
#import <Foundation/Foundation.h>
#import "Dog.h"
@interface Person : NSObject
{
Dog *_dog;
}
@property(retain) Dog *dog;
@end
#pragma mark ----------Person.m 文件-------------------------------------------
#import "Person.h"
@implementation Person
@synthesize dog = _dog;
-(void) setDog:(Dog *)dog
{
if (_dog != dog){
_dog = nil;
_dog = dog;
[_dog setBark:^(Dog *thisDog, int count) {
NSLog(@"person dog^ID %d count %d",[thisDog ID],count);
}];
}
}
-(Dog *) dog
{
return _dog;
}
-(void)dealloc
{
self.dog = nil;
}
@end
#pragma mark ----------main.m 文件 實現(xiàn)-------------------------------------------
Person * xiaoLi = [[Person alloc] init];
Dog *dog = [[Dog alloc]init];
[dog setID:10];
[xiaoLi setDog:dog];
while (1) {
[[NSRunLoop currentRunLoop]run];
}
輸出結(jié)果如圖下:

六、_ _block關(guān)鍵字
一個block內(nèi)部可以引用自身作用外域的變量(static變量、extern變量、自由變量),定義變量時,不加存儲修飾符,默認(rèn)是自由變量(auto),auto變量保存在stack中,除了auto還存在register、static等存儲修飾符;自由變量在 Block 中是只讀的,在引入 block 的同時,還引入來一種特殊的 _ _block關(guān)鍵字變量存儲修飾符。
七、block 塊回調(diào)產(chǎn)生的強引用
上面的第五demo只是一部分,在實際開發(fā)過程中,比如很多網(wǎng)絡(luò)請求的操作是要執(zhí)行回調(diào)提供UI使用的,這個時候就會產(chǎn)生強引用內(nèi)存泄漏的問題,雙方互相持有,由于強引用的關(guān)系雙方都沒有其中一方去執(zhí)行釋放,這個時候就是雙向強引用所產(chǎn)的問題。
那么在很多OC 或者 Swift 的語法上也有很多用到了 block 回調(diào),為什么沒有產(chǎn)生強引用內(nèi)存泄漏的問題呢,那是因為官方在語法內(nèi)部做了操作,總的來說就是把雙向強引用變成單向強引用,也就是有其中一方變成了弱引用先釋放掉了,另一方自然也就釋放掉了。
下面舉個例子,把雙向強引用變成單向強引用,也是最常的block回調(diào)操作之一
@implementation ViewController
-(void)working
{
//執(zhí)行網(wǎng)絡(luò)數(shù)據(jù)請求并回調(diào)
NetWork * net_joke = [[NetWork alloc]init];
__weak typeof(net_joke) net = net_joke; /// 強引用變成弱引用
// net_joke 的變成弱引用 net 在執(zhí)行完block回調(diào)操作后,net_joke就會釋放
NSMutableArray * model_Array = [NSMutableArray array];
[net setBark:^(NSDictionary *dic) {
NSArray * result = dic[@"result"];
// int count = 0;
if (result) {
for (NSDictionary * jokeDic in result) {
Joke_Model * joke = [[Joke_Model alloc]init];
[joke setTitle:jokeDic[@"title"]];
[joke setContent:jokeDic[@"content"]];
[model_Array addObject:joke];
Joke_Model * j = [[Joke_Model alloc]init];
j = model_Array[count];
// count++;
NSLog(@"%@,\n%@",j.title,j.content);
joke = nil;
j = nil;
}
}
}];
}