在SwiftUI中设置文本字段的初始值-比较新值和旧值

在SwiftUI中设置文本字段的初始值-比较新值和旧值,swiftui,Swiftui,我看过很多关于如何使用空文本字段收集新值的示例和教程,但没有一个演示如何使用文本字段编辑值 在我的用例中,我希望文本字段预填充/预填充来自我的viewmodel的数据,然后当用户编辑数据时,应该启用保存按钮。在我的表单中,我还有一个导航链接,它指向一个子页面,用户可以在该子页面中从列表中选择某个内容,然后返回表单 只要我使用一个空字段,它的行为就与所描述的一样;用户可以在字段中键入临时内容,导航到子页面,并且临时值仍然与他离开时一样 struct TextFieldDemo: View {

我看过很多关于如何使用空文本字段收集新值的示例和教程,但没有一个演示如何使用文本字段编辑值

在我的用例中,我希望文本字段预填充/预填充来自我的viewmodel的数据,然后当用户编辑数据时,应该启用保存按钮。在我的表单中,我还有一个导航链接,它指向一个子页面,用户可以在该子页面中从列表中选择某个内容,然后返回表单

只要我使用一个空字段,它的行为就与所描述的一样;用户可以在字段中键入临时内容,导航到子页面,并且临时值仍然与他离开时一样

struct TextFieldDemo: View {

    var model:String    // Actual a more complex view model
    @State var editedValue:String = ""

    var body: some View {
        VStack(alignment: .leading, spacing: 20) {
            Group{
                Text("Some label")
                TextField("Placeholder text", text: $editedValue)
            }
            Divider()
            Text("Some navigation link to push in a page where " +
                "the user can select something from a list and click back...")

            // If the user starts to edit the textfield - follows a navigation link and comes back
            // he should be able to continue edit the field where he left of - the text field should
            // not have been reset to the original value.

            Button(action: {
                // Call some save function in the ViewModel
                },label: {
                    Text("SAVE")
                }
            ).disabled(model == editedValue)
        }.onAppear(){
            // I could have done something like:
            //   self.editedValue = model
            // but it seems like this will fire if the user navigates into the described page and reset
            // the TextField to the model value.
        }
    }
}

struct TextFieldDemo_Previews: PreviewProvider {
    static var previews: some View {
        TextFieldDemo(model: "The old value")
    }
}

要使用模型中的值初始化文本字段,您需要定义自己的初始值设定项,并为
@State
变量使用
状态(wrappedValue:)
初始值设定项:

struct textfield演示:查看{
var模型:String//Actual一个更复杂的视图模型
@状态变量editedValue:字符串
init(模型:字符串){
self.model=model
self.\u editedValue=State(wrappedValue:model)/\u editedValue为State
}
var body:一些观点{
VStack(对齐:。前导,间距:20){
团体{
文本(“某些标签”)
文本字段(“占位符文本”,文本:$editedValue)
}
分隔器()
文本(“某个导航链接可在其中的页面中推送”+
“用户可以从列表中选择某些内容,然后单击“上一步…”)
//如果用户开始编辑文本字段-跟随导航链接并返回
//他应该能够继续编辑他留下的字段-文本字段应该
//未被重置为原始值。
按钮(操作:{
//在ViewModel中调用一些保存函数
},标签:{
文本(“保存”)
}
).disabled(model==editedValue)
}.onAppear(){
//我本可以这样做:
//self.editedValue=模型
//但是,如果用户导航到所描述的页面并重置,似乎会触发此操作
//将文本字段设置为模型值。
}
}
}
结构TextFieldDemo_预览:PreviewProvider{
静态var预览:一些视图{
TextFieldDemo(模型:“旧值”)
}
}

像这样的测试代码怎么样。关键是使用“ObservieObject”:

导入快捷界面
类MyModel:ObservableObject{
@已发布的var model=“model1”
}
结构ContentView:View{
@ObservedObject var myModel=myModel()
@状态变量editedValue=“”
var body:一些观点{
导航视图{
VStack(对齐:。前导,间距:20){
团体{
文本(“某些标签”)
文本字段(“占位符文本”,文本:绑定(
获取:{self.editedValue},
设置:{
self.editedValue=$0
self.myModel.model=self.editedValue
})).onAppear(执行:loadData)
}
分隔器()
导航链接(目的地:文本(“下一页”)){
文本(“单击我以显示下一个视图”)
}
//如果用户开始编辑文本字段-跟随导航链接并返回
//他应该能够继续编辑他留下的字段-文本字段应该
//未被重置为原始值。
按钮(操作:{
//在ViewModel中调用一些保存函数
self.myModel.model=self.editedValue
},标签:{
文本(“保存”)
})
}
}.navigationViewStyle(StackNavigationViewStyle())
}
func loadData(){
self.editedValue=myModel.model
}
}

我认为这与我想要的行为略有不同,但这是一个很好的提示。这是一些愚蠢的废话。不是你的解释,事实上这是唯一的方法。苹果,这让人感觉很不舒服。你在想什么?下划线和包装值以及状态包装。啊。@ChrisH你不知道我有多少次有同样的感觉。属性包装器,我已经介绍过了-它们非常酷和强大,随着新版本Swift的推出,您可以在越来越多的环境中使用它们,但是SwiftUI的某些部分有非常糟糕的方法。我需要显示存储在Firebase上的原始值,并允许用户在云上更改和更新它们。怎么可能呢?
import SwiftUI


class MyModel: ObservableObject {
@Published var model = "model1"
}

struct ContentView: View {

@ObservedObject var myModel = MyModel()
@State var editedValue = ""

var body: some View {
    NavigationView {
        VStack(alignment: .leading, spacing: 20) {
            Group{
                Text("Some label")
                TextField("Placeholder text", text: Binding<String>(
                    get: { self.editedValue },
                    set: {
                        self.editedValue = $0
                        self.myModel.model = self.editedValue
                })).onAppear(perform: loadData)
            }
            Divider()

            NavigationLink(destination: Text("the nex page")) {
                Text("Click Me To Display The next View")
            }

            // If the user starts to edit the textfield - follows a navigation link and comes back
            // he should be able to continue edit the field where he left of - the text field should
            // not have been reset to the original value.

            Button(action: {
                // Call some save function in the ViewModel
                self.myModel.model = self.editedValue
            },label: {
                Text("SAVE")
            })
        }
    }.navigationViewStyle(StackNavigationViewStyle())
}

func loadData() {
    self.editedValue = myModel.model
}

}