我正在尝试学习 SwiftUI 和 Combine 语法,并试图了解如何创建一个可重用的发布者来检查字符串是否为空。
我有一个带有 5 个 TextField 的 SwiftUI,它使用 @Binding 将它们连接到我的数据模型对象。
class DataWhatIsLoanPayment: ObservableObject {
// Input
@Published var pv = ""
@Published var iyr = ""
// a bunch more fields...
// Output
@Published var isvalidform = false
}
我想在填写完所有字段后启用“计算”按钮 (isEmpty == false)。
我正在关注 https://peterfriese.dev/swift-combine-love/ ,并且我能够通过创建一个 isValidPVPublisher
来让我的 SwiftUI 正确启用/禁用我的计算按钮。和一个 isValidIYRPublisher
并将它们组合成 isValidFormPublisher
,像这样:
private var isValidPVPublisher: AnyPublisher<Bool, Never> {
$pv
.debounce(for: 0.8, scheduler: RunLoop.main)
.removeDuplicates()
.map { input in
return input.isEmpty == false
}
.eraseToAnyPublisher()
}
private var isValidIYRPublisher: AnyPublisher<Bool, Never> {
$iyr
.debounce(for: 0.8, scheduler: RunLoop.main)
.removeDuplicates()
.map { input in
return input.isEmpty == false
}
.eraseToAnyPublisher()
}
private var isValidFormPublisher: AnyPublisher<Bool, Never> {
Publishers.CombineLatest(isValidPVPublisher, isValidIYRPublisher)
.map { pvIsValid, iyrIsValid in
return pvIsValid && iyrIsValid
}
.eraseToAnyPublisher()
}
init() {
isValidFormPublisher
.receive(on: RunLoop.main)
.assign(to: \.isValidForm, on: self)
.store(in: &cancellableSet)
}
但是,我将拥有 2 个以上的字段,并且我将在我的应用程序中拥有许多其他表单,我将在其中检查我的字段是否为空。并重复 .debounce(for: 0.8, scheduler: RunLoop.main).removeDuplicates().map { input in return input.isEmpty == false }.eraseToAnyPublisher()
一遍又一遍是个坏主意。
我想创建一个可重复使用的 NotEmptyPublisher
,或者类似的东西,它需要一个字段绑定(bind),比如我的 $pv
并设置链,如 isValidPVPublisher
中所示以上。所以我可以有类似的东西:
// Something like this, but I'm not sure of the syntax...
private var isValidPVPublisher = NotEmptyPublisher(field:$pv)
// instead of ...
private var isValidPVPublisher: AnyPublisher<Bool, Never> {
$pv
.debounce(for: 0.8, scheduler: RunLoop.main)
.removeDuplicates()
.map { input in
return input.isEmpty == false
}
.eraseToAnyPublisher()
}
但是我在解析很多我不熟悉的 Swift 语法时遇到了麻烦,而且我似乎无法弄清楚该怎么做,而且我在网上找到的每个示例都只是定义发布者内联链而不是可重复使用的方式。
如何创建可重复使用的发布器,这样我就不必重复这些做同样事情的内联发布器?
最佳答案
给你!
extension Publisher where Output == String {
func isStringInhabited() -> Publishers.Map<Self, Bool> {
map { !$0.isEmpty }
}
}
$0
是闭包第一个参数的简写,$1
表示第二个,依此类推。
!
是 Bool
反转运算符,前缀 !
是后缀 == false
的简写.
现在,关于您关于重用的问题,您不需要做那么困难的事情,您只需创建一个函数即可。
private func isValidTransform<P: Publisher>(input: P) -> some Publisher where P.Output == String {
input
.debounce(for: 0.8, scheduler: RunLoop.main)
.removeDuplicates()
.isStringInhabited()
}
P
是泛型,这意味着它可以是任何类型,只要该类型符合 Publisher
。 . where
子句允许我们进一步限制这种一致性,表示我们只能对 Publisher
进行操作这是他们的 Output
是String
. some Publisher
为我们提供了一个不透明的返回类型,使我们不必编写 Publisher
的类型签名多次变换后,可以改成AnyPublisher<Bool, Never>
并使用 .eraseToAnyPublisher()
如果你愿意,但我建议只在需要时使用该删除。
关于SwiftUI 和 Combine,如何创建可重用的发布者来检查字符串是否为空,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60983172/