In relation to my last question (over here: Swift where condition to check if a property is implemented ) where I thought I was very clever by creating a protocol extension to provide a default value for nil or empty strings by using the following code, I now have another question. But first, heres the code:
protocol Emptyable {
var isEmpty: Bool { get }
}
extension Optional where Wrapped: Emptyable {
func orWhenNilOrEmpty<T: Emptyable>(_ defaultValue: T) -> T {
switch(self) {
case .none:
return defaultValue
case .some(let value) where value.isEmpty:
return defaultValue
case .some(let value):
return value as! T
}
}
}
extension String: Emptyable {}
As you see i can now provide default values for optionals implementing the Emptyable protocol I defined. I did this to save the ever repeating code of this style (more about why I do this in the blog post mentioned in the other question):
if let unwrapped = optional, !unwrapped.isEmpty {
myLabel.text = unwrapped
} else {
myLabel.text = "Some Default Text"
}
Now for the purpose of learning and becoming a better developer, I thought it could be fun to create a new operator to call the orWhenNilOrEmpty function for me like so:
let optionalString: String? = nil
let actualString: String = some ??? "Hello World"
So I tried this:
infix operator ???: DefaultPrecedence
extension Optional where Wrapped: Emptyable {
static func ???<T>(left: T?, right: T) -> T {
return left.orWhenNilAndEmpty(right)
}
}
But I get this error and I don't really understand why. I hope you can clarify the issue and explain what I'm doing wrong:
generic parameter 'Wrapped' could not be inferred
Turns out the problem was trying to use a generic T
in the function declaration. Also DefaultPrecedence
wasn't the best choice. This is how I now solved it and how it works:
protocol Emptyable { var isEmpty: Bool { get } }
infix operator ???: NilCoalescingPrecedence
extension Optional where Wrapped: Emptyable {
func orWhenNilOrEmpty(_ defaultValue: Wrapped) -> Wrapped {
switch(self) {
case .none:
return defaultValue
case .some(let value) where value.isEmpty:
return defaultValue
case .some(let value):
return value
}
}
static func ???(left: Wrapped?, right: Wrapped) -> Wrapped {
return left.orWhenNilOrEmpty(right)
}
}
Now all I have to do is implement Emptyable
where ever I want and then I can use ???
to get a not empty value from any optional:
extension String: Emptyable {}
let notEmptyString = nilOrEmptyOptionalString ??? "Meaningful default value"
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.