gpt4 book ai didi

ios - 具有双向绑定(bind)的自定义 SwiftUI View

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

我正在努力实现一个自定义 View ,它可以将 Binding 作为参数并实现该值的双向更新。

所以基本上我正在实现我的自定义 slider 并希望它的初始化程序是这样的:

MySlider(value: <Binding<Float>)


我遇到的问题:

  1. 如何订阅绑定(bind)值的远程更新以便更新 View 的状态?
  2. 有什么好的方法可以将 Binding 与 @State 属性绑定(bind)在一起吗?

这是我目前的实现方式,但并不完美。

struct MySlider: View {

@Binding var selection: Float?
@State private var selectedValue: Float?

init(selection: Binding<Float?>) {
self._selection = selection

// https://stackoverflow.com/a/58137096
_selectedValue = State(wrappedValue: selection.wrappedValue)
}

var body: some View {
HStack(spacing: 3) {
ForEach(someValues) { (v) in
Item(value: v,
isSelected: v == self.selection)
.onTapGesture {
// No idea how to do that other way so I don't have to set it twice
self.selection = v
self.selectedValue = v
}
}
}
}
}

编辑 1:我想我的问题是底层模型对象来自核心数据,不属于任何会观察其变化的 SwiftUI View 。模型对象属于 UIKit ViewController,我只是传递绑定(bind)到 SwiftUI View 是不够的。我现在的解决方案是将模型对象也传递给 SwiftUI View ,以便它可以将其标记为 @ObservedObject。 .

struct MySlider<T>: View where T: ObservableObject {

@ObservedObject var object: T
@Binding var selection: Float?

var body: some View {
return ScrollView(.horizontal, showsIndicators: false) {
HStack(spacing: 3) {
ForEach(values) { (v) in
Item(value: v,
isSelected: v == self.selection)
.onTapGesture {
self.selection = v
}
}
}
}
}
}

最佳答案

@Binding 的定义本质上是与底层数据项的双向连接,例如 另一个@State 变量> 查看。如 Apple 所述:

Use a binding to create a two-way connection between a view and its underlying model.

如果它是一个绑定(bind),SwiftUI 将在值发生变化时自动更新它的 View ;所以(在回答您的第一个问题时),您不需要进行任何类型的订阅来更新您的自定义 View - 这将自动发生。

同样(关于你的第二个问题),因为绑定(bind)是来自另一个 View 的状态,你不应该将它声明为你 View 的状态,我也不相信这是可能的。 State 应该是您 View 的纯粹内部值(Apple 强烈建议将所有 @State 属性声明为 private)。

这一切都与 Apple 在推出 SwiftUI 时强调的“单一事实来源”概念有关:该绑定(bind)已经是 @State 的父 View 拥有信息,因此它不是您的 View 也应该声明为一个州。

对于您的代码,我认为您需要做的就是去掉第二个状态属性,因为它不是必需的。只需确保您传递的绑定(bind)是拥有自定义 View 的任何父 View 中的 @State 属性,然后使用 $ 语法将其传递以创建该绑定(bind)。 This article如果需要,可以更详细地介绍这个想法。

struct MySlider: View {

@Binding var selection: Float?

init(selection: Binding<Float?>) {
self._selection = selection
}

var body: some View {
HStack(spacing: 3) {
ForEach(someValues) { (v) in
Item(value: v, isSelected: v == self.selection)
.onTapGesture {
self.selection = v
}
}
}
}
}

关于ios - 具有双向绑定(bind)的自定义 SwiftUI View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60285177/

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