为什么即使发布服务器发出值,我的视图也不会在SwiftUI中呈现



我在swiftUI中有一个用户名textField。我正试图在出版商的帮助下验证输入。

这是我的代码:

View
struct UserView: View {
@StateObject private var userViewModel = UserViewModel()
init(){
UITextField.appearance().semanticContentAttribute = .forceRightToLeft
UITextField.appearance().keyboardAppearance = .dark

}
var body: some View {
SecureField("", text: $userViewModel.passwordText)
Text(userViewModel.passwordError).foregroundColor(.red)
.frame(width: 264, alignment: .trailing)
}
}

视图模型

ViewModel
final class UserViewModel: ObservableObject {
private var cancellables = Set<AnyCancellable>()
@Published var userText: String = ""
@Published var userTextError = ""
private var usernamevalidation: AnyPublisher<(username:String, isValid: Bool), Never> {
return $userText
.dropFirst()
.map{(username:$0, isValid: !$0.isEmpty)}
.eraseToAnyPublisher()
}
private var usernamevalidated: AnyPublisher<Bool,Never> {
return usernamevalidation
.filter{$0.isValid}
.map{$0.username.isValidUserName()}
.eraseToAnyPublisher()
}

init(){
usernamevalidation.receive(on: RunLoop.main)
.map{$0.isValid ? "": "Emptyusername "}
.assign(to: .userTextError, on: self)
.store(in: &cancellables)
usernamevalidated.receive(on: RunLoop.main)
.map{$0 ? "" : "wrong username "}
.assign(to: .userTextError, on: self)
.store(in: &cancellables)
}
}

扩展

extension String {
func isValidUserName() -> Bool {
let usernameRegex = "^[a-zA-Z0-9_-]*$"
let usernamepred = NSPredicate(format:"SELF MATCHES %@", usernameRegex)
return usernamepred.evaluate(with: self)
}
}

在ViewModel的init((块中验证的用户名中,我将错误分配给userTextError属性,该属性应反映在文本视图中。如果出现特殊字符,如@或%。。等等。发生的情况是,有时错误显示为红色,而其他错误显示为否,即使我试图在映射运算符之后打印字符串的值,我也可以在打印中看到字符串。只是错误有时会反映在视图中,有时不会。我是不是错过了什么或做了一些根本错误的事情

问题是usernamevalidationusernamevalidated都是计算属性。存储它们可以解决问题,但您也可以通过观察对userText的更改、验证它们并分配给userTextError来简化视图模型,如下所示:

final class UserViewModel: ObservableObject {

@Published var userText: String = ""
@Published private(set) var userTextError = ""

init() {
$userText
.dropFirst()
.map { username in
guard !username.isEmpty else {
return "Username is empty"
}
guard username.isValidUserName() else {
return "Username is invalid"
}
return ""
}
.receive(on: RunLoop.main)
.assign(to: &$userTextError)
} 
}

还值得一提的是,用.assign(to: &$userTextError)替换.assign(to: .userTextError, on: self)可以消除内存泄漏,这意味着您确实需要将其存储在cancellables中。

不要为发布者使用可计算的存储属性(以保持它们的活力(,如

private lazy var usernamevalidation: AnyPublisher<(username:String, isValid: Bool), Never> = {
return $userText
.dropFirst()
.map{(username:$0, isValid: !$0.isEmpty)}
.eraseToAnyPublisher()
}()

上一个答案(如果需要,请参阅编辑(是不正确的,因为Emptyusername错误将被覆盖,这不是我们需要的(我的错误(。

事实证明,问题是iOS 14更新了用户界面!这个修复程序,我以前不得不在TextField上使用过,看起来有点不寻常,但它确实起到了作用。

只需在视图主体中添加以下内容:

var body: some View {
let _ = userViewModel.userTextError
/* Rest of view as before */
}

相关内容

  • 没有找到相关文章

最新更新