如何在无回调同步方法中调用Swift异步方法?适配OC框架
同步OC代理适配Swift Async代理的解决方案及可行性分析
适配器方案可行性结论
代理适配器方案完全可行,核心是通过手动实现「异步转同步」的逻辑,打通OC同步代理与Swift异步代理的调用链路,同时规避并发模型差异带来的编译错误与运行时问题。
核心解决思路
OC的同步代理方法需要阻塞等待Swift async方法的执行结果,这里用GCD信号量(Semaphore)实现同步阻塞,搭配后台队列调度异步任务,避免主线程死锁。
代码实现示例
1. OC端代理适配器类
这个类作为OC框架代理的实现者,同时持有Swift异步代理的引用,负责中转调用:
// OCProxyAdapter.h #import <Foundation/Foundation.h> @protocol OCFrameworkDelegate; @protocol SwiftAsyncProxy; @interface OCProxyAdapter : NSObject <OCFrameworkDelegate> @property (nonatomic, weak) id<SwiftAsyncProxy> swiftProxy; @end // OCProxyAdapter.m #import "OCProxyAdapter.h" #import "YourSwiftBridgeHeader.h" // 替换为你的Swift桥接头文件 @implementation OCProxyAdapter - (NSString *)frameworkRequestDataWithParam:(NSString *)param { dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); __block NSString *result = @""; // 切换到后台队列执行异步调用,避免主线程死锁 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // 用Task包裹Swift异步方法调用 Task { result = await self.swiftProxy?.requestData(param: param) ?? @""; // 异步任务完成后发送信号量,唤醒阻塞的主线程 dispatch_semaphore_signal(semaphore); } }); // 阻塞当前线程,等待异步任务结果 dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); return result; } @end
2. Swift端异步代理协议与实现
保持Swift原生的async/await写法,符合需求要求:
// SwiftAsyncProxy.swift @objc protocol SwiftAsyncProxy { func requestData(param: String) async -> String } // 示例实现类,业务逻辑写在这里 class MySwiftProxy: NSObject, SwiftAsyncProxy { func requestData(param: String) async -> String { // 模拟异步操作(比如网络请求、本地IO) await Task.sleep(nanoseconds: 1_000_000_000) return "Processed result for: \(param)" } }
3. 绑定适配器与代理
在Swift代码中完成适配器、Swift代理与OC框架的关联:
let framework = OCFramework.shared // 你的OC框架实例 let adapter = OCProxyAdapter() let swiftProxy = MySwiftProxy() adapter.swiftProxy = swiftProxy framework.delegate = adapter
关键注意事项
- 规避主线程死锁:如果OC框架的代理方法是在主线程调用的,必须把Swift异步方法的调度放到后台队列,否则会导致主线程阻塞死锁。
- 错误处理:如果Swift async方法可能抛出错误,需要在Task中用
do-catch捕获,设置合理的错误返回值,避免程序崩溃。 - 避免循环引用:OC适配器中对Swift代理使用
weak引用,防止出现循环引用导致内存泄漏。
内容的提问来源于stack exchange,提问作者HangarRash
相关产品推荐
相关产品推荐

