问题描述
在ARC模式下,如果使用旧的(MRC)Objectivce-C代码,必须改写或禁用ARC。
[newWidgetDescriptors release];
_controlDescriptors = [controlDescriptors retain];
_activityDescriptors = [activityDescriptors retain];
例如,上述代码在ARC模式下不被允许出现,因此会输出报错信息:
'release' is unavailable: not available in automatic reference counting mode
'retain' is unavailable: not available in automatic reference counting mode
这两个报错信息表示,当前项目开启了ARC(Automatic Reference Counting,自动引用计数),在ARC 模式下不能再手动调用 [object release]、retain、autorelease 这类方法。
解决方案
方案一:为该文件关闭ARC
在 Xcode 左侧点击项目,选择Target → 项目名称 → Build Phases →Compile Sources 列表。
找到报错的文件(例如本次报错的Widget → FooObject.mm文件),双击该行右侧的“Compiler Flags”列。
输入:
-fno-objc-arc

重新编译项目文件。
这样,.mm文件将使用MRC(手动引用计数),不会再报错。
Swift 和其他 .m 文件仍然保持ARC模式。
推荐这个解决方案,能够保留原有的代码逻辑,不破坏第三方库的兼容性。
方案二:改写ARC兼容形式
如果想要将项目文件完全使用ARC,不关闭文件的ARC。
在 ARC 下,retain / release / autorelease 都由编译器自动生成。
需要删除这些手动调用,并保持对象强引用或弱引用即可。
[newWidgetDescriptors release];
_controlDescriptors = [controlDescriptors retain];
_activityDescriptors = [activityDescriptors retain];
改写如下:
// 删除 [newWidgetDescriptors release];
self.controlDescriptors = controlDescriptors;
self.activityDescriptors = activityDescriptors;
改写条件如下:
1、_controlDescriptors 和 _activityDescriptors 必须是用 @property 定义的属性;
2、这些属性应声明为 strong 或 copy(取决于对象类型)。
示例:
@property (nonatomic, strong) NSArray *controlDescriptors;
@property (nonatomic, strong) NSArray *activityDescriptors;
注意:
如果这些变量是手动管理的 ivar(不是属性),那就改为使用属性;
删除所有 retain / release 调用;
不要再调用 dealloc 中的 [ivar release];。
方案三:临时宏兼容(不推荐)
临时加宏:
#if !__has_feature(objc_arc)
[newWidgetDescriptors release];
_controlDescriptors = [controlDescriptors retain];
_activityDescriptors = [activityDescriptors retain];
#else
_controlDescriptors = controlDescriptors;
_activityDescriptors = activityDescriptors;
#endif
不建议尝试使用该解决方案。
总结
推荐为文件关闭ARC,该操作更安全、快速、对文件没有破坏。
如果想要项目全部启用ARC,就需要删除 retain/release,改用 strong 属性。
最后的宏包裹,只建议在临时测试编译中使用,不建议长期使用。