Block
os4.0系统已开始支持block
它封装了一段代码,这段代码可以在任何时候执行。Blocks可以作为函数参数或者函数的返回值,而其本身又可以带输入参数或返回值。它和传统的函数指针很类似
block其实就是一个函数指针,block可以看做是匿名函数的函数指针来对待。
Block会捕获外部变量,但是当你试图在Block里面修改捕获的外部变量时。就是出现编译错误,解决的一种办法是将外部变量使用 __block 修饰符修饰。
Block循环引用
在实际项目中对于Block最常见的问题应该是循环引用。如果Block中使用了 __strong 修饰符的对象,那么当block从栈复制到堆时,该对象为Block所持有。这样容易造成循环引用,
编译器来说, _obj 变量只不过是对象的成员变量罢了。
解决的方法便是便是通过 __weak 修饰符来修饰会被Block捕获的变量:
关于Block的应用:
block 属性,一般用 copy 修饰;
如果没有对block进行copy操作,block就存储于栈空间
如果对 block 进行 copy 操作, block 就存储于堆空间 --- 强引用
如果block存储于栈空间,不会对block内部所用到的对象产生强引用
如果block存储于堆空间,就会对block内部所用到的对象产生强引用
注意 :由于使用了 copy 修饰,如果 block 中调用了 block 属性的对象,就会造成循环引用
了避免循环引用,需要对对象进行弱引用修饰:
xxx *x = [[xxx alloc] init];
// 1、修饰方法1 //
__unsafe_unretained typeof(x) weakx = x;
// 2、修饰方法2
__block typeof(x) weakx = x;
x.testBlock = ^{ [weakx run];
};
简单应用
int(^getSum)(int,int) = ^(int num1,int num2) { return num1 +num2; }; int sum = getSum(10,20); NSLog(@"计算结果:%d",sum);
block传值
#import <Foundation/Foundation.h> @interface Other : NSObject typedef void (^myBlock)(NSString *str); @property (nonatomic, copy) myBlock block; - (instancetype)initWithBlock:(myBlock)block; @end
other.m
#import "Other.h" @implementation Other - (instancetype)initWithBlock:(myBlock)block{ self = [super init]; if (self.block=block) { self.block(@"abcxxx"); } return self; } @end
调用
#import "ViewController.h" #import "Other.h" @interface ViewController () @property (nonatomic, copy) NSString *tempStr; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; Other *other = [[Other alloc]initWithBlock:^(NSString *str) { self.tempStr = str; }]; NSLog(@"传来的结果是:%@",self.tempStr); } @end