将状态变量传递给父视图
Passing a state variable to parent view
我有以下代码:
struct BookView: View {
@State var title = ""
@State var author = ""
var body: some View {
TextField("Title", text: $title)
TextField("Author", text: $author)
}
}
struct MainView: View {
@State private var presentNewBook: Bool = false
var body: some View {
NavigationView {
// ... some button that toggles presentNewBook
}.sheet(isPresented: $presentNewBook) {
let view = BookView()
view.toolbar {
ToolbarItem(placement: principal) {
TextField("Title", text: view.$title)
}
}
}
}
}
这可以编译,但在运行时出现以下错误:
Accessing State's value outside of being installed on a View. This will result in a constant Binding of the initial value and will not update.
如何将状态变量传递给其他外部视图?我不能在 BookView
上使用 ObservableObject
,因为那需要我将它从 struct
更改为 class
一般来说,您的状态应该始终位于视图层次结构的更高层级。尝试从父级访问子状态是一种反模式。
一种选择是使用 @Binding
s 将值传递给子视图:
struct BookView: View {
@Binding var title : String
@Binding var author : String
var body: some View {
TextField("Title", text: $title)
TextField("Author", text: $author)
}
}
struct ContentView: View {
@State private var presentNewBook: Bool = false
@State private var title = ""
@State private var author = ""
var body: some View {
NavigationView {
VStack {
Text("Title: \(title)")
Text("Author: \(author)")
Button("Open") {
presentNewBook = true
}
}
}.sheet(isPresented: $presentNewBook) {
BookView(title: $title, author: $author)
}
}
}
另一种可能性是使用 ObservableObject
:
class BookState : ObservableObject {
@Published var title = ""
@Published var author = ""
}
struct BookView: View {
@ObservedObject var bookState : BookState
var body: some View {
TextField("Title", text: $bookState.title)
TextField("Author", text: $bookState.author)
}
}
struct ContentView: View {
@State private var presentNewBook: Bool = false
@StateObject private var bookState = BookState()
var body: some View {
NavigationView {
VStack {
Text("Title: \(bookState.title)")
Text("Author: \(bookState.author)")
Button("Open") {
presentNewBook = true
}
}
}.sheet(isPresented: $presentNewBook) {
BookView(bookState: bookState)
}
}
}
我稍微更改了您的示例视图,因为对我来说结构不清楚,但在父级别拥有状态的概念是重要元素。
您还可以在视图之间传递状态变量:
let view = BookView(title: "foobar")
view.toolbar {
ToolbarItem(placement: principal) {
TextField("Title", text: view.$title)
}
}
然后,在BookView
里面:
@State var title: String
init(title: String) {
_title = State(initialValue: title)
}
来源:
我有以下代码:
struct BookView: View {
@State var title = ""
@State var author = ""
var body: some View {
TextField("Title", text: $title)
TextField("Author", text: $author)
}
}
struct MainView: View {
@State private var presentNewBook: Bool = false
var body: some View {
NavigationView {
// ... some button that toggles presentNewBook
}.sheet(isPresented: $presentNewBook) {
let view = BookView()
view.toolbar {
ToolbarItem(placement: principal) {
TextField("Title", text: view.$title)
}
}
}
}
}
这可以编译,但在运行时出现以下错误:
Accessing State's value outside of being installed on a View. This will result in a constant Binding of the initial value and will not update.
如何将状态变量传递给其他外部视图?我不能在 BookView
上使用 ObservableObject
,因为那需要我将它从 struct
更改为 class
一般来说,您的状态应该始终位于视图层次结构的更高层级。尝试从父级访问子状态是一种反模式。
一种选择是使用 @Binding
s 将值传递给子视图:
struct BookView: View {
@Binding var title : String
@Binding var author : String
var body: some View {
TextField("Title", text: $title)
TextField("Author", text: $author)
}
}
struct ContentView: View {
@State private var presentNewBook: Bool = false
@State private var title = ""
@State private var author = ""
var body: some View {
NavigationView {
VStack {
Text("Title: \(title)")
Text("Author: \(author)")
Button("Open") {
presentNewBook = true
}
}
}.sheet(isPresented: $presentNewBook) {
BookView(title: $title, author: $author)
}
}
}
另一种可能性是使用 ObservableObject
:
class BookState : ObservableObject {
@Published var title = ""
@Published var author = ""
}
struct BookView: View {
@ObservedObject var bookState : BookState
var body: some View {
TextField("Title", text: $bookState.title)
TextField("Author", text: $bookState.author)
}
}
struct ContentView: View {
@State private var presentNewBook: Bool = false
@StateObject private var bookState = BookState()
var body: some View {
NavigationView {
VStack {
Text("Title: \(bookState.title)")
Text("Author: \(bookState.author)")
Button("Open") {
presentNewBook = true
}
}
}.sheet(isPresented: $presentNewBook) {
BookView(bookState: bookState)
}
}
}
我稍微更改了您的示例视图,因为对我来说结构不清楚,但在父级别拥有状态的概念是重要元素。
您还可以在视图之间传递状态变量:
let view = BookView(title: "foobar")
view.toolbar {
ToolbarItem(placement: principal) {
TextField("Title", text: view.$title)
}
}
然后,在BookView
里面:
@State var title: String
init(title: String) {
_title = State(initialValue: title)
}
来源: