Обработка потока данных в iOS 17 и использование наблюдаемых переменных внутри TextField

Я пытаюсь перейти на iOS 17, используя@Observable.

У меня есть глобальная модель представления приложения, в которой я вызываю модель экзамена со всеми необходимыми мне значениями внутри.

Согласно рекомендациям 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но значение, которое пользователь вставляет в textField, не читается и всегда возвращает пустую строку, где я ошибаюсь? Кто-нибудь начал работать на iOS 17?

3 ответа

Следующий пример кода с@Bindableу меня работает на iOS17. Когда$model.exam.titleизменяется вTextField, пользовательский интерфейс обновляется и отображает измененное значение.

      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()
}

Если вы используете@Environmentвам нужно преобразовать, например, в

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

@Bindableэто неDynamicPropertyтак что его можно использовать внутриbodyкак и любая другая структура.

Хорошей отправной точкой является:

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

Я также добавил пример проекта с помощью «добавить»:

https://github.com/ingconti/iOS17_ObservableLibraryView

Другие вопросы по тегам