网站建设业务员提成,免费投放广告的平台,wordpress网站如何播放视频播放器,如果做微商需不需要开个网站。一、定义#xff1a;
在 Objective-C 中#xff0c;一个 block 是一种可以捕获周围上下文变量的匿名函数。当你想要定义一个只在当前作用域内使用的 block 时#xff0c;你可以创建一个局部 block。以下是一个例子#xff0c;展示如何用 Objective-C 写一个局部 block
在 Objective-C 中一个 block 是一种可以捕获周围上下文变量的匿名函数。当你想要定义一个只在当前作用域内使用的 block 时你可以创建一个局部 block。以下是一个例子展示如何用 Objective-C 写一个局部 block
#import Foundation/Foundation.hint main(int argc, const char * argv[]) {autoreleasepool {// 定义一个局部 blockvoid (^myLocalBlock)(NSString *) ^(NSString *name) {NSLog(Hello, %, name);};// 调用这个局部 blockmyLocalBlock(World);}return 0;
}
在这个例子中myLocalBlock 是一个局部 block它接收一个 NSString 类型的参数并输出一条欢迎信息。这个 block 被定义在 main 函数的局部作用域内只能在这个作用域内被调用。
Block 也可以捕获外部变量。如果你想在 block 内部访问外部定义的变量你需要在 block 外部定义这些变量并确保它们有正确的存储类型。例如
#import Foundation/Foundation.hint main(int argc, const char * argv[]) {autoreleasepool {NSString *greeting Hello;// 定义一个局部 blockvoid (^myLocalBlock)(NSString *) ^(NSString *name) {NSLog(%, %, greeting, name);};// 调用这个局部 blockmyLocalBlock(World);}return 0;
}
在这个例子中greeting 是一个局部变量它在 block 外部定义并在 block 内部被捕获和使用。注意block 默认是捕获变量的值而不是引用除非你使用 __block 存储类型修饰符。如果你打算在 block 内部修改外部变量你应该使用 __block如下所示
#import Foundation/Foundation.hint main(int argc, const char * argv[]) {autoreleasepool {__block NSInteger counter 0;// 定义一个局部 blockvoid (^incrementCounterBlock)(void) ^{counter 1;NSLog(Counter: %ld, (long)counter);};// 调用这个局部 blockincrementCounterBlock(); // Counter: 1incrementCounterBlock(); // Counter: 2}return 0;
}
在这个例子中counter 变量被 __block 修饰符修饰这允许 block 在被调用时修改 counter 的值。 二、循环引用
在 Objective-C 中局部 block 本身不会产生循环引用因为它们通常是栈上的局部变量并且在声明它们的作用域结束时会被销毁。循环引用或称为保留retain循环产生的情况通常涉及 block 捕获了它外部的对象特别是当这些对象又持有这个 block 的强引用时。
下面是一个不会产生循环引用的局部 block 的例子
void someFunction() {int localVariable 42;void (^myBlock)(void) ^{NSLog(Local variable: %d, localVariable);};myBlock(); // 此处调用 block不会产生循环引用
}在上面的代码中myBlock 是一个局部 block它捕获了 localVariable。当 someFunction 函数执行完毕后myBlock 和 localVariable 都会从栈上移除因此不存在循环引用。
循环引用通常发生在以下场景
当一个对象持有一个 block 的强引用。该 block 又捕获了这个对象并持有其强引用。
例如
interface MyClass : NSObject
property (nonatomic, copy) void (^myBlock)(void);
endimplementation MyClass
- (void)configureBlock {__weak typeof(self) weakSelf self; // 使用弱引用来打破循环引用self.myBlock ^{__strong typeof(weakSelf) strongSelf weakSelf; // 在 block 内部将弱引用升级为强引用以保证执行期间 self 不会被释放[strongSelf doSomething];};
}- (void)doSomething {// 做一些事情
}
end在上面的例子中MyClass 的实例持有一个名为 myBlock 的 block。如果 myBlock 直接捕获 self 而没有使用弱引用 weakSelf那么当 MyClass 的实例持有这个 block 时就会产生循环引用。因为 self 持有 myBlock而 myBlock 又捕获了 self这样它们就相互持有对方的强引用。
为了打破这个循环可以使用 __weak 关键字创建一个 self 的弱引用 weakSelf然后在 block 内部使用这个弱引用。如果需要在 block 内部保证 self 在执行期间不会被释放可以临时将 weakSelf 升级为强引用 strongSelf如上面的例子所示。这种方式既防止了循环引用又确保了在 block 执行期间 self 是存在的。