Как использовать свойство BaseView @State в 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"))
        }
    }

}

А вот и мой SubView.

struct SubView: View {
    BaseView {
        Text("")
    }.onReceive(vm.publisher) { (output) in
        // here I want to trigger BaseView isAlertPresented property        
        // BaseView.isAlertPresented = true
    }
}

Могу я сделать что-то подобное? Если да, то как я могу?

1 ответ

Решение

Если представление содержит BaseView, это определенно не относящееся к нему подпредставление. И вы не должны получать доступ / манипулировать внутренним состоянием другого представления из-за нарушения единого источника истины.

Вместо этого вы должны использовать привязку в этом сценарии, как показано ниже (протестировано с 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
        }
    }
}
Другие вопросы по тегам