常用Block,写一个文章来避免自己犯错
,之后会不断补充Block的使用方式
1.什么是Block
Block是一种多个文件之间的数据交互方式
是Objective-C特有的一种数据类型
它可以保存一段代码,在合适的时候取出来调用常见格式
//不带参数,不带名称
^{
}
//带名称
void (^someBlock)() = ^{
}
//带参数带返回值
int (^addBlock)(int a, int b) = ^(int a, int b){
return a+b;
}
- 两种定义方式
@property (copy) void(^MyBlock)(void);
typedef void(^MyBlock)(void);//常用的block建立
@property (nonatomic, copy) MyBlock block;
- block在一些场合下需要用到copy,比如下边这段代码,如果在栈上if和else里会被释放
void (^block)();
if(xxx){
block = ^{
NSLog(@"1");
}
}else{
block = ^{
NSLog(@"2");
}
}
block();
这个时候我们需要用到copy把它放在堆上来,避免它被释放
void (^block)();
if(xxx){
block = [^{
NSLog(@"1");
} copy];
}else{
block = [^{
NSLog(@"2");
} copy];
}
block();
- 在属性中声明block用什么来修饰?
strong和copy都一样
使用copy修饰block是MRC时期的遗留物,这在MRC时期是至关重要的事情,但是使用ARC的现在,strong是可以代替的,只是一个习惯问题而已。
block其实是一个对象,有和其他对象相同的一些特性和信息,看起来像是C语言里的函数
2.Block优缺点 ####
相比代理,Block更轻便简单,不需要定义代理,协议,可以直接使用
如果有很多相关方法,我们就需要使用代理,这样更方便管理
使用Block需要避免循环引用
3.Block循环引用 ####
Block循环引用种类大概有三种,就不列举了,我们只需要知道如何避免循环引用就可以了
防止Self循环引用,当然括号里可以使任何对象,个人建议凡是Block中的对象都要使用 __weak
__weak typeof(self) weakSelf=self;
__weak TSController * weakCtl=Ctl;
- 在 block 中进行强引用防止被释放,一半多次使用的时候需要加strong,防止block没有跑完self被释放
typeof(self) __strong strongSelf = weakSelf;
ViewController *bSelf = wSelf;
4.Block中修改局部变量需要使用__block 修饰 ####
Block中修改局部变量需要使用__block
Block修饰符在ARC中Copy和Strong一样的,在MRC中用Copy
Block中有时候需要用到Strong保证代码在执行到block中,self不会被释放,当block执行完后,会自动释放该strongSelf
5.Block常见用法(会不断补充) ####
-
在头文件中定义Block属性,进行值传递
一般在View向Controller进行值传递的时候经常用到
定义
@property (strong,nonatomic)void (^TSHTToolCollectionCellBlock)(TSHTToolCollectionCell * cell);
实现
__weak typeof(self) weakSelf = self;
[cell setTSHTToolCollectionCellBlock:^(TSHTToolCollectionCell * htcell)
{
NSString * msgString=[NSString stringWithFormat:@"%ld/9\n长按图片可以拖动排序",(weakSelf.imageSelectArray.count)];
weakSelf.msgLabel.text=msgString;
}];
调用
if (self.TSHTToolCollectionCellBlock)
{
self.TSHTToolCollectionCellBlock(self);
}
-
定义带Block的方法
涉及到线程的方法,我们需要回到主线程
- (void)clipImageComplete:(void (^)(UIImage * clipedImage))complete
{
__weak typeof(self) weakSelf = self;
dispatch_queue_t conQueue = dispatch_queue_create("concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(conQueue, ^
{
//开始画图
UIImage * clipedImage=[weakSelf clipImage];
dispatch_sync(dispatch_get_main_queue(), ^{
complete(clipedImage);
});
});
}
注意:分享一个宏定义 ####
#ifndef weakify
#if DEBUG
#if __has_feature(objc_arc)
#define weakify(object) autoreleasepool{} __weak __typeof__(object) weak##_##object = object;
#else
#define weakify(object) autoreleasepool{} __block __typeof__(object) block##_##object = object;
#endif
#else
#if __has_feature(objc_arc)
#define weakify(object) try{} @finally{} {} __weak __typeof__(object) weak##_##object = object;
#else
#define weakify(object) try{} @finally{} {} __block __typeof__(object) block##_##object = object;
#endif
#endif
#endif
#ifndef strongify
#if DEBUG
#if __has_feature(objc_arc)
#define strongify(object) autoreleasepool{} __typeof__(object) object = weak##_##object;
#else
#define strongify(object) autoreleasepool{} __typeof__(object) object = block##_##object;
#endif
#else
#if __has_feature(objc_arc)
#define strongify(object) try{} @finally{} __typeof__(object) object = weak##_##object;
#else
#define strongify(object) try{} @finally{} __typeof__(object) object = block##_##object;
#endif
#endif
#endif
使用时候直接在block外边@weakify(self),在block里边使用@strongify(self)