Unity iOS插件Objective-C静态属性二次访问崩溃问题求助
问题场景
为Unity开发iOS平台插件时,第二次调用_generateAppAttestKeyId函数,在执行auto *instance = [[AppattestPluginWrapper sharedInstance] appAttestPlugin];时触发Thread 1: EXC_BAD_ACCESS (code=1, address=0xb21c290b0)崩溃。断点显示sharedInstance返回值不为空,但在赋值instance的过程中崩溃。
排查方向与修复方案
检查
AppAttestPlugin实例是否被意外释放
尽管appAttestPlugin使用了strong属性,但如果AppAttestPlugin内部存在不合理的内存管理(比如ARC环境下手动调用release),或者被Unity侧生命周期逻辑间接回收,会导致指针指向已释放的内存空间。
修复建议:- 把
AppAttestPlugin改成单例模式,确保实例不会被意外释放:// 在AppAttestPlugin的实现中添加单例逻辑 + (instancetype)sharedInstance { static AppAttestPlugin *sharedPlugin = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sharedPlugin = [[self alloc] init]; }); return sharedPlugin; } - 修改
AppattestPluginWrapper的初始化代码,使用单例实例:sharedInstance.appAttestPlugin = [AppAttestPlugin sharedInstance];
- 把
排查线程安全问题
虽然AppattestPluginWrapper的单例用dispatch_once保证了线程安全,但如果AppAttestPlugin的初始化逻辑非线程安全,或者其他线程对appAttestPlugin属性进行了修改,可能导致二次访问时内存异常。
修复建议:- 确保
AppAttestPlugin的初始化过程不涉及非线程安全的资源操作; - 给
appAttestPlugin属性添加atomic修饰,保证属性访问的原子性:@property (nonatomic, strong, atomic) AppAttestPlugin *appAttestPlugin;
- 确保
适配Unity与iOS的生命周期差异
Unity在场景切换、后台唤醒等场景下,可能会重置iOS侧的部分对象,导致AppattestPluginWrapper单例虽存在,但内部的appAttestPlugin已被回收。
修复建议:
在调用前检查appAttestPlugin是否为空,为空则重新初始化:void _generateAppAttestKeyId(){ AppattestPluginWrapper *wrapper = [AppattestPluginWrapper sharedInstance]; if (!wrapper.appAttestPlugin) { wrapper.appAttestPlugin = [[AppAttestPlugin alloc] init]; } AppAttestPlugin *instance = wrapper.appAttestPlugin; // 后续回调逻辑保持不变 }避免
auto自动推导的类型匹配问题auto自动推导类型可能因AppAttestPlugin的实际类型与推导类型不匹配,导致访问属性时内存越界。
修复建议:
显式声明变量类型,替换auto:AppAttestPlugin *instance = [[AppattestPluginWrapper sharedInstance] appAttestPlugin];
内容的提问来源于stack exchange,提问作者Omer Hadad

