Block

Block究竟有哪些稱呼和官方的解釋。

匿名函數(shù),塊函數(shù),塊,block基本上他們都是同一個鳥人。

維基百科中說,Block是Apple Inc.為C,C++,以及OC 添加的新特性,使得它們可以用lambda表達式的語法來創(chuàng)建閉包.(lambda表達式既匿名函數(shù)表達式,閉包既是可以包含自由(未綁定到特定對象)變量的代碼塊,具體可以自己下去認真理解下)。我理解為block就是用匿名函數(shù)表達式創(chuàng)建的代碼塊.

閉包就是能夠讀取其它函數(shù)內(nèi)部變量的函數(shù)

什么時候使用block.

Block除了能夠定義參數(shù)列表、返回類型外,還能夠獲取被定義時的詞法范圍內(nèi)的狀態(tài)(比如局部變量),并且在一定條件下(比如使用__block變量)能夠修改這些狀態(tài)。此外,這些可修改的狀態(tài)在相同詞法范圍內(nèi)的多個block之間是共享的,即便出了該詞法范圍(比如棧展開,出了作用域),仍可以繼續(xù)共享或者修改這些狀態(tài)。通常來說,block都是一些簡短代碼片段的封裝,適用作工作單元,通常用來做并發(fā)任務、遍歷、以及回調(diào)。

block如何聲明

[轉(zhuǎn)載]iOS中block實際應用初探

int (*CFunc)(int a) 函數(shù)調(diào)用 int result = CFunc(10);

int (^BFunc)(int a) 函數(shù)調(diào)用 int result = BFunc(10);

block用法1

void (^myblocks) (void) = NULL;

myblocks = ^(void) {

NSLog(@"in blocks");

};

NSLog(@"before myblocks");

myblocks();

NSLog(@"after myblocks");

int (^myblocks2) (int a, int b) = ^(int a, int b) {

int c = a + b;

return c;

};

NSLog(@"before blocks2");

int ret = myblocks2(10, 20);

NSLog(@"after blocks2 ret %d", ret);

//此處如果不加__block會報錯

__block int sum = 0;

int (^myblocks3) (int a, int b) = ^(int a, int b) {

sum = a + b;

return 3;

};

myblocks3(20, 30);

NSLog(@"sum is %d", sum);

對于這種用法,本人不才,基本沒有在實際項目中用過.因為我的理解這實際意義不大(如果是這種簡單的計算),唯一作用是提高程序的并發(fā)性.

回調(diào)是block一個重要的特性.

block回調(diào)是我在網(wǎng)絡請求中用得最多的.

這里先用前輩在ASIHTTP中的block為例子.

定義block

#if NS_BLOCKS_AVAILABLE

typedef void (^ASIBasicBlock)(void);

typedef void (^ASIHeadersBlock)(NSDictionary *responseHeaders);

typedef void (^ASISizeBlock)(long long size);

typedef void (^ASIProgressBlock)(unsigned long long size, unsigned long long total);

typedef void (^ASIDataBlock)(NSData *data);

#endif

此定義可以是全局的block,

這里只用了上門定義的其中一個block為例,作為ASIHTTPRequest的一個屬性.(意思是block可以作為一個對象的屬性存在)

@interface ASIHTTPRequest : NSOperation {

ASIBasicBlock completionBlock;

}

//向外暴露一個接口? 這里是為回調(diào)留一接口方法,其實也可以不用留

- (void)setCompletionBlock:(ASIBasicBlock)aCompletionBlock;

方法實現(xiàn)(這里用release是為開啟arc)

@implementation ASIHTTPRequest

- (void)setCompletionBlock:(ASIBasicBlock)aCompletionBlock

{

[completionBlock release];

completionBlock = [aCompletionBlock copy];

}

這里是網(wǎng)絡請求完成后的方法,在這里實現(xiàn)我們block的調(diào)用.

- (void)reportFinished

{

#if NS_BLOCKS_AVAILABLE

if(completionBlock){

completionBlock();

}

#endif

}

@end

如下,然后你可以在你請求網(wǎng)絡的類實現(xiàn)中,實現(xiàn)網(wǎng)絡請求并獲取網(wǎng)絡請求成功后的回調(diào), 這里可以回傳參數(shù)變量(我們這個例子block是回傳的參數(shù)為void,--typedef void (^ASIBasicBlock)(void)--).在這里回傳參數(shù)就是,上面說的參數(shù)共享,就象遍歷數(shù)組,這樣也許你更能理解

[arr enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {

}];

這里的obj 和idx 以及stop都可以為你在回調(diào)時候所用,就好比代理delegate回傳參數(shù)一樣.

