gpt4 book ai didi

swiftui - UIViewRepresentable 无法在模态呈现的 SwiftUI View 中工作

转载 作者:行者123 更新时间:2023-12-05 06:58:49 25 4
gpt4 key购买 nike

为了定制一个UISlider ,我在 UIViewRepresentable 中使用它.它公开了一个 @Binding var value: Double这样我的 View 模型 ( ObservableObject ) View 可以观察到更改并更新 View相应地。

问题是 View 在 @Binding 时没有更新。值被改变。在下面的示例中,我有两个 slider 。一位原生Slider和一个定制SwiftUISlider .

两者都将绑定(bind)值传递给应该更新 View 的 View 模型。 native Slider会更新 View 但不会更新自定义 View 。在日志中,我可以看到 $sliderValue.sink { ... 被正确调用,但 View 未更新。

我注意到当呈现 View 有 @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode> 时会发生这种情况属性(property)。如果我将其注释掉,它会按预期工作。

enter image description here

重现此代码的完整示例代码是

import SwiftUI
import Combine

struct ContentView: View {
@State var isPresentingModal = false

// comment this out
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>

var body: some View {
VStack {
Button("Show modal") {
isPresentingModal = true
}
.padding()
}
.sheet(isPresented: $isPresentingModal) {
MyModalView(viewModel: TempViewModel())
}
}
}

class TempViewModel: ObservableObject {
@Published var sliderText = ""
@Published var sliderValue: Double = 0
private var cancellable = Set<AnyCancellable>()

init() {
$sliderValue
.print("view model")
.sink { [weak self] value in
guard let self = self else { return }
print("updating view \(value)")
self.sliderText = "\(value) C = \(String(format: "%.2f" ,value * 9 / 5 + 32)) F"
}
.store(in: &cancellable)
}
}

struct MyModalView: View {
@ObservedObject var viewModel: TempViewModel

var body: some View {
VStack(alignment: .leading) {
Text("SwiftUI Slider")
Slider(value: $viewModel.sliderValue, in: -100...100, step: 0.5)
.padding(.bottom)

Text("UIViewRepresentable Slider")
SwiftUISlider(minValue: -100, maxValue: 100, value: $viewModel.sliderValue)
Text(viewModel.sliderText)
}
.padding()
}
}

struct SwiftUISlider: UIViewRepresentable {
final class Coordinator: NSObject {
var value: Binding<Double>
init(value: Binding<Double>) {
self.value = value
}

@objc func valueChanged(_ sender: UISlider) {
let index = Int(sender.value + 0.5)
sender.value = Float(index)
print("value changed \(sender.value)")
self.value.wrappedValue = Double(sender.value)
}
}

var minValue: Int = 0
var maxValue: Int = 0

@Binding var value: Double

func makeUIView(context: Context) -> UISlider {
let slider = UISlider(frame: .zero)
slider.minimumTrackTintColor = .systemRed
slider.maximumTrackTintColor = .systemRed
slider.maximumValue = Float(maxValue)
slider.minimumValue = Float(minValue)

slider.addTarget(
context.coordinator,
action: #selector(Coordinator.valueChanged(_:)),
for: .valueChanged
)

adapt(slider, context: context)
return slider
}

func updateUIView(_ uiView: UISlider, context: Context) {
adapt(uiView, context: context)
}

func makeCoordinator() -> SwiftUISlider.Coordinator {
Coordinator(value: $value)
}

private func adapt(_ slider: UISlider, context: Context) {
slider.value = Float(value)
}
}

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

最佳答案

我发现了问题。在 updateUIViewUIViewRepresentable ,我还需要将绑定(bind)传递给 SwiftUISlider 的新实例:

func updateUIView(_ uiView: UISlider, context: Context) {
uiView.value = Float(value)

// the _value is the Binding<Double> of the new View struct, we pass it to the coordinator
context.coordinator.value = _value
}

SwiftUI.View可以随时重新创建,当它发生时 updateUIView叫做。一个新的 View 结构有一个新的 var value: Binding<Double>所以我们将它分配给我们的协调员

关于swiftui - UIViewRepresentable 无法在模态呈现的 SwiftUI View 中工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64533899/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com