深入理解Block
- block的
灵活之处
:能够从函数外部访问函数内部的变量
。
-
如果
有返回值
,block的声明和实现语法略有不同:-
声明
:
// 返回类型 (^block变量名)(参数类型); CGFloat (^myBlock)(NSObject *);
-
实现
:
// ^返回类型(参数类型 参数名) ^CGFloat(NSObject *obj) { /** 实现block */ };
-
做参数
:
// (返回类型 (^)(参数类型))block变量名; (CGFloat (^)(NSObject *))myBlock;
-
- 利用block实现
回调方法
,作为属性的block会被保存
到堆,等待
被调用时执行。
- block的
typedef
格式同其他类型不同:
/**
typedef 原始类型 新类型
*/
typedef int intType;
/**
typedef 返回类型 (^block类型名)(参数类型)
*/
typedef CGFloat(^myBlock)(NSString *str);
- 直接设置对象的
block属性
,编译器不提示block类型
。解决方法:- 利用
typedef
定义所需的block类型。 - 将block属性划为
私有
。 - 提供一个setBlock方法,用来
设置
block属性。
- 利用
/**
1. 定义block类型(.h)
*/
typedef void(^RAPWebImageDownloadHandler)(RAPWebImageDownloadOperation *op);
/**
2. 提供一个设置block属性的方法(.h)
*/
- (void)setWebImageDownloadHandler:(RAPWebImageDownloadHandler)handler;
/**
3. 将block属性划为私有(.m)
*/
@property (nonatomic, copy) RAPWebImageDownloadHandler handler;
// 4. 方法实现(.m)
- (void)setWebImageDownloadHandler:(RAPWebImageDownloadHandler)handler
{
self.handler = handler;
}
- 在 block 中使用 self 前,要先判断是否为空,如果为空,则返回,否则,继续执行后续逻辑;尽管在 OC 中,向 nil 发消息没问题,但是,如果后续逻辑包含数据操作,那么就会出现界面未改变,但数据已经发生变化的情况
// 弱引用 self
__weak __typeof(&*self)weakSelf = self;
[DDPhpClient request:@"http://www.baidu.com" params:nil completion:^(NSError *err, id returnData) {
if (self == nil) return;
// 其它业务逻辑
UIViewController *vc = [UIViewController new];
[self presentViewController:vc animated:YES completion:nil];
}];