block使用技巧
来源:互联网 发布:数据库 论坛回复 编辑:程序博客网 时间:2024/05/16 06:58
1.为常用的块类型创建typedef
typedef return_type (^block_type) (parameters);
block_type是块的类型名
typedefint(^EOCCompletionHandler) (NSData*data, NSTimeInterval duration,NSError*error); //为块创建typedef
- (void)startWithCompletionHandler:(EOCCompletionHandler) completion;
好处:
1.更加清晰
2.方便重构块的类型签名,比如说,要给原来的completion handler块再加一个参数,用以表示完成任务所花时间,那么只需修改类型定义语句即可:
typedefint(^EOCCompletionHandler) (NSData*data, NSTimeInterval duration,NSError*error);
修改之后,凡是使用了这个类型定义的地方,如方法签名等处,都会无法编译,于是可以逐个修改。
2.用途不同时应定义不同的块。
方法签名是ObjC中对一个方法的参数类型和返回值类型的一条记录。每个方法都对应一个方法签名。
typedefvoid(^ACAcountStoreSaveCompletionHandler) (BOOLsuccess, NSError *error);
typedefvoid(^ACAcountStoreRequestCompletionHandler) (BOOLsuccess, NSError *error);
这两个类型定义的签名相同,可以合并成一个typedef,然而,这么做之后,块与参数的用途看上去就不那么明显了。
与此相似,如果有好几个类都要执行相似但各有区别的异步任务,而这几个类又不能放入同一个继承体系,那么,每个类就应该有自己的completion handler类型。
3.使用委托和块实现回调对比
3.1使用委托
令关注此事件的对象遵从该协议。对象成为delegate之后,就可以在相关事件发生时得到通知了。
#import<Foundation/Foundation.h>
@class EOCNetworkFetcher;
@protocol EOCNetworkFetcherDelegate <NSObject>
- (void)networkFetcher:(EOCNetworkFetcher*)fetcher didReceiveData:(NSData*)data;
- (void)networkFetcher:(EOCNetworkFetcher*)fetcher didFailWithError:(NSError*)error;
@end
@interface EOCNetworkFetcher : NSObject
@property (nonatomic,weak)id<EOCNetworkFetcherDelegate> delegate;
- (id)initWithURL:(NSURL*)url;
- (void)start;
@class EOCNetworkFetcher;
@protocol EOCNetworkFetcherDelegate <NSObject>
- (void)networkFetcher:(EOCNetworkFetcher*)fetcher didReceiveData:(NSData*)data;
- (void)networkFetcher:(EOCNetworkFetcher*)fetcher didFailWithError:(NSError*)error;
@end
@interface EOCNetworkFetcher : NSObject
@property (nonatomic,weak)id<EOCNetworkFetcherDelegate> delegate;
- (id)initWithURL:(NSURL*)url;
- (void)start;
@end
其他类则可像下面这样使用此类提供的API:
- (void)fetchFooData {
NSURL *url = [[NSURLalloc]initWithString:@"http://www.example.com/foo.dat"];
EOCNetworkFetcher*fetcher = [[EOCNetworkFetcheralloc]initWithURL:url];
fetcher.delegate= self;
[fetcher start];
}
- (void)networkFetcher:(EOCNetworkFetcher*)fetcher didReceiveData:(NSData*)data {
_fetchedFooData = data;
NSURL *url = [[NSURLalloc]initWithString:@"http://www.example.com/foo.dat"];
EOCNetworkFetcher*fetcher = [[EOCNetworkFetcheralloc]initWithURL:url];
fetcher.delegate= self;
[fetcher start];
}
- (void)networkFetcher:(EOCNetworkFetcher*)fetcher didReceiveData:(NSData*)data {
_fetchedFooData = data;
}
这种做法确实可行,然而如果改用块来实现,代码会更加清晰。但委托模式有个缺点:如果类要分别使用多个获取器下载不同的数据,那么就得在delegate回调方法里根据传入的获取器参数来切换。
- (void)networkFetcher:(EOCNetworkFetcher*)fetcher didReceiveData:(NSData*)data {
if(fetcher == _fooFetcher) {
_fetchedFooData = data;
_fooFetcher = nil;
} else if(fetcher == _barFetcher) {
_fetchedBarData = data;
_barFetcher = nil;
}
if(fetcher == _fooFetcher) {
_fetchedFooData = data;
_fooFetcher = nil;
} else if(fetcher == _barFetcher) {
_fetchedBarData = data;
_barFetcher = nil;
}
}
3.2使用block
#import<Foundation/Foundation.h>
typedefvoid(^EOCNetworkFetcherCompletionHandler)(NSData*data);
@interface EOCNetworkFetcher : NSObject
@property (nonatomic,weak)id<EOCNetworkFetcherDelegate> delegate;
- (id)initWithURL:(NSURL*)url;
- (void)startWithCompletionHandler:(EOCNetworkFetcherCompletionHandler)handler;
@interface EOCNetworkFetcher : NSObject
@property (nonatomic,weak)id<EOCNetworkFetcherDelegate> delegate;
- (id)initWithURL:(NSURL*)url;
- (void)startWithCompletionHandler:(EOCNetworkFetcherCompletionHandler)handler;
@end
- (void)fetchFooData {
NSURL *url = [[NSURLalloc]initWithString:@"http://www.example.com/foo.dat"];
EOCNetworkFetcher*fetcher = [[EOCNetworkFetcheralloc]initWithURL:url];
[fetcher startWithCompletionHandler:^(NSData*data) {
_fetchedFooData = data;
}];
NSURL *url = [[NSURLalloc]initWithString:@"http://www.example.com/foo.dat"];
EOCNetworkFetcher*fetcher = [[EOCNetworkFetcheralloc]initWithURL:url];
[fetcher startWithCompletionHandler:^(NSData*data) {
_fetchedFooData = data;
}];
}
与使用委托模式的代码相比,用块写出来的代码显然更为整洁。异步任务执行完后所需运行的业务逻辑,和启动异步任务所用的代码放在一起了。而且,由于块声明在创建获取器范围里,所以他可以访问此范围内的全部变量。而使用委托模式需要把这些变量作为参数传入。
并且如果有多个获取器也不需要根据获取器参数来切换处理业务逻辑,每个completion handler的业务逻辑,都是和相关的获取器对象一起定义:
- (void)fetchFooData {
NSURL *url = [[NSURLalloc]initWithString:@"http://www.example.com/foo.dat"];
EOCNetworkFetcher*fetcher = [[EOCNetworkFetcheralloc]initWithURL:url];
[fetcher startWithCompletionHandler:^(NSData*data) {
_fetchedFooData = data;
}];
}
- (void)fetchBarData {
NSURL *url = [[NSURLalloc]initWithString:@"http://www.example.com/foo.dat"];
EOCNetworkFetcher*fetcher = [[EOCNetworkFetcheralloc]initWithURL:url];
[fetcher startWithCompletionHandler:^(NSData*data) {
_fetchedBarData = data;
}];
NSURL *url = [[NSURLalloc]initWithString:@"http://www.example.com/foo.dat"];
EOCNetworkFetcher*fetcher = [[EOCNetworkFetcheralloc]initWithURL:url];
[fetcher startWithCompletionHandler:^(NSData*data) {
_fetchedFooData = data;
}];
}
- (void)fetchBarData {
NSURL *url = [[NSURLalloc]initWithString:@"http://www.example.com/foo.dat"];
EOCNetworkFetcher*fetcher = [[EOCNetworkFetcheralloc]initWithURL:url];
[fetcher startWithCompletionHandler:^(NSData*data) {
_fetchedBarData = data;
}];
}
总结:委托和block都可以实现回调,block能把异步任务执行完后所需运行的业务逻辑,和启动异步任务所用的代码放在一起,代码更加清晰。委托模式有一个缺点:如果类要分别使用多个网络获取器下载不同的数据,任务完成后,那么就得在delegate回调方法里根据传入的获取器参数来切换。
0 0
- block使用技巧
- block 使用技巧
- 使用 block 的小技巧和注意事项
- iOS block介绍和使用技巧(基础篇)
- [个人博客搬运]Objective-C的Block使用技巧
- 编程技巧 - block
- Block 的小技巧
- 编程技巧 - 关联+Block
- 四个 block 小技巧
- Block使用
- block使用
- block使用
- block使用
- block使用
- Block 使用
- Block 技巧与底层解析
- Block技巧与底层解析
- 代理的return怎么造成循环引用的,block的使用技巧
- MySql连接
- C语言中volatile关键字的作用
- android开发常见编程错误总结
- 孵化003-赵航规范后程序
- 运算符优先级与结合性
- block使用技巧
- ios block 使用注意,必须都用__weak 弱引用
- 单例模式
- pg表中的系统列
- Codeforces 650A Watchmen 【数学 + 二分】
- iOS开发中的界面跳转效果的样式
- discuz X3.2 DB:类数据库操作
- 毕业后我这操蛋的五年
- centos6.5挂载ntfs