Swift: Storage for extension properties
Let's get in some trouble
A little birdy told me the Swift team has stored extension properties on their roadmap, but obviously we must await some future build or even revision of the language depending on when their schedule allows for it.
In the mean time, we can use objc_setAssociatedObject
and objc_getAssociatedObject
to simulate it. Unfortunately this only works on classes marked @objc
or that are automatically representable in Objective-C. As soon as you involve generics or any other advanced features of either the class being extended or the value you want to store it all falls apart.
Using it might look like this:
let _mutablePropKey = malloc(4)
class Fancy {
var mutableProp : String? {
get {
let r : AnyObject! = objc_getAssociatedObject(self, _mutablePropKey)
return r as? String
}
set {
objc_setAssociatedObject(self, _mutablePropKey, newValue, UInt(OBJC_ASSOCIATION_RETAIN_NONATOMIC));
}
}
}
The cast of the storage policy to UInt
is a result of strangeness in the headers where someone declared the enumeration as signed integers, but the methods as taking unsigned integers.
In Objective-C we often pass a constant C string as the key, but in reality the runtime doesn't care. It just needs to be a pointer that never changes, so we allocate 4 bytes of memory. It won't be freed but again, not relevant for our purposes. I have yet to figure out how (and if) you can even declare a constant C string in Swift, since the semantics are quite different. (I hope to do a future blog post about using the various C interop types from Swift).
Not a great solution, but it's what we have access to for the moment. If there were a weak-keyed hash map equivalent in Swift, we could implement storage that way but as far as I know there is no such class yet.
This blog represents my own personal opinion and is not endorsed by my employer.