I'm struggling to learn SwiftUI and Combine syntax and am trying to understand how to create a reusable publisher that will check if a String is empty.
I've got a SwiftUI with 5 TextFields which using @Binding to connect them to my data model object.
class DataWhatIsLoanPayment: ObservableObject {
// Input
@Published var pv = ""
@Published var iyr = ""
// a bunch more fields...
// Output
@Published var isvalidform = false
}
I want to enable the Calculate button once all of the fields are filled in (isEmpty == false).
I'm following along with https://peterfriese.dev/swift-combine-love/, and I was able to get my SwiftUI to properly enable/disable my Calculate button by creating an isValidPVPublisher and an isValidIYRPublisher and combing them in an isValidFormPublisher, like so:
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)
}
However, I'm going to have a lot more than 2 fields, and I'm going to have a lot of other forms in my app in which I will want to check if my fields are empty. And repeating .debounce(for: 0.8, scheduler: RunLoop.main).removeDuplicates().map { input in return input.isEmpty == false }.eraseToAnyPublisher() over and over again is a bad idea.
I want to create a reusable NotEmptyPublisher, or something like that, which takes a field binding, like my $pv and sets up the chain as show in the isValidPVPublisher above. So I can have something like:
// 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()
}
But I'm having a great deal of trouble parsing a lot of Swift syntax that I'm not familiar with and I can't seem to figure out how to do it, and every example I find on the web is just defining the publisher chain inline instead of in a reusable fashion.
Any help? How can I create a reusable publisher so that I don't have to repeat these inline publishers which all do the same thing?