ASIHTTPRequest *request = [self requestWithUrl:url];

//請求成功

[request setCompletionBlock:^{

switch (request.responseStatusCode) {

case RequestStatus_OK:

complete(request.responseString);break;

case RequestStatus_ErrorRequest:

failed(@"錯誤的請求");break;

case RequestStatus_NotFound:

failed(@"找不到指定的資源");break;

case RequestStatus_Error:

failed(@"內(nèi)部服務器錯誤");break;

default:

failed(@"服務器出錯");break;

}

}];

//請求失敗

[request setFailedBlock:^{

failed(@"網(wǎng)絡連接失敗");

}];

這里的FailedBlock我們沒有舉例實現(xiàn).



看了前輩的block實現(xiàn),兄弟伙寫是否有所理解?接下來看看,我寫的一個block的簡單用法.

第一種,接網(wǎng)絡請求的block自己再次封裝的方法.把block作為方法參數(shù)使用.

@interface JHttpRequest : NSObject

//異步Get請求

+ (ASIHTTPRequest *)asyncGetRequest:(NSString *)url complete:(void (^)(NSString *responseStr))complete failed:(void (^)(NSString *errorMsg))failed;

//異步Get請求帶緩存

//異步Post請求

//異步Post上傳圖片

//異步下載請求

//生成異步請求對象

@end

//發(fā)送異步Get請求

+ (ASIHTTPRequest *)asyncGetRequest:(NSString *)url

complete:(void (^)(NSString *responseStr))complete

failed:(void (^)(NSString *errorMsg))failed{

ASIHTTPRequest *request = [self requestWithUrl:url];

[request setUserAgent:UserAgent];

[request setTimeOutSeconds:5.];

//請求成功

[request setCompletionBlock:^{

switch (request.responseStatusCode) {

case RequestStatus_OK:

complete(request.responseString);break;

case RequestStatus_ErrorRequest:

failed(@"錯誤的請求");break;

case RequestStatus_NotFound:

failed(@"找不到指定的資源");break;

case RequestStatus_Error:

failed(@"內(nèi)部服務器錯誤");break;

default:

failed(@"服務器出錯");break;

}

}];

//請求失敗

[request setFailedBlock:^{

failed(@"網(wǎng)絡連接失敗");

}];

//開始請求

[request startAsynchronous];

return request;

}

下面是你需要調(diào)用網(wǎng)絡接口的viewcontroller種對上面網(wǎng)絡請求block方法的調(diào)用

[JHttpRequest asyncGetRequest:url complete:^(NSString *responseStr) {

if (responseStr) {

NSDictionary *getDic = [responseStr JSONValue];

if ([[getDic objectForKey:@"success"] boolValue]) {

//getDic 請求成功取得的json數(shù)據(jù)

}else{

faild([getDic objectForKey:@"msg"]);

}

}else{

faild(@"獲取信息失敗");

}

} failed:^(NSString *errorMsg) {

faild(errorMsg);

}];

綜上例子所訴,block可以作為一個方法參數(shù)使用,能更方便地去取得回調(diào)數(shù)據(jù).

第二種,把block作為類的屬性來使用.

//定義一個block作為viewcontroler的一個屬性.

@interface FirstViewController : UIViewController{

//定義一個blocks變量

void (^BarkCallback) (FirstViewController *thisDog, int count);

NSInteger barkCount;

}

@property(nonatomic , copy) void (^BarkCallback) (FirstViewController *thisDog, int count);

@end

其中void (^BarkCallback) (FirstViewController *thisDog, int count);thisDog count是參數(shù).

@implementation FirstViewController

@synthesize BarkCallback;

- (void)viewDidLoad

{

[super viewDidLoad];

barkCount = 0;

//這里我們啟動一個定時器方便回調(diào)看效果

[NSTimer scheduledTimerWithTimeInterval:10.0f target:self selector:@selector(updateTimer:) userInfo:nil repeats:YES];

}

-(void) updateTimer:(id) arg

{

barkCount ++;

if (BarkCallback) {

//調(diào)用從其他類傳過來的BarkCallback

BarkCallback(self, barkCount);

}

}

@end

實現(xiàn)block

FirstViewController *viewController = [[FirstViewController alloc] initWithNibName:@"FirstViewController" bundle:nil];

viewController.BarkCallback = ^(FirstViewController *thisDog, int count) {

NSLog(@"count == %d", count);

};

把block作為類的屬性來使用.還有一種表達方法.

typedef void (^BarkCallback) (FirstViewController *thisDog, int count);

@interface FirstViewController : UIViewController{

NSInteger barkCount;

}

@property (nonatomic, copy) BarkCallback completionHandler;

@end

