iOS中block实际应用初探
对于block不才的我已经接触有段时间了,但究竟block是何方神圣,可以在我实际项目中带来什么,我自己如何实现一个block。一切无知。都是用一些官方的API时用到,或者前辈写的第三库的接口时用到.例如
[socialVC dismissViewControllerAni
[arr enumerateObjectsUsingBlo
但从未自己写一个blcok。曾经也花一些时间了解了block可始终理解不到其中精髓,所以又来再次摸索.从中理解到一些肤浅认识,所以与大家来分享.多多指教.
Block究竟有哪些称呼和官方的解释。
匿名函数,块函数,块,block基本上他们都是同一个鸟人。
维基百科中说,Block是Apple Inc.为C,C++,以及OC 添加的新特性,使得它们可以用lambda表达式的语法来创建闭包.(lambda表达式既匿名函数表达式,闭包既是可以包含自由(未绑定到特定对象)变量的代码块,具体可以自己下去认真理解下)。我理解为block就是用匿名函数表达式创建的代码块.
闭包就是能够读取其它函数内部变量的函数 (抄来的)
什么时候使用block.
Block除了能够定义参数列表、返回类型外,还能够获取被定义时的词法范围内的状态(比如局部变量),并且在一定条件下(比如使用__block变量)能够修改这些状态。此外,这些可修改的状态在相同词法范围内的多个block之间是共享的,即便出了该词法范围(比如栈展开,出了作用域),仍可以继续共享或者修改这些状态。通常来说,block都是一些简短代码片段的封装,适用作工作单元,通常用来做并发任务、遍历、以及回调。
block如何声明
block的结构就用这张图来说明
int (*CFunc)(int a)
int (^BFunc)(int a)
回调是block一个重要的特性.
block回调是我在网络请求中用得最多的.
这里先用前辈在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;
}
//向外暴露一个接口
- (void)setCompletionBlock:(ASIBasicBlock)aCompletionBlock;
方法实现(这里用release是为开启arc)
@implementation ASIHTTPRequest
- (void)setCompletionBlock:(ASIBasicBlock)aCompletionBlock
{
[completionBlock release];
completionBlock = [aCompletionBlock copy];
}
这里是网络请求完成后的方法,在这里实现我们block的调用.
- (void)reportFinished
{
#if NS_BLOCKS_AVAILABLE
if(completionBlock){
completionBlock();
}
#endif
}
@end
如下,然后你可以在你请求网络的类实现中,实现网络请求并获取网络请求成功后的回调, 这里可以回传参数变量(我们这个例子block是回传的参数为void,--typedef
[arr
这里的obj 和idx 以及stop都可以为你在回调时候所用,就好比代理delegate回传参数一样.
ASIHTTPRequest *request = [self requestWithUrl:url];
看了前辈的block实现,兄弟伙写是否有所理解?接下来看看,我写的一个block的简单用法.
第一种,接网络请求的block自己再次封装的方法.把block作为方法参数使用.
@interface JHttpRequest : NSObject
//异步Get请求
+ (ASIHTTPRequest *)asyncGetRequest:(NSString *)url complete:(void (^)(NSString *responseStr))complete failed:(void (^)(NSString *errorMsg))failed;
//异步Get请求带缓存
//异步Post请求
//异步Post上传图片
//异步下载请求
//生成异步请求对象
@end
//发送异步Get请求
+ (ASIHTTPRequest *)asyncGetRequest:(NSString *)url
}
下面是你需要调用网络接口的viewcontroller种对上面网络请求block方法的调用
[JHttpRequest
//getDic
综上例子所诉,block可以作为一个方法参数使用,能更方便地去取得回调数据.
第二种,把block作为类的属性来使用.
//定义一个block作为viewcontroler的一个属性.
@interface FirstViewController : UIViewController{
}
@property(nonatomic , copy) void (^BarkCallback) (FirstViewController *thisDog, int count);
其中void
@implementation FirstViewController
@synthesize BarkCallback;
- (void)viewDidLoad
{
//这里我们启动一个定时器方便回调看效果
}
-(void) updateTimer:(id) arg
{
}
@end
实现block
viewController.BarkCallback = ^(FirstViewController *thisDog, int count) {
};
把block作为类的属性来使用.还有一种表达方法.
typedef
@interface FirstViewController : UIViewController{
}
@property (nonatomic, copy)
@end
@implementation FirstViewController
@synthesize completionHandler;
- (void)viewDidLoad
{
}
-(void) updateTimer:(id) arg
{
if (completionHandler) {
}
@end
实现block
BarkCallback
把block作为全局变量来使用.(无意间奇葩地自己创造出来的)
void
@interface FirstViewController : UIViewController{
}
@end
@implementation
- (void)viewDidLoad
{
}
-(void) updateTimer:(id) arg
{
barkCount++;
if (BarkCallback) {
}
@end
实现block
#import "FirstViewController.h"
BarkCallback
最后,把block方法的参数来使用.(上面已经提到过)
@interface FirstViewController : UIViewController{
}
//向外暴露一个接口
-(void) setBark:( void (^) (FirstViewController *thisDog, int count) ) eachBark;
@end
@implementation
- (void)viewDidLoad
{
}
-(void) updateTimer:(id) arg
{
barkCount++;
}
-(void) setBark:(void (^)(FirstViewController *, int))eachBark
{
//在这里我们直接把block回调了,其实一般不这样直接回调,一般情况是在某种动作完成后回调,比如网络请求,比如用户动作监听到以后回调,所以在这里我们可以简单改进下.
}
@end
方法改进
@interface
//多定义个block变量指针
}
//向外暴露一个接口
-(void) setBark:(
@end
@implementation
- (void)viewDidLoad
{
}
-(void) updateTimer:(id) arg
{
barkCount++;
//在动作完成,或者监听到用户操作时,调用这个block。这里我们是用timer定时调用.
if
}
-(void) setBark:(void
{
//把实现类传过来的block指针付值给,我们定义的BarkCallback
BarkCallback = [eachBark copy];
}
@end
各位写得有点啰嗦,不知道是否能给你们带来肤浅的认识,就这样o啦,谢谢支持!