在Swift中是否可以在运行时向对象添加变量?

前端之家收集整理的这篇文章主要介绍了在Swift中是否可以在运行时向对象添加变量?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
具体来说,我想将一个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));
}

接下来,您将从程序的其余部分调用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)
}

最后,用于将特定视图控制器的视图标记为“调试”的示例.

// 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,因此您不需要进行任何显式转换.

猜你在找的Swift相关文章