@implementation FirstViewController

@synthesize completionHandler;

- (void)viewDidLoad

{

[super viewDidLoad];

barkCount = 0;

[NSTimer scheduledTimerWithTimeInterval:10.0f target:self selector:@selector(updateTimer:) userInfo:nil repeats:YES];

}

-(void) updateTimer:(id) arg

{

barkCount ++;

if (completionHandler) {

completionHandler(self, barkCount);

}

}

@end

實現(xiàn)block

FirstViewController *viewController = [[FirstViewController alloc]initWithNibName:@"FirstViewController" bundle:nil];

BarkCallback myab = ^(FirstViewController *thisDog, int count) {

NSLog(@"count == %d", count);

};

viewController.completionHandler = myab;

把block作為全局變量來使用.(無意間奇葩地自己創(chuàng)造出來的)

void (^ BarkCallback) (FirstViewController *thisDog, int count);

@interface FirstViewController : UIViewController{

NSInteger barkCount;

}

@end

@implementation FirstViewController

- (void)viewDidLoad

{

[super viewDidLoad];

barkCount = 0;

[NSTimer scheduledTimerWithTimeInterval:10.0f target:self selector:@selector(updateTimer:)userInfo:nil repeats:YES];

}

-(void) updateTimer:(id) arg

{

barkCount++;

if (BarkCallback) {

BarkCallback(self, barkCount);

}

}

@end

實現(xiàn)block

#import "FirstViewController.h"

BarkCallback? = ^(FirstViewController *thisDog, int count) {

NSLog(@"person do 1 222count %d", count);

};

最后,把block方法的參數(shù)來使用.(上面已經(jīng)提到過)

@interface FirstViewController : UIViewController{

}

//向外暴露一個接口

-(void) setBark:( void (^) (FirstViewController *thisDog, int count) ) eachBark;

@end

@implementation FirstViewController

- (void)viewDidLoad

{

[super viewDidLoad];

barkCount = 0;

[NSTimer scheduledTimerWithTimeInterval:10.0f target:self selector:@selector(updateTimer:)userInfo:nil repeats:YES];

}

-(void) updateTimer:(id) arg

{

barkCount++;

}

-(void) setBark:(void (^)(FirstViewController *, int))eachBark

{

eachBark(self, barkCount);

//在這里我們直接把block回調(diào)了,其實一般不這樣直接回調(diào),一般情況是在某種動作完成后回調(diào),比如網(wǎng)絡請求,比如用戶動作監(jiān)聽到以后回調(diào),所以在這里我們可以簡單改進下.

}

@end

方法改進

@interface FirstViewController : UIViewController{

//多定義個block變量指針

void (^BarkCallback) (FirstViewController *thisDog, int count);

}

//向外暴露一個接口

-(void) setBark:( void (^) (FirstViewController *thisDog, int count) ) eachBark;

@end

@implementation FirstViewController

- (void)viewDidLoad

{

[super viewDidLoad];

barkCount = 0;

[NSTimer scheduledTimerWithTimeInterval:10.0f target:self selector:@selector(updateTimer:)userInfo:nil repeats:YES];

}

-(void) updateTimer:(id) arg

{

barkCount++;

//在動作完成,或者監(jiān)聽到用戶操作時,調(diào)用這個block。這里我們是用timer定時調(diào)用.

if (BarkCallback) {

BarkCallback(self, barkCount);

}

}

-(void) setBark:(void (^)(FirstViewController *, int))eachBark

{

//把實現(xiàn)類傳過來的block指針付值給,我們定義的BarkCallback

BarkCallback = [eachBark copy];

}

@end

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)自李峰峰博客 一、概述 閉包 = 一個函數(shù)「或指向函數(shù)的指針」+ 該函數(shù)執(zhí)行的外部的上下文變量「也就是自由變量」...
    Joshua520閱讀 1,104評論 0 0
  • 1.1 局部變量 局部自動變量,在Block中可被讀取。Block定義時copy變量的值,在Block中作為常量使...
    陳雨塵閱讀 3,038評論 4 31
  • 簡述 一句話搞懂block:可以理解為,block是對上下文代碼段的打包,然后在適當?shù)臅r機執(zhí)行。 block長什么...
    Allan_野草閱讀 2,237評論 0 25
  • 1.object-C中的block 作用:保存一段代碼塊 2.聲明block的寫法:block的寫法: 類型: 返...
    KevinChein閱讀 338評論 0 0
  • 蘋果在Mac OS X10.6 和iOS 4之后引入block語法,之后就大幅改變了OC 的編程方式。Block...
    小王子sl閱讀 1,805評論 2 9

友情鏈接更多精彩內(nèi)容