所有人
我目前正在做一个SwiftUI项目,遇到了一个关于在视图模型中使用@Published的问题。我在视图模型中有一个带有变量'errorMessage'的登录视图。
我注意到,即使我从变量中删除了@Published,应用程序仍然可以正常运行。我已经使用@EnvironmentObject将视图模型注入SwiftUI环境中,但我没有显式地使用@Published标记变量或在视图模型中使用objectWillChange.send()。
我的问题是:在这种情况下,当需要观察属性并触发视图更新时,我是否仍然应该显式使用@Published?在这个上下文中,使用@Published和不使用它声明变量之间有什么区别?是否有任何我应该注意的最佳实践或潜在影响?
我将非常感谢任何与此主题相关的见解,建议或例子。提前感谢您的帮助!
import SwiftUI
struct LoginView: View {
@EnvironmentObject var authService: AuthService
@Environment(\.dismiss) private var dismiss
var body: some View {
ZStack {
Text(authService.errorMessage)
}
.onSubmit {
Task {
if await authService.signIn(){
dismiss()
}
}
}
}
}
import Foundation
import FirebaseAuth
enum AuthError: Error {
case emptyPassword
case emptyEmail
}
extension AuthError: LocalizedError {
var errorDescription: String? {
switch self {
case .emptyPassword:
return NSLocalizedString("Please enter a password to continue.", comment: "")
case .emptyEmail:
return NSLocalizedString("Please enter an email address to continue.", comment: "")
}
@MainActor
final class AuthService: ObservableObject {
@Published var email = ""
@Published var password = ""
private(set) var errorMessage = ""
private func validation() throws {
if email.isEmpty {
throw AuthError.emptyEmail
}
if password.isEmpty {
throw AuthError.emptyPassword
}
}
func signIn() async -> Bool {
do {
try validation()
let authResult = try await auth.signIn(withEmail: email, password: password)
return true
} catch {
errorMessage = error.localizedDescription
return false
}
}
}
我已经检查了Apple提供的文档中的相关概念(Published,EnvironmentObject,ObservableObject等)。
1条答案
按热度按时间eqqqjvef1#
以下是一些最佳实践:
1.使用
View
结构体和属性 Package 器而不是遗留的视图模型对象,这可以提高性能并防止一致性错误。View
结构中的let
是最简单的功能:当let
的值从上次初始化View
时发生更改时,将调用body
。使用合并框架中的ObservableObject
中的@Published
重新实现这个基本模式的效率很低。1.在使用async/await时,使用
.task
和.task(id: signIn)
而不是合并的ObservableObject
,这为您提供了取消和重新启动功能。1.为服务使用自定义的
EnvironmentKey
,就像AuthorizationController
的实现方式一样。