Я играю немного с Combine и SwiftUI для моего маленького любимого проекта, учусь на ходу.
Вот LoginModel
в его текущем состоянии:
public class LoginModel: ObservableObject {
@Published var domain: String = ""
@Published var email: String = ""
@Published var password: String = ""
@Published var isValid: Bool = false
public var didChange = PassthroughSubject<Void, Never>()
var credentialsValidPublisher: AnyPublisher<Bool, Never> {
Publishers.CombineLatest($email, $password)
.receive(on: RunLoop.main)
.map { (email, password) in
let emailValid = String.emailValid(emailString: email) // String extension function
let passwordValid = password.count > 5
return emailValid && passwordValid
}
.breakpointOnError()
.eraseToAnyPublisher()
}
init() {
// This works just fine
_ = credentialsValidPublisher.sink { isValid in
self.isValid = isValid
}
// However this does not work at all
_ = domain
.publisher
.receive(on: RunLoop.main)
.sink { value in
print(value)
}
}
}
Теперь, насколько я понимаю, @Published var foo: String
уже имеет Publisher
. И это должно быть в состоянии использовать это непосредственно, чтобы подписаться на его изменения.
Изменение переменной credentialsValidPublisher
на это тоже работает:
var credentialsValidPublisher: AnyPublisher<Bool, Never> {
Publishers.CombineLatest3($domain, $email, $password)
.receive(on: RunLoop.main)
.map { (domain, email, password) in
let domainValid = URL.isValidURL(urlString: domain)
let emailValid = String.emailValid(emailString: email)
let passwordValid = password.count > 5
return domainValid && emailValid && passwordValid
}
.breakpointOnError()
.eraseToAnyPublisher()
}
Но это не то, что я хочу. В моем случае мне нужен специальный Publisher
, чтобы сопоставить действительную строку URL-адреса с сетевым запросом, а затем пропинговать сервер, чтобы узнать, отвечает ли предоставленный сервер.
Также эта модельподключен к представлению SwiftUI с помощью набора текстовых полей SwiftUI. Буду очень признателен за любую помощь, чтобы указать мне правильное направление.