簡體   English   中英

UIViewRepresentable 不更新綁定到 ObservedObject 屬性?

[英]UIViewRepresentable not updating binding to ObservedObject property?

This view is a UIKit slider adapted to my SwiftUI project because in SwiftUI Slider cannot change its track color, which is probably a bug since you should be able to change it with .accentColor . 無論如何,這個 slider 根據它的值改變它的軌道顏色,從綠色到紅色。 如果value綁定到普通的@State屬性,那么整個事情就可以完美地工作(盡管我的漸變還不是那么好),但是當您嘗試將其附加到@ObservedObject的屬性時,它會中斷,盡管軌道顏色仍然有效,它永遠不會改變基礎價值。 我想現在這只是一個錯誤,但更有可能這里有一些東西需要修復。

struct RedscaleSlider: UIViewRepresentable {
    
    @Binding var value: Double
    
    var min: Double
    var max: Double
    
    class Coordinator: NSObject {
        @Binding var value: Double
        var min: Double
        var max: Double
        
        init(value: Binding<Double>, min: Double = 0, max: Double = 100) {
           _value = value
            self.min = min
            self.max = max
        }
        
        @objc func valueChanged(_ sender: UISlider) {
            self.value = Double(sender.value)
            sender.minimumTrackTintColor = green_to_red_gradient(value: (Double(sender.value) - min) / (max - min)).into_UIKit_color()
        }
    }
    
    var thumb_color: UIColor = .white
    var track_color: UIColor = .systemBlue
    
    func makeUIView(context: Context) -> UISlider {
        let slider = UISlider(frame: .zero)
        
        slider.addTarget(
            context.coordinator,
            action: #selector(Coordinator.valueChanged),
            for: .valueChanged
        )
        
        slider.thumbTintColor = thumb_color
        slider.minimumTrackTintColor = track_color
        slider.minimumValue = Float(min)
        slider.maximumValue = Float(max)
        slider.value = Float(value)
        
        return slider
    }
    
    func updateUIView(_ UI_View: UISlider, context: Context) {
        UI_View.value = Float(self.value)
    }
    
    func makeCoordinator() -> RedscaleSlider.Coordinator {
        Coordinator(value: $value, min: self.min, max: self.max)
    }
}

編輯:它應該如何使用的例子:

class ViewModel: ObservableObject {
    @Published var danger_level: Double
}
struct ExampleView: View {
    @ObservedObject var view_model = ViewModel(danger_level: 50)
    
    var body: some View {
        VStack {
            Text(view_model.danger_level.description)
            RedscaleSlider(value: $view_model.danger_level)
            // should update view model just like a Stepper would
        }
    }
}

@Binding只應該在View / UIViewRepresentable中使用

而不是在Coordinator中使用@Binding切換init以接收init(_ parent: RedscaleSlider)然后使用parent.value = Double(sender.value)

import SwiftUI

class RedscaleSliderViewModel : ObservableObject {
    @Published var value : Double = 5
    @Published var danger_level: Double = 7.5

}
struct ParentRedscaleSlider: View{
    //@State var value: Double = 5
    @ObservedObject var vm = RedscaleSliderViewModel()
    var body: some View {
        VStack{
            Text(vm.danger_level.description)
            RedscaleSlider(value: $vm.danger_level, min: 0, max: 10)
            
        }
    }
}
struct RedscaleSlider: UIViewRepresentable {
    //@EnvironmentObject var vm: RedscaleSliderViewModel
    @Binding var value: Double
    
    var min: Double
    var max: Double
    
    class Coordinator: NSObject {
        var parent: RedscaleSlider
        
        init(_ parent: RedscaleSlider) {
            self.parent = parent
        }
        
        @objc func valueChanged(_ sender: UISlider) {
            let senderVal = Double(sender.value)
            self.parent.value = senderVal
            
            //Missing code
            //sender.minimumTrackTintColor = green_to_red_gradient(value: (Double(sender.value) - min) / (max - min)).into_UIKit_color()
        }
    }
    
    var thumb_color: UIColor = .white
    var track_color: UIColor = .systemBlue
    
    func makeUIView(context: Context) -> UISlider {
        let slider = UISlider(frame: .zero)
        
        slider.addTarget(
            context.coordinator,
            action: #selector(Coordinator.valueChanged),
            for: .valueChanged
        )
        
        slider.thumbTintColor = thumb_color
        slider.minimumTrackTintColor = track_color
        slider.minimumValue = Float(min)
        slider.maximumValue = Float(max)
        slider.value = Float(value)
        
        return slider
    }
    
    func updateUIView(_ UI_View: UISlider, context: Context) {
        UI_View.value = Float(self.value)
    }
    
    func makeCoordinator() -> RedscaleSlider.Coordinator {
        Coordinator(self)
    }
}

struct RedScaleSlider_Previews: PreviewProvider {
    static var previews: some View {
        ParentRedscaleSlider()
    }
}

accentColor對我來說很好用..

您的代碼也適用於 ObservableObject。 這是演示代碼:

class ViewModel : ObservableObject {
    @Published var double : Double = 0.0
}
struct ContentView : View {
    @State private var value: Double = 0
    
    @ObservedObject var viewModel = ViewModel()

    var body : some View {
        Slider(value: $value, in: -100...100, step: 0.1)
            .accentColor(.red) //<< here accent color
        
        RedscaleSlider(value: $viewModel.double, min: 5.0, max: 250.0)
        Text(String(viewModel.double))
    }
    
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM