如何在 SubView SwiftUI 中使用 BaseView @State 属性
How to use BaseView @State property in SubView SwiftUI
我有一个类似这样的 BaseView,我想为我的所有子视图添加警报机制
struct BaseView<Content: View>: View {
@State var isAlertPresented = false
let content: Content
init(@ViewBuilder content: () -> Content) {
self.content = content()
}
var body : some View {
content.alert(isPresented: $isAlertPresented) {
Alert(title: Text("title"))
}
}
}
这是我的子视图。
struct SubView: View {
BaseView {
Text("")
}.onReceive(vm.publisher) { (output) in
// here I want to trigger BaseView isAlertPresented property
// BaseView.isAlertPresented = true
}
}
我可以做这样的事情吗?如果可以,我该怎么办?
如果视图包含BaseView,那么它肯定不是与其相关的子视图。由于 single-source-of-truth 违规,您不应该 access/manipulate 其他视图的内部状态。
相反,您必须在这种情况下使用 Binding,如下所示(使用 Xcode 11.7 测试)
struct BaseView<Content: View>: View {
@Binding var isAlertPresented: Bool
let content: Content
init(isAlertPresented: Binding<Bool>, @ViewBuilder content: () -> Content) {
self._isAlertPresented = isAlertPresented
self.content = content()
}
var body : some View {
content.alert(isPresented: $isAlertPresented) {
Alert(title: Text("title"))
}
}
}
struct SomeOtherView: View {
@State private var showAlert = false
var body: some View {
BaseView(isAlertPresented: $showAlert) {
Text("Test")
}
.onReceive(vm.publisher) { (output) in
// .onAppear { // used instead of above just for test
self.showAlert = true
}
}
}
我有一个类似这样的 BaseView,我想为我的所有子视图添加警报机制
struct BaseView<Content: View>: View {
@State var isAlertPresented = false
let content: Content
init(@ViewBuilder content: () -> Content) {
self.content = content()
}
var body : some View {
content.alert(isPresented: $isAlertPresented) {
Alert(title: Text("title"))
}
}
}
这是我的子视图。
struct SubView: View {
BaseView {
Text("")
}.onReceive(vm.publisher) { (output) in
// here I want to trigger BaseView isAlertPresented property
// BaseView.isAlertPresented = true
}
}
我可以做这样的事情吗?如果可以,我该怎么办?
如果视图包含BaseView,那么它肯定不是与其相关的子视图。由于 single-source-of-truth 违规,您不应该 access/manipulate 其他视图的内部状态。
相反,您必须在这种情况下使用 Binding,如下所示(使用 Xcode 11.7 测试)
struct BaseView<Content: View>: View {
@Binding var isAlertPresented: Bool
let content: Content
init(isAlertPresented: Binding<Bool>, @ViewBuilder content: () -> Content) {
self._isAlertPresented = isAlertPresented
self.content = content()
}
var body : some View {
content.alert(isPresented: $isAlertPresented) {
Alert(title: Text("title"))
}
}
}
struct SomeOtherView: View {
@State private var showAlert = false
var body: some View {
BaseView(isAlertPresented: $showAlert) {
Text("Test")
}
.onReceive(vm.publisher) { (output) in
// .onAppear { // used instead of above just for test
self.showAlert = true
}
}
}