I've a little issue I cannot find an elegant way to use a closure with an associated type as a Void in a protocol.
Let's say I've the following protocol:
protocol MyProtocol {
associatedtype OutputDataType
associatedtype InputDataType
var isCompleted: ( (InputDataType) -> OutputDataType)? { get set }
}
Now I've a class that conforms to this protocol with Void type inside the closure like this:
class MyClass: MyProtocol {
var isCompleted: ( () -> Void )? // Error: Type 'MyClass' does not conform to protocol 'MyProtocol'
}
So I tried this:
var isCompleted: ( (Void) -> Void )? // warning: When calling this function in Swift 4 or later, you must pass a '()' tuple; did you mean for the input type to be '()'?
And ended up with this "weird" syntax:
var isCompleted: ( (()) -> Void )?
or this verbose one:
typealias InputDataType = Void
var isCompleted: ( (InputDataType) -> Void )?
But now when I want to assign this closure in an other class I need to explicitely use a "_" in parameter:
myClass.isCompleted = { _ in
// other code
}
Isn't possible to use something like this:
myClass.isCompleted = {
// other code
}
So do you know if it would be possible to get something more elegant like the example I quoted and expected?
Because you've declared isCompleted as necessary via the protocol, you will have to implement it in MyClass and unfortunately use the "weird" syntax.
However, to make using it nicer, you can add an extension to the protocol for when InputDataType == Void that gives a convenience to accessing isCompleted without having to explicitly pass Void... Something like this:
extension MyProtocol where InputDataType == Void {
var isCompleted: (() -> OutputDataType)? {
get {
guard let isCompleted = self.isCompleted else { return nil }
return { return isCompleted(()) }
}
set {
if let newValue = newValue {
self.isCompleted = { _ in return newValue() }
} else {
self.isCompleted = nil
}
}
}
}
Then you can use the method on your class through the convenience, which gives you the last code example you were looking for:
var myClass = MyClass()
myClass.isCompleted = {
print("Hello World!")
}
myClass.isCompleted?()
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