Swift调用Obj-C时的FunSDK内存管理问题求助
解决方案:阻止ARC提前释放FunSDKWrapper实例
方案1:利用ARC强引用延长生命周期(推荐)
核心思路是在Swift侧和Obj-C++ wrapper内部同时持有强引用,直到异步回调完成后再主动释放。
Swift插件类实现
import Capacitor @objc(FunSDKPlugin) class FunSDKPlugin: CAPPlugin { // 强引用持有wrapper,防止ARC提前回收 private var sdkWrapper: FunSDKWrapper? @objc func initSDK(_ call: CAPPluginCall) { sdkWrapper = FunSDKWrapper() // 设置回调,回调完成后释放wrapper sdkWrapper?.setCompletionHandler { [weak self] result in call.resolve(["result": result]) // 回调结束,允许ARC回收wrapper self?.sdkWrapper = nil } // 调用异步初始化方法 sdkWrapper?.iniXMSDK() } }
Obj-C++ Wrapper实现(.mm文件)
#import "FunSDKWrapper.h" #include "FunSDK.h" @interface FunSDKWrapper () @property (nonatomic, copy) void(^completionHandler)(NSString *result); // 内部持有自身强引用,双重保障不被提前释放 @property (nonatomic, strong) FunSDKWrapper *selfReference; @end @implementation FunSDKWrapper - (instancetype)init { self = [super init]; if (self) { // 将当前wrapper实例绑定到FunSDK的回调上下文 SetFunSDKResultCallback(self, OnFunSDKResult); } return self; } - (void)setCompletionHandler:(void(^)(NSString *result))handler { _completionHandler = handler; // 持有自身强引用,直到回调完成 self.selfReference = self; } // FunSDK异步回调的C函数 void OnFunSDKResult(void *context, const char *result) { // 将C上下文转换为Obj-C++实例 FunSDKWrapper *wrapper = (__bridge FunSDKWrapper *)context; NSString *resultStr = [NSString stringWithUTF8String:result]; if (wrapper.completionHandler) { wrapper.completionHandler(resultStr); // 回调完成,清空引用,允许ARC回收 wrapper.selfReference = nil; wrapper.completionHandler = nil; } } - (void)iniXMSDK { // 调用C++ SDK的异步初始化方法 IniXMSDK(); } @end
桥接头文件(FunSDKWrapper.h)
#import <Foundation/Foundation.h> @interface FunSDKWrapper : NSObject - (void)iniXMSDK; - (void)setCompletionHandler:(void(^)(NSString *result))handler; @end
方案2:单独禁用该类的ARC
如果更习惯手动管理内存,可以单独对FunSDKWrapper.mm禁用ARC:
- 在Xcode中选中项目目标,进入Build Phases > Compile Sources
- 找到
FunSDKWrapper.mm,双击其编译标志列,添加-fno-objc-arc
禁用ARC后的Wrapper实现
#import "FunSDKWrapper.h" #include "FunSDK.h" @interface FunSDKWrapper () @property (nonatomic, copy) void(^completionHandler)(NSString *result); @end @implementation FunSDKWrapper - (instancetype)init { self = [super init]; if (self) { SetFunSDKResultCallback(self, OnFunSDKResult); [self retain]; // 手动持有实例,防止被提前释放 } return self; } - (void)setCompletionHandler:(void(^)(NSString *result))handler { _completionHandler = [handler copy]; } void OnFunSDKResult(void *context, const char *result) { FunSDKWrapper *wrapper = (__bridge FunSDKWrapper *)context; NSString *resultStr = [NSString stringWithUTF8String:result]; if (wrapper.completionHandler) { wrapper.completionHandler(resultStr); [wrapper.completionHandler release]; wrapper.completionHandler = nil; [wrapper release]; // 回调完成后手动释放实例 } } - (void)iniXMSDK { IniXMSDK(); } - (void)dealloc { [_completionHandler release]; [super dealloc]; } @end
注意事项
- 禁用ARC后必须手动调用
retain/release管理内存,否则会出现内存泄漏或野指针问题 - 推荐优先使用方案1,符合iOS现代开发的内存管理规范
内容的提问来源于stack exchange,提问作者jalixdesign
相关产品推荐
相关产品推荐

