Block 是 iOS 系统中常用的一种闭包类型,它可以封装一段代码,并在需要的时候进行调用。 Block 的原理是通过一个结构体将其所在的函数或方法地址和变量值存储起来,形成一个闭包,使得代码块可以在其他地方被访问和调用,同时也可以使用外部的变量。
下面是 Block 的代码实现步骤:
1. 定义 Block
例如,我们定义一个 Block,用于将传递进来的字符串添加后缀并输出:
“`
void (^addSuffixBlock)(NSString *) = ^(NSString *str) {
NSString *result = [str stringByAppendingString:@"_Suffix"];
NSLog(@"%@", result);
};
“`
其中,^ 表示定义一个 Block,后面的括号表示 Block 的参数列表,可以有多个参数,而大括号中的代码就是 Block 的代码体,可以访问传入的参数以及外部变量。
2. 调用 Block
我们可以通过调用 Block 来执行其中的代码:
“`
NSString *testStr = @"Test";
addSuffixBlock(testStr);
“`
在这里,我们将 addSuffixBlock Block 传入一个字符串,然后通过调用该 Block 输出带有“_Suffix”后缀的字符串。
3. 在 Block 中使用外部变量
Block 的一个强大之处是可以使用外部变量,这些变量在 Block 被定义时会被复制到 Block 内部。例如:
“`
int num = 10;
void (^numPrintBlock)(void) = ^{
NSLog(@"num = %d", num);
};
numPrintBlock();
“`
在这个例子中,我们定义了一个整型变量 num,并在 Block 中使用它输出 num 的值。在使用时,我们可以直接调用 numPrintBlock 来执行其中的代码。
4. 解决 Block 中的循环引用
在使用 Block 时,我们有时会遇到循环引用的问题,即 Block 和其所在的对象之间互相引用,导致它们都无法释放。为了解决这个问题,可以使用 __weak 或 __block 关键字来避免循环引用。
例如,我们定义一个 ViewController 对象,在其中定义一个 Block,并在 Block 中使用该对象:
“`
@interface ViewController ()
@property (nonatomic, copy) void (^testBlock)(void);
@end
@implementation ViewController
– (void)viewDidLoad {
[super viewDidLoad];
__weak typeof(self) weakSelf = self;
self.testBlock = ^{
NSLog(@"%@", weakSelf.view);
};
}
@end
“`
在这个例子中,我们使用了 __weak 关键字来避免循环引用,使得 Block 不会持有 ViewController 对象。注意,由于 Block 是在堆上创建的,所以需要使用 copy 属性来保证 Block 在不同线程或对象间传递时不会被释放。