interestingly objc_setAssociatedObject / objc_getAssociatedObject work not just on NSObject based types (notwithstanding its name) but on any swift class. even more surprisingly it works on some swift value types like structs or ints or strings but doesn't work on enums.
is it a bug or a feature that it works on some value types? shall it's parameter be typed "AnyObject" or even "NSObject" (if it's not supposed to work on non-obj-c-objects)?
it's actually cool and useful that it works on any swift class object. but i have hard time understanding what it possibly means to associate some arbitrary object with the value types, be it a number 1 or 1.0 or a string "hey" or some custom struct type value.
import Foundation
class NSObjectBasedClass: NSObject {}
class OtherClass {}
class Struct {}
enum Enum { case one, two }
let nsObject1 = NSObjectBasedClass(), nsObject2 = NSObjectBasedClass()
let otherObject1 = OtherClass(), otherObject2 = OtherClass()
let struct1 = Struct(), struct2 = Struct()
let enum1: Enum = .one, enum2: Enum = .two
let int1 = 1, int2 = 2
let double1: Double = 1, double2: Double = 2
let string1 = "hey", string2 = "dude"
private var keyA: Int = 0
private var keyB: Int = 0
func test(_ object1: Any, _ value1A: String, _ value1B: String, _ object2: Any, _ value2A: String, _ value2B: String) {
assert(objc_getAssociatedObject(object1, &keyA) == nil)
assert(objc_getAssociatedObject(object1, &keyB) == nil)
assert(objc_getAssociatedObject(object2, &keyA) == nil)
assert(objc_getAssociatedObject(object2, &keyB) == nil)
objc_setAssociatedObject(object1, &keyA, value1A, .OBJC_ASSOCIATION_RETAIN)
objc_setAssociatedObject(object1, &keyB, value1B, .OBJC_ASSOCIATION_RETAIN)
objc_setAssociatedObject(object2, &keyA, value2A, .OBJC_ASSOCIATION_RETAIN)
objc_setAssociatedObject(object2, &keyB, value2B, .OBJC_ASSOCIATION_RETAIN)
assert(objc_getAssociatedObject(object1, &keyA) as? String == value1A)
assert(objc_getAssociatedObject(object1, &keyB) as? String == value1B)
assert(objc_getAssociatedObject(object2, &keyA) as? String == value2A)
assert(objc_getAssociatedObject(object2, &keyB) as? String == value2B)
}
func testAll() {
test(nsObject1, "ns-hello1", "ns-world1", nsObject2, "ns-hello2", "ns-world2")
test(otherObject1, "other-hello1", "other-world1", otherObject2, "other-hello2", "other-world2")
test(struct1, "struct-hello1", "struct-world1", struct2, "struct-hello2", "struct-world2")
test(int1, "int-hello1", "int-world1", int2, "int-hello2", "int-world2")
test(double1, "double-hello1", "double-world1", double2, "double-hello2", "double-world2")
test(string1, "string-hello1", "string-world1", string2, "string-hello2", "string-world2")
test(enum1, "enum-hello1", "enum-world1", enum2, "enum-hello2", "enum-world2") // fails
print("done")
}
testAll()