Block面试题解析:局部变量与上下文

需积分: 0 0 下载量 154 浏览量 更新于2024-08-05 收藏 2.84MB PDF 举报
"Block面试题1 - iOS技术讨论" 在iOS开发中,Block是一种强大的特性,它可以捕获和封装代码块以及执行环境。面试时,理解Block的工作原理和行为至关重要。以下是对标题和描述中提到知识点的详细解释: 1. **Block的定义**: Block是Objective-C中的一个特性,它允许你创建匿名函数(没有名字的函数),并将它们作为对象传递。Block本质上是一个结构体,包含了函数指针和执行上下文。 2. **Block变量截获**: - **局部变量截获**:当Block捕获局部变量时,它实际上是捕获该变量的一个副本,也就是值截获。这意味着,即使在Block执行时原始变量的值发生了变化,Block内部仍然使用的是被捕获时的值。例如,如果在Block中修改这个变量,编译器会报错,因为修改的是副本而非原始变量。 ```swift int num = 6; void (^myBlock)(void) = ^{ NSLog(@"%d", num); // 输出6,不是2 }; num = 2; myBlock(); // 打印6,因为Block捕获的是num的值 ``` - **局部静态变量截获**:与局部变量不同,Block捕获局部静态变量时,它捕获的是变量的指针,也就是指针截获。因此,Block内部可以改变这个变量的值。 ```swift static int m = 1; void (^myBlock)(void) = ^{ m = 2; // 有效,因为捕获的是指针 }; myBlock(); NSLog(@"%d", m); // 输出2 ``` - **全局变量和静态全局变量**:对于全局变量和静态全局变量,Block不会捕获它们,而是直接使用它们的当前值。这意味着在Block中对这些变量的修改是立即可见的,无需特殊的Block修饰符。 3. **Block的存储类型**: - **全局Block**(_NSConcreteGlobalBlock):存储在程序的数据段,生命周期与程序相同。 - **栈Block**(_NSConcreteStackBlock):存储在调用栈上,生命周期与包含它的函数或Block相同。如果Block需要在函数返回后继续存在,它会被复制到堆上。 - **堆Block**(_NSConcreteMallocBlock):存储在堆上,需要手动管理内存,通常由`copy`或`__block`修饰符导致。 4. **Block修饰符`__block`**: 如果需要在Block内部修改局部变量,必须使用`__block`修饰符。这会让变量存储在堆上,从而Block可以修改其值。对于全局变量和静态变量,由于它们已经在堆上,所以不需要`__block`。 5. **Block对`self`和成员变量的处理**: 当Block中引用`self`或者成员变量时,Block会捕获`self`的指针,这意味着Block执行时可能会引起循环引用问题。解决这个问题通常需要使用弱引用(`__weak`)或者在Block外使用强引用(`__strong`)来临时持有`self`。 Block是Objective-C中一种强大的编程工具,理解和掌握其工作原理和注意事项是iOS开发者必备的技能。了解Block如何捕获变量、存储类型以及避免内存问题,能够帮助写出更高效、安全的代码。