SwiftUI中如何实现Objective-C库的Delegate/Protocol方法?
在SwiftUI中实现Objective-C代理协议的解决方案
问题核心原因
- 值类型无法适配OC代理系统:SwiftUI视图是
struct(值类型),而Objective-C的代理机制仅支持引用类型(NSObject子类)——OC的id指向的是类实例,值类型无法被OC的消息传递系统识别。 - OC代码本身的Selector错误:原OC库中检查的
@selector(endEvent: done:)与协议定义的endEvent:不匹配,这是逻辑错误,即使UIKit场景下能偶然工作,也会导致SwiftUI场景下直接失败。 - Swift方法签名不匹配:你在SwiftUI视图中写的
endEvent(sender: Myclass , endEvent done:Bool),和OC协议要求的endEvent(_ done: Bool)签名完全不符。
修复步骤
步骤1:修正OC库的Selector错误(优先处理)
如果有权限修改OC库,把notifyEndEvent中的Selector检查改为正确的协议方法签名:
-(void)notifyEndEvent { if (myDelegate == nil) return; // 修正:协议方法是endEvent:,不是endEvent: done: if ([myDelegate respondsToSelector:@selector(endEvent:)]) { [myDelegate endEvent:done]; } else { printf("endEvent not implemented by the caller\n"); } }
步骤2:创建代理中转类(适配OC与SwiftUI)
由于SwiftUI视图是值类型,需要创建一个NSObject子类作为代理中转,承接OC的代理事件后,通过闭包传递给SwiftUI视图:
// 代理中转类,遵循OC的CustomDelegate协议 class CustomDelegateHandler: NSObject, CustomDelegate { // 闭包用于将OC事件传递给SwiftUI视图 var onEndEvent: ((Bool) -> Void)? // 实现OC协议要求的方法 func endEvent(_ done: Bool) { onEndEvent?(done) } }
步骤3:在SwiftUI视图中使用中转类
struct ContentView: View { // 用@StateObject保持代理类实例的生命周期稳定 @StateObject private var delegateHandler = CustomDelegateHandler() @State private var myclass = Myclass() var body: some View { Button("Start") { start() } .onAppear { // 绑定事件回调 delegateHandler.onEndEvent = { done in print("endEvent \(done)") // 在这里处理SwiftUI侧的UI更新逻辑 } } } private func start() { // 将中转类实例设置为OC对象的代理 myclass.setDelegate(delegateHandler) } }
关键说明
@StateObject用于保证代理中转类的实例在SwiftUI视图刷新时不会被重新创建,确保OC侧能持续找到正确的代理对象。- 中转类作为NSObject子类,完全符合OC对代理对象的类型要求,能被OC的
respondsToSelector正确识别。
内容的提问来源于stack exchange,提问作者wzxecr
相关产品推荐
相关产品推荐

