面试题答案
一键面试- 编译选项:
- 确保第三方库以手动引用计数(MRC)方式编译。在Xcode项目设置中,针对第三方库的目标,将“Objective - C Automatic Reference Counting”设置为“NO”。
- 代码修改:
- 隔离MRC代码:将第三方库代码放在单独的文件或模块中,这样可以更好地管理其内存,并且减少对ARC代码的影响。
- 桥接函数:在ARC代码与MRC代码交互的边界处,创建桥接函数。这些函数负责处理内存管理的转换。例如,如果从MRC函数返回一个对象,在桥接函数中,使用
__bridge
、__bridge_retained
或__bridge_transfer
等关键字来处理对象所有权的转换。 - ARC代码调用MRC函数:
- 如果MRC函数返回一个对象,并且ARC代码需要接管该对象的所有权,使用
__bridge_transfer
关键字。例如:id mrcFunctionReturningObject(); id obj = CFBridgingRelease(mrcFunctionReturningObject()); // 这里`obj`现在由ARC管理
- 如果MRC函数返回一个对象,但ARC代码不需要接管所有权,使用
__bridge
关键字。例如:id mrcFunctionReturningObject(); id obj = (__bridge id)mrcFunctionReturningObject(); // `obj`仍由MRC管理,ARC代码仅使用该对象
- 如果MRC函数返回一个对象,并且ARC代码需要接管该对象的所有权,使用
- MRC代码调用ARC函数:
- 如果ARC函数返回一个对象,并且MRC代码需要接管该对象的所有权,使用
__bridge_retained
关键字。例如:id arcFunctionReturningObject(); id obj = (__bridge_retained id)arcFunctionReturningObject(); // 这里`obj`现在由MRC管理,需要在适当的时候释放 CFRelease((CFTypeRef)obj);
- 如果ARC函数返回一个对象,并且MRC代码需要接管该对象的所有权,使用
- 特定内存管理语法:
- MRC部分:在第三方库(MRC)代码中,严格遵循手动引用计数规则。使用
retain
增加对象的引用计数,release
减少引用计数,autorelease
将对象放入自动释放池。例如:MyObject *obj = [[MyObject alloc] init]; [obj retain]; // 使用obj [obj release];
- ARC部分:在ARC代码中,遵循ARC的内存管理规则。对象的创建、释放由ARC自动处理,无需手动调用
retain
、release
等方法。例如:MyObject *obj = [[MyObject alloc] init]; // 使用obj,ARC会自动释放
- MRC部分:在第三方库(MRC)代码中,严格遵循手动引用计数规则。使用
- 内存泄漏和野指针检测:
- 静态分析:使用Xcode的静态分析工具(Analyze),它可以检测出一些潜在的内存泄漏和野指针问题。对于MRC代码,静态分析可以检查是否有未平衡的
retain
和release
调用;对于ARC和MRC混合的代码,可以检查桥接关键字使用是否正确。 - 运行时检测:在开发和测试阶段,启用僵尸对象模式(Zombie Objects)。在Xcode的Scheme设置中,在“Diagnostics”选项卡下,勾选“Enable Zombie Objects”。这可以帮助检测野指针访问,因为当一个对象被释放后,系统会将其转换为僵尸对象,当再次访问该对象时,会抛出异常并给出详细的错误信息。
- 静态分析:使用Xcode的静态分析工具(Analyze),它可以检测出一些潜在的内存泄漏和野指针问题。对于MRC代码,静态分析可以检查是否有未平衡的