SwiftUI,如何将 EnvironmnetObject Int 属性绑定到 TextField?
Posted
技术标签:
【中文标题】SwiftUI,如何将 EnvironmnetObject Int 属性绑定到 TextField?【英文标题】:SwiftUI, how to bind EnvironmnetObject Int property to TextField? 【发布时间】:2020-04-19 17:54:33 【问题描述】:我有一个 ObservableObject 应该保存我的应用程序状态:
final class Store: ObservableObject
@Published var fetchInterval = 30
现在,该对象被注入到我的层次结构的根部,然后在树下的某个组件中,我试图访问它并将其绑定到 TextField,即:
struct ConfigurationView: View
@EnvironmnetObject var store: Store
var body: some View
TextField("Fetch interval", $store.fetchInterval, formatter: NumberFormatter())
Text("\(store.fetchInterval)"
-
即使绑定了变量(使用
$
),属性也没有更新,初始值显示正确,但是当我更改它时,文本字段更改但绑定没有传播
与第一个问题相关的是,一旦值更改,我将如何接收事件,我尝试了以下 sn-p,但没有任何内容被触发(我假设是因为文本字段未正确绑定...
$fetchInterval
.debounce(for: 0.8, scheduler: RunLoop.main)
.removeDuplicates()
.sink interval in
print("sink from my code \(interval)")
非常感谢任何帮助。
编辑:我刚刚发现对于文本变量,绑定可以开箱即用,例如:
// on store
@Published var testString = "ropo"
// on component
TextField("Ropo", text: $store.testString)
Text("\(store.testString)")
只有 int 字段才不会正确更新变量
编辑 2:
好的,我刚刚发现仅更改字段是不够的,必须按Enter
才能传播更改,这不是我想要的,我希望每次更改字段时都传播更改...
【问题讨论】:
【参考方案1】:对于任何感兴趣的人,这是我最终得到的解决方案:
TextField("Seconds", text: Binding(
get: String(self.store.fetchInterval) ,
set: self.store.fetchInterval = Int($0.filter "0123456789".contains($0) ) ?? self.store.fetchInterval
))
添加无效字符时会有一点延迟,但这是最干净的解决方案,不允许在不重置 TextField 状态的情况下添加无效字符。
它还可以立即提交更改,而无需等待用户按 Enter 键或无需等待字段模糊。
【讨论】:
【参考方案2】:这样做,您甚至不必按 Enter。如果您将 Store() 放在 SceneDelegate 中,这也适用于 EnvironmentObject:
struct ContentView: View
@ObservedObject var store = Store()
var body: some View
VStack
TextField("Fetch interval", text: $store.fetchInterval)
Text("\(store.fetchInterval)")
关于您的第二个问题:在 SwiftUI 中,如果视图中的变量发生更改,视图总是会自动更新。
【讨论】:
嗯,是的,只是使用文本直接改变观察值,但验证呢?它只会尝试将文本放在那里对吗? 如果您只在 iPhone 上使用您的应用程序,最简单的解决方案是在您的 TextField 下添加“.keyboardType(.numberPad)”。请注意,在模拟器上,您必须在单击 TextField 后打开小键盘 (CMD+K) 才能正确模拟此行为。如需更复杂的解决方案,请查看:***.com/questions/58733003/… 不,不幸的是(?)我正在开发一个 mac 应用程序,所以允许文本值更让人头疼 此代码无法编译。 TextField 将 Binding如何在macos
上也能正常工作的简单解决方案,如下所示:
import SwiftUI
final class Store: ObservableObject
@Published var fetchInterval: Int = 30
struct ContentView: View
@ObservedObject var store = Store()
var body: some View
VStack
TextField("Fetch interval", text: Binding<String>(
get: String(format: "%d", self.store.fetchInterval) ,
set:
if let value = NumberFormatter().number(from: $0)
self.store.fetchInterval = value.intValue
))
Text("\(store.fetchInterval)").padding()
【讨论】:
我确实最终选择了类似的东西,谢谢以上是关于SwiftUI,如何将 EnvironmnetObject Int 属性绑定到 TextField?的主要内容,如果未能解决你的问题,请参考以下文章
如何将 UISearchController 与 SwiftUI 集成
如何将我的自定义 ButtonStyle 添加到 swiftui3 中的快捷方式 swiftui .buttonstyle() 属性