I want an extension for two classes UITextField
and UITextView
and the code is identical, but I have trouble coming up with an extension that will work for them both.
I am using ReactiveCocoa and I currently have this
import UIKit
import ReactiveCocoa
import enum Result.NoError
typealias NoError = Result.NoError
// How to DRY up this code?
extension UITextField {
func textSignalProducer() -> SignalProducer<String, NoError> {
return self.rac_textSignal()
.toSignalProducer()
.map { $0 as! String }
.flatMapError { error in SignalProducer<String, NoError>(value: "") }
}
}
extension UITextView {
func textSignalProducer() -> SignalProducer<String, NoError> {
return self.rac_textSignal()
.toSignalProducer()
.map { $0 as! String }
.flatMapError { error in SignalProducer<String, NoError>(value: "") }
}
}
How would I write an extension that would work for both? I was trying to do something like
protocol TextSignalProducer {}
extension TextSignalProducer where Self: ???? {
// Same code as is duplicated in both current extensions...
}
but I have no idea how to specify Self
as either UITextField
or UITextView
. Something like where Self == UITextField || Self == UITextView
would probably make this possible.
Is there a nice way to accomplish what I want to try? Is this really necessary (I don't know the naming conventions for protocols/extensions)
import UIKit
import ReactiveCocoa
import enum Result.NoError
typealias NoError = Result.NoError
protocol TextSignal {
func rac_textSignal() -> RACSignal!
}
extension UITextField: TextSignal, TextSignalProducer {}
extension UITextView: TextSignal, TextSignalProducer {}
protocol TextSignalProducer {}
extension TextSignalProducer where Self: TextSignal {
func textSignalProducer() -> SignalProducer<String, NoError> {
return self.rac_textSignal()
.toSignalProducer()
.map { $0 as! String }
.flatMapError { error in SignalProducer<String, NoError>(value: "") }
}
}
I am using Swift 2.1, Xcode 7.2 and ReactiveCocoa 4.0.1
In Swift, you can even extend a protocol to provide implementations of its requirements or add additional functionality that conforming types can take advantage of. For more details, see Protocol Extensions. Extensions can add new functionality to a type, but they can't override existing functionality.
Naming a fileAll Swift files should use the . swift extension. The name of a file should make it clear what the contents are.
Yeah. Extensions cannot contain stored properties. If you need to add a property to a native component, you must create your own button inheriting from UIButton. In my opinion, creating your own button using a UIButton inheritance is the best way to resolve this situation.
Under the protocols section in the language guide, it is explained that: Protocol extensions can add implementations to conforming types but can't make a protocol extend or inherit from another protocol. Protocol inheritance is always specified in the protocol declaration itself.
You can cut down your proposed solution to a single dummy protocol:
protocol TextSignalProducer {
func rac_textSignal() -> RACSignal!
}
extension TextSignalProducer {
func textSignalProducer() -> SignalProducer<String, NoError> {
return self.rac_textSignal()
.toSignalProducer()
.map { $0 as! String }
.flatMapError { error in SignalProducer<String, NoError>(value: "") }
}
}
extension UITextField: TextSignalProducer {}
extension UITextView: TextSignalProducer {}
I don't think there's a more concise way than that, though. UITextField
and UITextView
's rac_textSignal()
implementations have nothing in common.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With