swift 为什么XUIView中的`Binding< Bool>`看不到更新后的值?

2nc8po8w  于 2023-05-21  发布在  Swift
关注(0)|答案(1)|浏览(94)

为什么XUIView中的Binding<Bool>看不到更新后的值?
我有一个SwiftUI XView,它封装了一个XUIView。在XUIView中,我有一个Binding<Bool>,它是用XView@Binding...初始化的。在XUIView中,我有一个UIButton,我使用XUIView中的“Binding”属性切换customFlag。这很好地传播到SwiftUI视图中,因为Text正确更新。但是,UIButton的标题没有正确更新。XUIView._update方法不会“看到”新值。
我错过了什么?我是否必须在updateUIView方法中分配customFlag才能使其工作?
下面是一些print调用的示例代码,看看发生了什么:

import SwiftUI

struct UIKitBindingView: View {
    @State private var customFlag: Bool = false
    var body: some View {
        VStack {
            Text("customFlag: \(customFlag ? "ON" : "OFF")")
            XView(customFlag: $customFlag)
                .frame(width: 200, height: 100)
        }
    }
}

struct UIKitBindingView_Previews: PreviewProvider {
    static var previews: some View {
        UIKitBindingView()
    }
}

struct XView: UIViewRepresentable {
    typealias UIViewType = XUIView
    typealias Context = UIViewRepresentableContext<XView>
    @Binding var customFlag: Bool
    
    init(customFlag: Binding<Bool>) {
        self._customFlag = customFlag
    }

    func makeUIView(context: Context) -> XUIView {
        Swift.print("XView: \(#function)")
        let v = XUIView(frame: .zero, customFlag: $customFlag)
        return v
    }

    func updateUIView(_ uiView: XUIView, context: Context) {
        Swift.print("XView: \(#function)")
        // uiView.customFlag = $customFlag
        Swift.print("XView: \(#function): customFlag: \(customFlag) \n--\($customFlag)")
        uiView._update()
    }
}

class XUIView: UIView {
    weak var button: UIButton?
    var customFlag: Binding<Bool>
    
    init(frame: CGRect, customFlag: Binding<Bool>) {
        self.customFlag = customFlag
        super.init(frame: frame)
        Swift.print("XUIView: \(#function)")
        _configure()
    }
    
    required init?(coder: NSCoder) {
        self.customFlag = Binding(get: { true }, set: { v, t in })
        super.init(coder: coder)
        Swift.print("XUIView: \(#function)")
        _configure()
    }
    
    deinit {
        Swift.print("XUIView: \(#function)")
    }
    
    func _update() {
        Swift.print("XUIView: \(#function): \(customFlag.wrappedValue)\n--\(customFlag)")
        button?.setTitle("BUTTON:" + (customFlag.wrappedValue ? "ON" : "OFF"), for: .normal)
    }
    
    private func _configure() {
        backgroundColor = .yellow
        let b = UIButton()
        button = b
        self.addSubview(b)
        b.translatesAutoresizingMaskIntoConstraints = false
        let cons = [
            self.centerXAnchor.constraint(equalTo: b.centerXAnchor),
            self.centerYAnchor.constraint(equalTo: b.centerYAnchor),
        ]
        NSLayoutConstraint.activate(cons)
        b.setTitleColor(.systemBlue, for: .normal)
        b.addAction(UIAction(handler: { action in
            Swift.print("XUIView: \(#function): button action ***")
            self.customFlag.wrappedValue.toggle()
        }), for: .touchUpInside)
        _update()
    }
}

点击按钮后的控制台输出:

XUIView: __preview___configure(): button action ***
XView: __preview__updateUIView(_:context:)
XView: __preview__updateUIView(_:context:): customFlag: true 
--Binding<Bool>(transaction: SwiftUI.Transaction(plist: []), location: SwiftUI.LocationBox<SwiftUI.Binding<Swift.Bool>.(unknown context at $10594f2e0).ScopedLocation>, _value: true)
XUIView: __preview___update(): false
--Binding<Bool>(transaction: SwiftUI.Transaction(plist: []), location: SwiftUI.LocationBox<SwiftUI.Binding<Swift.Bool>.(unknown context at $10594f2e0).ScopedLocation>, _value: false)
qojgxg4l

qojgxg4l1#

不要调用XUIView的_update()(删除该方法),而是直接在updateUIView(_ uiView: XUIView, context: Context)中进行更新:

func updateUIView(_ uiView: XUIView, context: Context) {
        uiView.button?.setTitle("BUTTON:" + ($customFlag.wrappedValue ? "ON" : "OFF"), for: .normal)
}

相关问题