block的定义
typedef void (^YourBlock) (NSInteger);
@property (nonatomic, copy) YourBlock yourBlock;
self.yourBlock = ^(NSInteger a) {
NSLog(@"%ld",(long)a);
};
_yourBlock(8);
直接定义
@property (nonatomic, copy) void(^myBlock)(NSInteger);
self.myBlock = ^(NSInteger a) {
NSLog(@"%ld",(long)a);
};
_myBlock(5);
方法中定义
void(^ourBlock)(NSInteger) = ^(NSInteger a){
NSLog(@"%ld",(long)a);
};
ourBlock(3);
在MRC下用copy修饰block,在MRC声明创建的block是在栈区,当函数之行结束的时候block就会被释放掉,所以需要用copy修饰block,将block拷贝一份到堆区,引用计数加1,,则block不会被释放。在ARC下,使用copy和strong修饰都可以,因为在ARC下声明创建block是在堆区的。
block的使用
block作为返回值,链式编程的思想。
self.select.where(@"哈哈");
- (ViewController *)select {
return self;
}
- (void(^)(NSString *))where {
void (^block)(NSString *) = ^(NSString *str){
NSLog(@"%@",str);
};
return block;
}
block作为参数,函数式编程的思想。
typedef void (^NetBlock) (NSString *);
- (void)request:(NetBlock)netBlock {
netBlock(@"网络请求结果");
}
[self request:^(NSString *result) {
NSLog(@"%@",result);
}];
block的底层
在block代码块中修改外部变量,需要用__block修饰外部变量。
__block int c = 10;
void(^Block)(NSInteger) = ^(NSInteger a){
a++;
NSLog(@"%ld",(long)a);
};
Block(c);
int c是存储在栈区的。将c传入到block中,底层block执行时,会重新定义一个c,这个c是一个值,bound by copy,block代码块中使用的c其实是将新定义的c,实际上执行block代码块c累加操作的是新定义的c。所以在代码块中c++并不会改变一开始定义在栈区的c的值。当使用__block修饰c的时候,byref引用栈区的值进行copy到堆区,此时block代码块中进行c ++中的c实际上是传入了c的指针地址,此时修改这个值的时候,会达到值同步变化的情况。
block的循环引用
自动释放池释放对象,需要引用计数为0,才可以调起dealloc方法进行销毁,当A持有B,B也持有A的时候,互相强引用持有则不会使引用计数减1,因此造成循环引用,无法释放。
使用__weak修饰,在block代码块中使用__strong修饰。在block代码块中__strong有时候可以不用写。直接调用,此时self还没有进行释放的话就没有问题。如果是延时调用的话,比如block块中的代码为10秒后调用,如果在10秒前退出了当前控制器,则当前控制器会被释放销毁,则block中的代码块就不会执行了。__strong修饰后会使引用计数再次加1,此时控制器就不会被释放,当block的代码块里面执行完毕后,引用计数才会减1,此时会调用dealloc方法,控制器才会被释放。
__weak typeof(self) weakSelf = self;
self.lwnBlock = ^{
__strong typeof(weakSelf) strongSelf = weakSelf;
[strongSelf select];
NSLog(@"你好");
};
强弱共舞也可以解决循环引用
#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
强弱共舞的使用
@weakify(self);
bgViw.clickBlock = ^(id boj) {
@strongify(self);
[self hideClick:boj];
};
使用__block解决循环引用,使用__block修饰,相当于重新copy 了一份self,使用这个拷贝出来的对象进行一系列的操作,但当代码块内容执行结束后,要在最后释放这个拷贝出来的对象,即bWeakSelf = nil,释放掉拷贝出来的self。
__block ViewController *bWeakSelf = self;
self.lwnBlock = ^{
NSLog(@"%@",bWeakSelf);
bWeakSelf = nil;
};
把self作为block中的参数传入也可以解决循环引用。声明一个block,参数为当前self类,调用时传入self。
typedef void (^LwnBlock2) (ViewController *);
@property (nonatomic, copy) LwnBlock2 lwnBlock2;
self.lwnBlock2 = ^(ViewController *obj) {
NSLog(@"%@",obj);
};
self.lwnBlock2(self);
网友评论