Соблюдайте environmentObject в URLSession - PullRequest
0 голосов
/ 10 марта 2020

Я попытался обновить environmentObject в моем URLSession.

Мой вид входа в систему.

struct LoginView: View {
    @EnvironmentObject var env: Env

    ...

    var body: some View {
        Group {
            if env.isLogin {    // 2    but the env.isLogin is still false
                UserView()
            } else {
                VStack {
                    ...
                    Button(action: {
                        self.login(name: self.name, pass: self.pass)
                    }) {
                        Text("Login")
                    }

                    Text("isLogin: \(String(env.isLogin))")
                }
                .padding()
            }
        }
    }

    func login(name: String, pass: String) {
        ...

        URLSession.shared.dataTask(with: request) { data, response, error in
            if let data = data {
                if let decodedResponse = try? JSONDecoder().decode(Response.self, from: data) {
                    DispatchQueue.main.async {
                        ...
                        if ... {
                            self.env.isLogin = true
                            print(self.system.isLogin)    // 1   output true
                        }
                    }

                    return
                }
            }

            print("Fetch failed: \(error?.localizedDescription ?? "Unknown error")")
        }.resume()
    }
}

Мой стартовый вид.

class Env: ObservableObject {
    @Published var isLogin: Bool = false
}

struct ContentView: View {
    let env = Env()

    var body: some View {
        VStack {
            if env.isLogin {
                UserView()
            } else {
                LoginView()
            }
        }
        .environmentObject(env)
    }
}

Я могу убедиться, что уже обновил isLogin в true на месте 1, но связанное свойство env не отвечает с ним на месте 2.

Разрешение

Я создаю другое представление LoginToOtherView и замените его ContentView.

struct LoginToOtherView: View {
    @EnvironmentObject var env: Env

    var body: some View {
        Group {
            if env.isLogin {
                UserView()
            }
        }
    }
}

// and in place 2.
if env.isLogin {
    LoginToOtherView()
}

1 Ответ

1 голос
/ 10 марта 2020

Как только я упростил предоставленный моментальный снимок кода для тестируемого модуля, все работает нормально. Протестировано с Xcode 11.4beta2.

Полный тестируемый модуль:

class Env: ObservableObject {
    @Published var isLogin: Bool = false
}

struct LoginViewEnv: View {
    @EnvironmentObject var env: Env
    var body: some View {
        Group {
            if env.isLogin {
                Text("UserView") // << shown in 2 secs after button click
            } else {
                VStack {
                    Button(action: {
                        self.login(name: "name", pass: "pass")
                    }) {
                        Text("Login")
                    }

                    Text("isLogin: \(String(env.isLogin))")
                }
                .padding()
            }
        }
    }

    func login(name: String, pass: String) {
        // simulate async login
        DispatchQueue.global(qos: .background).asyncAfter(deadline: .now( ) + 2) {
            DispatchQueue.main.async {
                self.env.isLogin = true
                print(self.env.isLogin)
            }
        }
    }
}

struct TestVStackEnv: View {
    let env = Env()

    var body: some View {
        VStack {
            if env.isLogin {
                Text("UserView")
            } else {
                LoginViewEnv()
            }
        }
        .environmentObject(env)
    }
}

struct TestVStackEnv_Previews: PreviewProvider {
    static var previews: some View {
        TestVStackEnv()
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...