I'm trying to add tap gesture support to UIView via an extension. This is pretty straight forward using Objective-C, but I'm getting the following error when trying to set the void return block on the runtime property.
error: type '() -> Void' does not conform to protocol 'AnyObject'
Here is the computed property:
var tapAction: (() -> Void)? {
get {
objc_getAssociatedObject(self, &AssociatedKeys.SNGLSActionHandlerTapBlockKey)
}
set {
objc_setAssociatedObject(
self,
&AssociatedKeys.SNGLSActionHandlerTapBlockKey,
newValue,
UInt(OBJC_ASSOCIATION_COPY_NONATOMIC)
)
}
}
I've tried to set the tapAction as a typealias
, but still receive the same error.
The problem is closures are not objects that conform to AnyObject
so you can't store them like that from Swift.
You could look into wrapping the closures in a class with a single property. Something like:
class ClosureWrapper {
var closure: (() -> Void)?
init(_ closure: (() -> Void)?) {
self.closure = closure
}
}
var tapAction: (() -> Void)? {
get {
if let cl = objc_getAssociatedObject(self, "key") as? ClosureWrapper {
return cl.closure
}
return nil
}
set {
objc_setAssociatedObject(
self,
"key",
ClosureWrapper(newValue),
UInt(OBJC_ASSOCIATION_RETAIN_NONATOMIC)
)
}
}
It's a little ugly and could use a nice typealias
but it's one way to do it.
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