Swift Combine 中的双向绑定
Two-way binding in Swift Combine
我有一个进度条和一个文本字段,两者都根据彼此的输入进行更新:
class ViewModel: ObservableObject {
@Published var progressBarValue: Double {
didSet {
textFieldValue = String(progressBarValue)
}
}
@Published var textFieldValue: String {
didSet {
progressBarValue = Double(progressBarValue)
}
}
}
由于更新一个更新另一个,我最终在我的代码中有一个无限递归。
有没有办法使用 Combine 或纯 swift 代码来解决这个问题?
也许避免循环的额外检查会起作用?
@Published var progressBarValue: Double {
didSet {
let newText = String(progressBarValue)
if newText != textFieldValue {
textFieldValue = newText
}
}
}
@Published var textFieldValue: String {
didSet {
if let newProgress = Double(textFieldValue),
abs(newProgress - progressBarValue) > Double.ulpOfOne {
progressBarValue = newProgress
}
}
}
扩展我的评论,这是一个滑块和文本字段的最小示例,它们都通过双向绑定控制(并被控制)一个值:
class ViewModel: ObservableObject {
@Published var progress: Double = 0
}
struct ContentView: View {
@EnvironmentObject var model: ViewModel
var body: some View {
VStack {
TextField("", value: self.$model.progress, formatter: NumberFormatter())
Slider(value: self.$model.progress, in: 0...100)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
.environmentObject(ViewModel())
}
}
请注意,我还必须在 AppDelegate 上向我的环境中注入一个 ViewModel
实例才能使其正常工作(在预览版和实际应用程序中)
我有一个进度条和一个文本字段,两者都根据彼此的输入进行更新:
class ViewModel: ObservableObject {
@Published var progressBarValue: Double {
didSet {
textFieldValue = String(progressBarValue)
}
}
@Published var textFieldValue: String {
didSet {
progressBarValue = Double(progressBarValue)
}
}
}
由于更新一个更新另一个,我最终在我的代码中有一个无限递归。
有没有办法使用 Combine 或纯 swift 代码来解决这个问题?
也许避免循环的额外检查会起作用?
@Published var progressBarValue: Double {
didSet {
let newText = String(progressBarValue)
if newText != textFieldValue {
textFieldValue = newText
}
}
}
@Published var textFieldValue: String {
didSet {
if let newProgress = Double(textFieldValue),
abs(newProgress - progressBarValue) > Double.ulpOfOne {
progressBarValue = newProgress
}
}
}
扩展我的评论,这是一个滑块和文本字段的最小示例,它们都通过双向绑定控制(并被控制)一个值:
class ViewModel: ObservableObject {
@Published var progress: Double = 0
}
struct ContentView: View {
@EnvironmentObject var model: ViewModel
var body: some View {
VStack {
TextField("", value: self.$model.progress, formatter: NumberFormatter())
Slider(value: self.$model.progress, in: 0...100)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
.environmentObject(ViewModel())
}
}
请注意,我还必须在 AppDelegate 上向我的环境中注入一个 ViewModel
实例才能使其正常工作(在预览版和实际应用程序中)