在iOS 17中处理数据流并在TextField内使用观察变量

huangapple go评论77阅读模式
英文:

Handling data flow in iOS 17 and using observed variables inside a TextField

问题

我正在尝试迁移到 iOS 17,并使用 @Observable

我有一个应用程序的全局视图模型,在其中我调用一个包含我需要的所有值的 Exam 模型。

根据 Apple 的指南,我使用我的视图模型如下:

import Foundation
import Observation

struct Exam: {
    var title: String = ""
}

@Observable
final class Global {
    var exam = Exam()
}
import SwiftUI

@main
struct TestApp: App {
    @State private var model = Global()
    var body: some Scene {
        WindowGroup {
            InfoView()
                .environment(model)
        }
    }
}

接下来,我在 InfoView 中像这样使用我的模型:

struct InfoView: View {
   // @Bindable private var model = Global()
    @Environment(Global.self) private var model

    var body: some View {
         VStack {
             TitledField(text: $model.exam.title, isMandatory: true, descriptionLabel: "", placeholder: "")
             .submitLabel(.continue)
          }
     }
}

正如你所看到的,在第一个自定义文本字段中,我使用了 $model.exam.title,但似乎不起作用,因为它给我报错:

无法在范围内找到 '$model'

所以我尝试了 @Bindable,但用户在文本字段中插入的值未被读取,始终返回空字符串。我哪里出错了?有人已经开始使用 iOS 17 了吗?

英文:

I'm trying to migrate to iOS 17 using @Observable.

I have a global view model of the app where I call an Exam model with all the values ​​I need inside.

According to Apple guidelines I'm using my view model like this

import Foundation
import Observation

struct Exam: {
    var title: String = ""
}


@Observable
final class Global {
    var exam = Exam()
}

import SwiftUI

@main
struct TestApp: App {
    @State private var model = Global()
    var body: some Scene {
        WindowGroup {
            InfoView()
                .environment(model)
                
        }
    }
}

Next I use my model within the InfoView like this

struct InfoView: View {
   // @Bindable private var model = Global()
    @Environment(Global.self) private var model

    var body: some View {
         VStack {
             TitledField(text: $model.exam.title, isMandatory: true, descriptionLabel: "", placeholder: "")
             .submitLabel(.continue)

          }
     }
}

As you can see in the first custom textField I use $model.exam.title but it doesn't seem to work because it gives me this error

>Cannot find '$model' in scope

So I tried with @Bindable but the value that the user inserts in the textField is not read and always returns an empty string where am I going wrong? Has anyone started working on iOS 17?

答案1

得分: 1

以下是翻译好的部分:

以下示例代码中使用@Bindable在iOS17上对我有用。
当在TextField中更改$model.exam.title时,UI会刷新并显示更改后的值。

import SwiftUI
import Observation

@main
struct TestApp: App {
    @State private var model = Global()
    var body: some Scene {
        WindowGroup {
            InfoView(model: model) // <-- 这里
        }
    }
}

struct InfoView: View {
    @Bindable var model: Global // <-- 这里
    var body: some View {
        VStack {
            TextField("", text: $model.exam.title).border(.red)
                .submitLabel(.continue)
            
            Text(model.exam.title) // <-- 用于测试
        }
    }
}

struct Exam {
    var title: String = "exam-title"
}

@Observable
final class Global {
    var exam = Exam()
}

希望这对你有所帮助。如果有其他翻译需求,请随时告诉我。

英文:

The following example code with @Bindable works for me on iOS17.
When the $model.exam.title is changed in the TextField,
the UI is refreshed and displays the changed value.

import SwiftUI
import Observation

 @main
 struct TestApp: App {
     @State private var model = Global()
      var body: some Scene {
          WindowGroup {
              InfoView(model: model) // <-- here
          }
      }
 }
 
 struct InfoView: View {
     @Bindable var model: Global // <-- here
     var body: some View {
          VStack {
              TextField("", text: $model.exam.title).border(.red)
                  .submitLabel(.continue)
              
              Text(model.exam.title) // <-- for testing
           }
      }
 }

struct Exam {
    var title: String = "exam-title"
}

@Observable
final class Global {
    var exam = Exam()
}

答案2

得分: 0

如果您正在使用@Environment,您需要将其转换为@Bindable,例如:

@Bindable var exam = model.exam
TitledField(text: $exam.title, isMandatory: true, descriptionLabel: "", placeholder: "")

@Bindable不是DynamicProperty,因此它可以像任何其他结构体一样在body中使用。

英文:

If you are using @Environment you need to convert to @Bindable, e.g.

@Bindable var exam = model.exam
TitledField(text: $exam.title, isMandatory: true, descriptionLabel: "", placeholder: "") 

@Bindable isn't a DynamicProperty so it can be used inside body like any other struct.

答案3

得分: 0

一个很好的起点是:

https://developer.apple.com/documentation/swiftui/migrating-from-the-observable-object-protocol-to-the-observable-macro

我还添加了一个包含“add”的示例项目:

https://github.com/ingconti/iOS17_ObservableLibraryView

英文:

A good starting point is:

https://developer.apple.com/documentation/swiftui/migrating-from-the-observable-object-protocol-to-the-observable-macro

I added a sample project with "add" too:

https://github.com/ingconti/iOS17_ObservableLibraryView

huangapple
  • 本文由 发表于 2023年6月22日 02:29:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/76526171.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定