Ссылка EnvironmentObject в ObservableObject - PullRequest
2 голосов
/ 01 февраля 2020

У меня есть LoginView, который показывает RegisterView, если пользователь не вошел в систему, и ContentView, если он вошел в систему:

struct LoginView: View {
    @EnvironmentObject var userManager: UserManager
    var body: some View {
        Group {
            if userManager.isRegistered {
                ContentView()
            } else {
                RegisterView()
            }
        }
    }
}

ContentView имеет три ObservedObject свойства, которые используют объединение для извлечения контента с сервера с API остальных.

struct ContentView: View {
    @EnvironmentObject var userManager: UserManager
    @ObservedObject var usersStore = UsersStore()
    @ObservedObject var rolesStore = RolesStore()
    @ObservedObject var elementsStore = ElementsStore()

    var body: some View {
        NavigationView {
            ZStack {
                Image("stell")
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .opacity(0.1)

                VStack(alignment: .leading, spacing: 5) {
                    NavigationLink(destination: UsersView(usersStore: usersStore) ) {
                        Text("Users")
                    }
                    NavigationLink(destination: RolesView(rolesStore: rolesStore)) {
                        Text("Roles")
                    }
                    NavigationLink(destination: ElementsView(elements: $elementsStore.elements)) {
                        Text("Elements")
                    }
                }.font(.title).padding(20)
            }.navigationBarTitle(Text("STELL"))
        }
    }
}

Проблема, с которой я столкнулся, заключается в том, что я хочу сослаться на userManager с любого из наблюдаемых объектов, например, когда остальные API возвращают 401 Unauthorized, когда сеанс срок действия токена истек Затем я хочу, чтобы ObservedObject установил флаг isRegistered в userManager на false, чтобы автоматически отображался RegisterView. Но как я могу это сделать? Я не могу установить ссылку на userManager ни в одном из инициализаторов свойств ObservedObject, потому что компилятор жалуется на то, что инициализаторы свойств запускаются до того, как self станет доступным.

1 Ответ

1 голос
/ 01 февраля 2020

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

Изменения в UsersStore

class UsersStore: ObservableObject {
    var manager: UserManager

    init(manager: UserManager) { // << inject UserManager via constructor
        self.manager = manager 
    }
    ...
}

Изменения в ContentView

struct ContentView: View {
    @EnvironmentObject var userManager: UserManager
    @ObservedObject var usersStore: UsersStore

    init(usersStore: UsersStore) {
        self.usersStore = usersStore // << inject UsersStore via contructor
    }

Изменения в использовании

struct LoginView: View {
    @EnvironmentObject var userManager: UserManager
    var body: some View {
        Group {
            if userManager.isRegistered {
                // userManager is valid here some UsersStore can be created
                ContentView(usersStore: UsersStore(manager: self.userManager))
...