I am trying to get some functionality through default implementations that I can't nail. Consider the following code, which is a simplification of what I'm trying to do, but captures the problem as simply as possible.
//protocol definition
protocol Configurable {
associatedtype Data
func configure(data: Data)
static func generateObject() -> Self
}
//default implementation for any UIView
extension Configurable where Self: UIView {
static func generateObject() -> Self {
return Self()
}
}
//implement protocol for UILabels
extension UILabel: Configurable {
typealias Data = Int
func configure(data: Int) {
label.text = "\(data)"
}
}
//use the protocol
let label = UILabel.generateObject()
label.configure(data: 5)
print(label.text!) //5
I have a protocol, a default implementation for some methods for UIView, and the a specific implementation for UILabel.
My issue is the last part... the actual use of all this functionality
let label = UILabel.generateObject()
label.configure(data: 5)
print(label.text!) //5
I find myself doing generateObject() followed by configure(data: <something>) constantly. So I tried doing the following:
Add static func generateObjectAndConfigure(data: Data) -> Self to the protocol. The issue comes when I try to make a default implementation for UIView for this method. I get the following error
Method 'generateObjectAndConfigure(data:)' in non-final class 'UILabel' cannot be implemented in a protocol extension because it returnsSelfand has associated type requirements
Basically, I can't have a method that returns Self and uses an associated type. It feels really nasty for me to always call the two methods in a row. I want to only declare configure(Data) for each class and get generateObjectAndConfigure(Data) for free.
Any suggestions?
UICollectionView. Also usingSelf()kinda abuses the fact that the no-param initializer is still availableUIView's, even if for many of subclasses it doesn't make sense to call it. Better keep those two separated: instantiation and configuration. - Cristik