gpt4 book ai didi

SwiftUI/Combine - 订阅单个发布者的最新值

转载 作者:行者123 更新时间:2023-11-30 10:33:05 27 4
gpt4 key购买 nike

我正在为我的一个小宠物项目尝试一些 Joint 和 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 字符串映射到网络请求,然后 ping 手边的服务器以查看提供的服务器是否正在响应。

此外,该模型还连接到带有一堆 SwiftUI TextField 的 SwiftUI View 。任何帮助我指明正确方向的帮助都将受到高度赞赏。

最佳答案

所以我想出了办法。在 LoginModel下面var credentialsValidPublisher: AnyPublisher<Bool, Never>我补充道:

var domainValidPublisher: AnyPublisher<Bool, Never> {
$domain
.debounce(for: 0.5, scheduler: DispatchQueue.main)
.removeDuplicates()
.map { domain in
URL.isValidURL(urlString: domain)
}
.eraseToAnyPublisher()
}

然后我就可以订阅init 。我还添加了AnyCancellable我们称之为 .cancel() 的属性上deinit 。更新后的模型如下所示:

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>()
private var credentialsValidPublisherCancellable: AnyCancellable!
private var domainValidCancellable: AnyCancellable!

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()
}
var domainValidPublisher: AnyPublisher<Bool, Never> {
$domain
.debounce(for: 0.5, scheduler: DispatchQueue.main)
.removeDuplicates()
.map { domain in
URL.isValidURL(urlString: domain)
}
.eraseToAnyPublisher()
}

init() {
credentialsValidPublisherCancellable = credentialsValidPublisher.sink { isValid in
self.isValid = isValid
}

domainValidCancellable = domainValidPublisher.sink { isValid in
print("isValid: \(isValid)")
}
}

deinit {
credentialsValidPublisherCancellable.cancel()
domainValidCancellable.cancel()
}
}

关于SwiftUI/Combine - 订阅单个发布者的最新值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58675933/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com