具体来说,我想将一个enum类型的变量添加到UIView的实例中,而不进行子类化或创建扩展.
谢谢.
关于objc_setAssociatedObject()的前一个答案是正确的方法,但我认为Apple的API尚未经过审查,因为我很难以我认为应该使用它们的方式使用它们. (我不应该用不安全的指针等等.)这是我现在使用的解决方案.
首先,您需要一些Objective-C粘合剂(遵循Apple的说明,在同一个项目中混合使用Objective-C和Swift:
// RuntimeGlue.h // Should be included from your bridging header. @import Foundation; void setAssociatedObject_glue(NSObject *object,const NSString *key,NSObject *value); NSObject *getAssociatedObject_glue(NSObject *object,const NSString* key); // RuntimeGlue.m #import "RuntimeGlue.h" #import <objc/runtime.h> void setAssociatedObject_glue(NSObject *object,NSObject *value) { objc_setAssociatedObject(object,(__bridge const void *)(key),value,OBJC_ASSOCIATION_RETAIN_NONATOMIC); } NSObject *getAssociatedObject_glue(NSObject *object,const NSString* key) { return objc_getAssociatedObject(object,(__bridge const void *)(key)); }
// Runtime.swift import Foundation public func setAssociatedObject(#object: NSObject,#key: NSString,#value: NSObject?) { setAssociatedObject_glue(object,key,value) } public func getAssociatedObject(#object: NSObject,#key: NSString) -> NSObject? { return getAssociatedObject_glue(object,key) }
最后,用于将特定视图控制器的视图标记为“调试”的示例.
// MyViewController.swift import UIKit let debugKey: NSString = "DebugKey" class MyViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() setAssociatedObject(object: self.view,key: debugKey,value: "debugging") } override func viewWillAppear(animated: Bool) { super.viewWillAppear(animated) let val = getAssociatedObject(object: self.view,key: debugKey) println("val:\(val)") } }
此方法允许您将nil for value传递给setter以清除键的值,并从getter返回一个可选项.另请注意,关键参数在两种情况下必须相同(k1 === k2),而不仅仅等效(k1 == k2).
另请注意,这只允许您标记NSObject或其子类的实例 – 它不适用于Swift本机类.该值也必须是NSObject子类,但字符串和数字文字都自动桥接到Objective-C,因此您不需要进行任何显式转换.