微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

将@Published属性从视图控制器传递到SwiftUI

如何解决将@Published属性从视图控制器传递到SwiftUI

假设您有一个旧的视图控制器,我想与SwiftUI一起使用。视图控制器具有一个@Published属性,其中包含它的当前状态:

class LegacyViewController: UIViewController {
    enum State {
        case opened
        case closed
        case halfOpened
    }
    
    @Published var state: State
    
    override init(nibName nibNameOrNil: String?,bundle nibBundleOrNil: Bundle?) {
        self.state = .closed
        super.init(nibName: nil,bundle: nil)
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // state is changed after some time
    }
}

理想情况下,我想像这样在SwiftUI中使用它:

struct ContentView: View {
    @State var state: LegacyViewController.State
    
    var body: some View {
        VCWrapper(state: $state).overlay (
            Text("\(state)")
        )
    }
}

这意味着我需要实现UIViewControllerRepresentable协议:

struct VCWrapper: UIViewControllerRepresentable {
    @Binding var state: LegacyViewController.State
    
    func makeUIViewController(context: Context) -> LegacyViewController {
        let vc = LegacyViewController(nibName: nil,bundle: nil)
        /// where to perform the actual binding?
        return vc
    }
    
    func updateUIViewController(_ uiViewController: LegacyViewController,context: Context) {
        
    }
}

但是,我在弄清楚从state的{​​{1}}属性LegacyViewController公开的state属性的实际绑定时遇到了麻烦。如果VCWrapper公开了一个委托,我可以通过LegacyViewController对象来实现绑定,但是考虑到我不使用委托对象,我不确定如何做到这一点?

解决方法

这是可能的解决方法-使用Combine。在Xcode 12 / iOS 14上进行了测试。

import Combine

struct VCWrapper: UIViewControllerRepresentable {
    @Binding var state: LegacyViewController.State
    
    func makeUIViewController(context: Context) -> LegacyViewController {
        let vc = LegacyViewController(nibName: nil,bundle: nil)

        // subscribe to controller state publisher and update bound
        // external state
        context.coordinator.cancelable = vc.$state
            .sink {
               DispatchQueue.main.async {
                  _state.wrappedValue = $0
               }
            }

        return vc
    }
    
    func updateUIViewController(_ uiViewController: LegacyViewController,context: Context) {
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator()
    }
    
    class Coordinator {
        var cancelable: AnyCancellable?
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。