Last active
November 6, 2021 06:55
-
-
Save aufflick/83b74f3a3bc201b0b3e6 to your computer and use it in GitHub Desktop.
Helpers to assist using the ObjC runtime to associate both objects and structs in Swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Associated wrapper by WeZZard : https://wezzard.com/2015/10/09/associated-object-and-swift-struct/ | |
// Type safe helpers inspired by Tikitu de Jager : https://medium.com/@ttikitu/swift-extensions-can-add-stored-properties-92db66bce6cd#.mx6ekrw16 | |
public final class AssociatedStruct<T>: NSObject, NSCopying { | |
public typealias Type = T | |
public let value: Type | |
public init(_ value: Type) { self.value = value } | |
public func copyWithZone(zone: NSZone) -> AnyObject { | |
return self.dynamicType.init(value) | |
} | |
} | |
extension AssociatedStruct where T: NSCopying { | |
public func copyWithZone(zone: NSZone) -> AnyObject { | |
return self.dynamicType.init(value.copyWithZone(zone) as! Type) | |
} | |
} | |
extension NSObject { | |
func associatedOptionalObject<ValueType: AnyObject>( | |
key: UnsafePointer<String>, | |
initialiser: () -> ValueType?) -> ValueType? { | |
if let obj = objc_getAssociatedObject(self, key) as? ValueType { | |
return obj | |
} | |
let obj = initialiser() | |
self.associateOptionalObject(key, value:obj) | |
return obj | |
} | |
func associateOptionalObject<ValueType: AnyObject>(key: UnsafePointer<String>, value: ValueType?) { | |
objc_setAssociatedObject(self, key, value, .OBJC_ASSOCIATION_RETAIN) | |
} | |
func associatedObject<ValueType: AnyObject>( | |
key: UnsafePointer<String>, | |
initialiser: () -> ValueType) -> ValueType { | |
if let obj = objc_getAssociatedObject(self, key) as? ValueType { | |
return obj | |
} | |
let obj = initialiser() | |
self.associateOptionalObject(key, value:obj) | |
return obj | |
} | |
func associateObject<ValueType: AnyObject>(key: UnsafePointer<String>, value: ValueType) { | |
objc_setAssociatedObject(self, key, value, .OBJC_ASSOCIATION_RETAIN) | |
} | |
func associatedOptionalStruct<ValueType: Any>( | |
key: UnsafePointer<String>, | |
initialiser: () -> ValueType?) -> ValueType? { | |
if let obj = objc_getAssociatedObject(self, key) as? AssociatedStruct<ValueType?> { | |
return obj.value | |
} | |
let value = initialiser() | |
self.associateOptionalStruct(key, value:value) | |
return value | |
} | |
func associateOptionalStruct<ValueType: Any>(key: UnsafePointer<String>, value: ValueType?) { | |
objc_setAssociatedObject(self, key, AssociatedStruct<ValueType?>(value), .OBJC_ASSOCIATION_RETAIN) | |
} | |
func associatedStruct<ValueType: Any>( | |
key: UnsafePointer<String>, | |
initialiser: () -> ValueType) -> ValueType { | |
if let obj = objc_getAssociatedObject(self, key) as? AssociatedStruct<ValueType> { | |
return obj.value | |
} | |
let value = initialiser() | |
self.associateOptionalStruct(key, value:value) | |
return value | |
} | |
func associateStruct<ValueType: Any>(key: UnsafePointer<String>, value: ValueType) { | |
objc_setAssociatedObject(self, key, AssociatedStruct<ValueType>(value), .OBJC_ASSOCIATION_RETAIN) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let foo = NSNumber(int:5) | |
private var anOptionalColourKey = "anOptionalColourKey" | |
private var aColourKey = "aColourKey" | |
private var anOptionalStringKey = "anOptionalStringKey" | |
private var aStringKey = "aStringKey" | |
extension NSNumber { | |
var anOptionalColour : UIColor? { | |
get { | |
return self.associatedOptionalObject(&anOptionalColourKey) { return nil as UIColor? } | |
} | |
set { | |
self.associateOptionalObject(&anOptionalColourKey, value: newValue) | |
} | |
} | |
var aColour : UIColor { | |
get { | |
return self.associatedObject(&aColourKey) { | |
return UIColor.blackColor() | |
} | |
} | |
set { | |
self.associateObject(&aColourKey, value: newValue) | |
} | |
} | |
var anOptionalString : String? { | |
get { | |
return self.associatedOptionalStruct(&anOptionalStringKey) { | |
return nil as String? | |
} | |
} | |
set { | |
self.associateOptionalStruct(&anOptionalStringKey, value: newValue) | |
} | |
} | |
var aString : String { | |
get { | |
return self.associatedStruct(&aStringKey) { | |
return "" | |
} | |
} | |
set { | |
self.associateStruct(&aStringKey, value: newValue) | |
} | |
} | |
} | |
foo.anOptionalColour | |
foo.anOptionalColour = UIColor.greenColor() | |
foo.anOptionalColour | |
foo.anOptionalColour = nil | |
foo.anOptionalColour | |
foo.aColour | |
foo.aColour = UIColor.redColor() | |
foo.aColour | |
foo.anOptionalString | |
foo.anOptionalString = "42" | |
foo.anOptionalString | |
foo.anOptionalString = nil | |
foo.anOptionalString | |
foo.aString | |
foo.aString = "Hello World" | |
foo.aString | |
foo.aString = "Goodbye World" | |
foo.aString |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment