eimantas
(Eimantas)
1
How can I collapse a publisher's type that was built using few operators? Say I have a UITextField and want a publisher that signals whether that text field has value of at least N characters in length. I could build that publisher like this:
let textFieldValuePublisher = textField.publisher(for: \.text)
let valueLengthPublisher = textFieldValuePublisher.map { $0?.lengthInBytes(using: .utf8) ?? 0 }
let minimumLengthPredicatePublisher = valueLengthPublisher.map { $0 > N }
The type of minimumLengthPredicatePublisher has a lot of nested types in generics. Is there a way to get a Publisher<Bool, Never> from it?
mayoff
(Rob Mayoff)
2
Use the eraseToAnyPublisher() at the end to get an AnyPublisher<Bool, Never>.
However, I don't know if UITextField's text property is KVO-compliant. It's not documented as such.
1 Like
eimantas
(Eimantas)
3
I tried using reaseToAnyPublisher(), however when inspecting the resulting publisher Xcode shows something along the lines of AnyPublisher<(loads of nexted generics).Output, Never>. :(
mayoff
(Rob Mayoff)
4
Yes but it's the same as AnyPublisher<Bool, Never>.
1 Like
eimantas
(Eimantas)
5
I wonder where I am mistaken when I try to subscribe an Subscriber.Assign<UIButton, Bool>? I get the compilation error here:
let boolSubscriber = Subscribers.Assign(object: button, keyPath: \.isEnabled)
publisher.subscribe(boolSubscriber) // No exact matches in call to instance method 'subscribe'
mayoff
(Rob Mayoff)
6
Without seeing all the relevant code, I can't say what you've done wrong. This compiles:
import UIKit
import Combine
let textField = UITextField()
let button = UIButton()
let boolPublisher: AnyPublisher<Bool, Never> =
textField.publisher(for: \.text)
.map { ($0 ?? "").count > 5 }
.eraseToAnyPublisher()
let assigner = Subscribers.Assign(object: button, keyPath: \.isEnabled)
boolPublisher.subscribe(assigner)
But creating an Assign explicitly is unusual. You probably want something more like this:
import UIKit
import Combine
class MyController: UIViewController {
let textField = UITextField()
let button = UIButton()
private var tickets: [AnyCancellable] = []
override func viewDidLoad() {
super.viewDidLoad()
textField.publisher(for: \.text)
.map { ($0 ?? "").count > 5 }
.assign(to: \.isEnabled, on: button)
.store(in: &tickets)
}
}
But again I must emphasize that the text property on UITextField is not documented to support Key-Value Observing. Therefore textField.publisher(for: \.text) might not work reliably.
1 Like
eimantas
(Eimantas)
7
The missing piece was explicit type declaration for the final publisher. Thanks a heap!