You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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:

  1. 在Xcode中选中项目目标,进入Build Phases > Compile Sources
  2. 找到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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 17:49:50