面试题答案
一键面试1. 引用计数内存管理机制的不同
- Objective - C引用计数(MRC,Manual Reference Counting):
- 手动操作:开发者需要手动调用
retain
、release
和autorelease
方法来管理对象的引用计数。当调用retain
时,对象的引用计数加1;调用release
时,引用计数减1;当引用计数为0时,对象的内存被释放。例如:
- 手动操作:开发者需要手动调用
NSObject *obj = [[NSObject alloc] init]; // 创建对象,引用计数为1
[obj retain]; // 引用计数加1,变为2
[obj release]; // 引用计数减1,变为1
[obj release]; // 引用计数减1,变为0,对象内存被释放
- 容易出错:如果过度调用
release
导致提前释放对象,会引发悬空指针问题;若忘记调用release
则会造成内存泄漏。 - Swift自动引用计数(ARC,Automatic Reference Counting):
- 自动管理:ARC由编译器自动插入内存管理代码,开发者无需手动调用引用计数相关方法。编译器会在适当的位置自动添加
retain
(增加引用计数)和release
(减少引用计数)操作。例如:
- 自动管理:ARC由编译器自动插入内存管理代码,开发者无需手动调用引用计数相关方法。编译器会在适当的位置自动添加
class SomeClass {
// 类定义
}
var obj: SomeClass? = SomeClass() // 创建对象,引用计数增加
obj = nil // 引用计数减少,对象内存被释放
- 内存安全:ARC大大减少了手动管理内存带来的错误,如悬空指针和内存泄漏,但在处理循环引用时仍需开发者手动干预。
2. 混编开发中的问题
- 内存管理混乱:由于Objective - C的MRC需要手动管理,而Swift的ARC是自动管理,在混编时可能会出现一方释放了对象,另一方还在使用的情况。例如,在Objective - C代码中手动释放了一个对象,而Swift代码中持有该对象的引用,此时Swift代码访问该对象会导致程序崩溃。
- 循环引用:尽管Swift的ARC能自动处理大部分内存管理,但在与Objective - C混编时,由于双方内存管理方式不同,可能更容易出现循环引用问题。比如,Objective - C对象强引用Swift对象,Swift对象又强引用Objective - C对象,导致对象无法被释放。
3. 解决办法
- 确保一致性:如果项目大部分代码是Swift,尽量将Objective - C代码迁移到ARC模式。在Xcode项目设置中,可以将Objective - C文件的编译选项
Objective - C Automatic Reference Counting
设置为Yes
,这样Objective - C代码也能使用ARC。 - 处理循环引用:在Swift中使用
weak
或unowned
修饰符来打破循环引用。在Objective - C中,使用__weak
或__unsafe_unretained
修饰符。例如,在Swift中:
class SwiftClass {
var objCObject: NSObject?
}
class NSObjectSubclass: NSObject {
weak var swiftObject: SwiftClass?
}
在Objective - C中:
@interface NSObjectSubclass : NSObject
@property (nonatomic, weak) SwiftClass *swiftObject;
@end
- 谨慎传递对象:在Objective - C和Swift代码之间传递对象时,要明确对象的所有权。确保在释放对象之前,没有其他代码持有其有效引用。如果在Objective - C中手动释放对象,要确保Swift代码不再使用该对象。