具体来说,我想将一个enum类型的变量添加到UIView的实例中,而不进行子类化或创建扩展。
感谢。
答案 0 :(得分:9)
以下是源自jckarter's answer的简单但完整的示例。
它显示了如何向现有类添加新属性。它通过在扩展块中定义计算属性来实现。 computed属性存储为关联对象:
import ObjectiveC
// Declare a global var to produce a unique address as the assoc object handle
var AssociatedObjectHandle: UInt8 = 0
extension MyClass {
var stringProperty:String {
get {
return objc_getAssociatedObject(self, &AssociatedObjectHandle) as String
}
set {
objc_setAssociatedObject(self, &AssociatedObjectHandle, newValue, objc_AssociationPolicy(OBJC_ASSOCIATION_RETAIN_NONATOMIC))
}
}
}
答案 1 :(得分:4)
关于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, const NSString *key, 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));
}
接下来,您将从程序的其余部分调用Swift方法:
// 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)
}
最后,用于将特定视图控制器的视图标记为&#34; debugging&#34;。
的示例// 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
value
传递给setter,以清除键的值,并从getter返回一个可选项。另请注意,key
参数在两种情况下必须相同(k1 === k2),而不仅仅等效(k1 == k2)。
另请注意,这只允许您标记NSObject或其子类的实例 - 它不适用于Swift本机类。 value
也必须是NSObject子类,但字符串和数字文字都自动桥接到Objective-C,因此您不需要进行任何显式转换。
答案 2 :(得分:1)
您可以使用Objective-C运行时的objc_setAssociatedObject()
函数将对象(您可以将该枚举包装到对象中)附加到另一个对象上,并objc_getAssociatedObject()
来检索它。
答案 3 :(得分:0)
objc_AssociationPolicy.OBJC_ASSOCIATION_COPY_NONATOMIC