🐰
Objective-C黒魔術を駆使してあるオブジェクトに別のオブジェクトを追加するやつ
黒魔術とはObjective-C Runtime APIのobjc_setAssociatedObject
やobjc_getAssociatedObject
のことですが、久々にSwift(5)から使おうとしたらRawPointer周りの扱いが少し変わっていたので、備忘録として残しておきます。
import Foundation
import ObjectiveC
extension NSString {
private static let _associatedObjectKey = malloc(1)!
var customObject: Date? {
get {
value(forKey: Self._associatedObjectKey)
}
set {
setAssign(value: newValue, forKey: Self._associatedObjectKey)
}
}
}
extension NSObject {
func value<T>(forKey key: UnsafeRawPointer) -> T? {
objc_getAssociatedObject(self, key) as? T
}
func setAssign<T>(value: T?, forKey key: UnsafeRawPointer) {
objc_setAssociatedObject(self, key, value, .OBJC_ASSOCIATION_ASSIGN)
}
func setRetainNonAtomic<T>(value: T?, forKey key: UnsafeRawPointer) {
objc_setAssociatedObject(self, key, value, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
func setCopyNonAtomic<T>(value: T?, forKey key: UnsafeRawPointer) {
objc_setAssociatedObject(self, key, value, .OBJC_ASSOCIATION_COPY_NONATOMIC)
}
func setRetain<T>(value: T?, forKey key: UnsafeRawPointer) {
objc_setAssociatedObject(self, key, value, .OBJC_ASSOCIATION_RETAIN)
}
func setCopy<T>(value: T?, forKey key: UnsafeRawPointer) {
objc_setAssociatedObject(self, key, value, .OBJC_ASSOCIATION_COPY)
}
}
NSObjectの拡張として実装をまとめたのでNSObject継承ツリー配下のクラスにしか使えませんが、この辺りは適宜実装方法を変えれば良いと思います。
キーの定義方法はこのフォーラムの投稿を参考に、malloc(1)で生成する方法にしました。
private static let _associatedObjectKey = malloc(1)!
公式資料:
Discussion