I am having a username textField in swiftUI. I am trying to validate input with the help of publishers.
Here is my code:
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)
}
}
The View Model
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
extension String {
func isValidUserName() -> Bool {
let usernameRegex = "^[a-zA-Z0-9_-]*$"
let usernamepred = NSPredicate(format:"SELF MATCHES %@", usernameRegex)
return usernamepred.evaluate(with: self)
}
}
In the usernamevalidated in the init() block in the ViewModel I am assigning the error to userTextError property which should be reflected in the textview. This should happens if a special character such as @ or % .. etc are entered. What happens is that sometimes the error appears in red and other no even though I try to print value of string after map operator i can see the string in printing fine. It is just the error is sometimes reflected in the view and sometimes not. Am I missing something or doing something fundamentally wrong