block本质是什么,需要注意什么?
Block 的本质是一个封装了函数和函数调用环境(捕获的变量)的 Objective-C 对象。Block 的实现基于 C 语言的函数指针,但它们比普通的函数指针更加强大,因为它们能够捕获周围的状态。
在 Objective-C 中,每个 block 实际上是一个结构体,该结构体包含了几个重要的元素:
isa
指针,表明这是一个对象,并指向该 block 类型的类对象。- 函数指针,指向 block 的执行体(即 block 里写的代码)。
- 捕获的变量的副本,block 能够捕获其作用域内的变量,这些变量在 block 被定义时拷贝到了 block 结构体中。
- 引用计数,用于在非 ARC 环境下管理 block 的生命周期。
- 其他用于管理 block 生命周期和状态的字段。
使用 block 时需要注意以下几个方面:
-
循环引用:Block 内部如果捕获了
self
或其成员变量,且self
同时持有这个 block,会产生循环引用,导致内存泄漏。为了打破循环引用,通常会使用 __weak 关键字来声明一个self
的弱引用。 -
内存管理:在非 ARC 环境下,需要手动管理 block 的拷贝和释放。在 ARC 环境下,block 通常会自动从栈复制到堆上,但仍需要注意循环引用问题。
-
变量捕获:Block 只能捕获其作用域内的变量的值,如果需要在 block 内部修改外部变量,那么这个变量必须使用
__block
修饰符声明。 -
执行环境:Block 在定义时捕获变量的状态,而不是在执行时,所以 block 内部看到的外部变量是在 block 创建时的快照。
-
性能考虑:频繁地创建和销毁大量的 block 可能会对性能造成影响,特别是当这些 block 被拷贝到堆上时。同时,block 捕获大量数据时也会增加内存使用。
-
线程安全:如果 block 在多线程环境中执行,需要确保 block 内部访问的数据是线程安全的。
延伸: block性能考虑和线程安全
理解并注意以上方面,可以有效地使用 block 编程,同时避免常见的陷阱和错误。
1.局部block:
局部Block-CSDN博客
2.gcd:
GCD与Block
3.函数参数是block,调这个block中使用self:
函数参数是block-CSDN博客
4.什么时候strong;
在 Objective-C 中,当你在 block 内部使用 weakSelf
并希望在 block 执行的过程中确保被捕获的对象不会被释放,你会将 weakSelf
转换为 strongSelf
。
这个模式是一种预防性的做法,用以确保在 block 执行的时候,即使是在异步操作中,对象(通常是 self
)仍然存在。如果不这么做,在异步操作中,self
可能会在 block 执行之前被释放,尤其是当 block 执行不是立即发生时。一旦 self
被释放,尝试访问 weakSelf
将返回 nil
,并且在 block 内部调用 self
的方法或者访问其属性将不会执行任何操作。
这是将 weakSelf
转换为 strongSelf
的模式:
__weak typeof(self) weakSelf = self;
self.myBlock = ^{
// 将弱引用的 weakSelf 转换为强引用的 strongSelf
__strong typeof(weakSelf) strongSelf = weakSelf;
// 确保 strongSelf 在 block 执行时还存在
if (strongSelf) {
[strongSelf doSomething];
// 其他使用 strongSelf 的代码...
}
// 如果 strongSelf 为 nil,则意味着原始的 self 已经被释放
};
在这个模式中,一旦 block 开始执行并且 strongSelf
被成功创建,self
的生命周期就会在 block 执行的过程中得到保证。如果 strongSelf
为 nil
,则表示原始的 self
已经被释放,block 内部的代码应该处理这种情况,避免执行任何依赖于 self
存在的操作。
总结来说,将 weakSelf
转换为 strongSelf
是为了:
- 确保在 block 的执行期间,
self
不会被释放。 - 允许 block 在
self
不存在时正确地处理这种情况,通常是直接返回或者执行一些不依赖于self
的操作。
这种做法是一种推荐的编程模式,可以避免循环引用的同时也确保了代码的稳定性和安全性。
5. 什么时候拷贝到堆上;
block什么时候拷贝到堆上-CSDN博客
6.weak的本质;
待总结;
7.是否是OC对象?
Block是OC对象吗-CSDN博客
8.Block为什么不能为nil?
OC中Block为什么不能为nil-CSDN博客