SwiftUI为什么context.coordinator.value.wrappedValue只返回初始值?

时间:2020-10-12 14:01:30

标签: ios swift swiftui

我正在尝试在我的SwiftUI应用中实现一些UIKit组件。我已成功将UISlider添加到我的SwiftUI视图。但是有一件事困扰着我。当我移动滑块时,值可以更新,但是我很想知道为什么context.coordinator.value.wrappedValue保持不变?这是我的实现:

time

现在这让我很麻烦:

import SwiftUI

struct UISliderView: UIViewRepresentable {
typealias UIViewType = UISlider

@Binding var value: Double
var minValue: Double
var maxValue: Double

func makeUIView(context: Context) -> UISlider {
    let slider = UISlider(frame: .zero)
    slider.maximumValue = Float(minValue)
    slider.maximumValue = Float(maxValue)
    slider.value = Float(value)
    slider.addTarget(context.coordinator,
                     action: #selector(Coordinator.valueChanged(_:)),
                     for: .valueChanged)
    return slider
}

func updateUIView(_ uiView: UISlider, context: Context) {
    print("Value: \(value)")
    print("Wrapped value: \(context.coordinator.value.wrappedValue)")
    uiView.value = Float(value)
}

func makeCoordinator() -> Coordinator {
    let coordinator = Coordinator(value: $value)
    coordinator.id = 5
    return coordinator
}

class Coordinator: NSObject {
    var value: Binding<Double>
    var id: Int = 0
    
    init(value: Binding<Double>) {
        self.value = value
    }
    
    @objc func valueChanged(_ sender: UISlider) {
        value.wrappedValue = Double(sender.value)
    }
}
}

这些值应该相同,或者至少我希望它们相同,但是却不相同?

1 个答案:

答案 0 :(得分:1)

功劳应归功于@Asperi和@ClausJørgensen

如果您异步打印context.coordinator的包装值,如下所示,则它的值是正确的。

我不知道为什么会这样,我对此很好奇。从理论上讲,由于context.coordinator.value应该与UISliderView和Coordinator具有相同的绑定。因此,它们应该在同一时间更新。

import SwiftUI

struct ContentView: View {
    @State var value: Double = 0
    
    var body: some View {
        UISliderView(value: $value, minValue: 0, maxValue: 10)
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}


struct UISliderView: UIViewRepresentable {
    typealias UIViewType = UISlider

    @Binding var value: Double
    var minValue: Double
    var maxValue: Double

    init(value: Binding<Double>, minValue: Double, maxValue: Double) {
        print("UISliderView", #function)

        self._value = value
        self.minValue = minValue
        self.maxValue = maxValue
    }

    func makeUIView(context: Context) -> UISlider {
        print("UISliderView", #function)

        let slider = UISlider(frame: .zero)
        slider.maximumValue = Float(minValue)
        slider.maximumValue = Float(maxValue)
//        slider.value = Float(value)
        slider.addTarget(context.coordinator,
                         action: #selector(Coordinator.valueChanged(_:)),
                         for: .valueChanged)
        return slider
    }

    func updateUIView(_ uiView: UISlider, context: Context) {
        print("UISliderView", #function, "coordinator", ObjectIdentifier(context.coordinator))

        print("UISliderView", "Value: \(value)")
        DispatchQueue.main.async {
            print("UISliderView", "Wrapped value: \(context.coordinator.value.wrappedValue)")
        }
        uiView.value = Float(value)
    }

    func makeCoordinator() -> Coordinator {
        print("UISliderView", #function)

        let coordinator = Coordinator(value: $value)
        coordinator.id = 5
        return coordinator
    }

    class Coordinator: NSObject {
        var value: Binding<Double>
        var id: Int = 0

        init(value: Binding<Double>) {
            self.value = value
            super.init()
            print("Coordinator", #function, ObjectIdentifier(self))
        }

        @objc func valueChanged(_ sender: UISlider) {
            print("Coordinator", #function, "newValue:", value.wrappedValue)
            value.wrappedValue = Double(sender.value)
        }
    }
}
UISliderView init(value:minValue:maxValue:)
UISliderView makeCoordinator()
Coordinator init(value:) ObjectIdentifier(0x00006000018b4d50)
UISliderView makeUIView(context:)
UISliderView updateUIView(_:context:) coordinator ObjectIdentifier(0x00006000018b4d50)
UISliderView Value: 0.0
UISliderView Wrapped value: 0.0
UISliderView updateUIView(_:context:) coordinator ObjectIdentifier(0x00006000018b4d50)
UISliderView Value: 0.0
UISliderView Wrapped value: 0.0
Coordinator valueChanged(_:) newValue: 0.0
Coordinator valueChanged(_:) newValue: 0.0
Coordinator valueChanged(_:) newValue: 0.0
UISliderView updateUIView(_:context:) coordinator ObjectIdentifier(0x00006000018b4d50)
UISliderView Value: 0.03875968977808952
UISliderView Wrapped value: 0.03875968977808952
Coordinator valueChanged(_:) newValue: 0.03875968977808952
UISliderView updateUIView(_:context:) coordinator ObjectIdentifier(0x00006000018b4d50)
UISliderView Value: 0.1550387591123581
UISliderView Wrapped value: 0.1550387591123581
Coordinator valueChanged(_:) newValue: 0.1550387591123581
UISliderView updateUIView(_:context:) coordinator ObjectIdentifier(0x00006000018b4d50)
UISliderView Value: 0.23255814611911774
UISliderView Wrapped value: 0.23255814611911774
Coordinator valueChanged(_:) newValue: 0.23255814611911774