在Swift中,对于AnyObject,我如何setValue()然后调用valueForKey()

时间:2014-10-31 04:06:37

标签: ios xcode swift

我想在AnyObject中存储一个值,然后按如下方式检索它:

var obj:AnyObject = UIButton()
obj.setValue("James", forKey: "owner")
obj.valueForKey("owner")

但是,即使这些方法可用,AnyObject也不允许它,如错误所示:

setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key owner.'

怎么可以这样做?

4 个答案:

答案 0 :(得分:5)

您无法分配UIButton的任意键。有些类确实允许这个(CALayer和CAAnimation出现,当然还有NSDictionary),但是UIButton和AnyObject都不是这样的类,也没有owner属性 - 所以试图设置它是无稽之谈,是运行时崩溃的原因。您可以使用键设置按钮的现有属性,但不能像这样创建自己的密钥。

答案 1 :(得分:3)

您不能只动态地向对象添加属性。这不是斯威夫特的工作方式。你可以在Javascript(以及Obj-C中的一点)中使用它,但不能在Swift中使用它。

您的问题有几种简单的方法:

  1. 封装 - 创建一个封装按钮及其所有者的类,例如OwnedButton
  2. 继承 - 覆盖UIButton,为其添加新的owner属性。然后,您就可以设置button.owner = ...
  3. 让所有者保存其拥有的按钮owner.addButton(button)
  4. 单独保存关系,例如使用按钮所有者字典。

答案 2 :(得分:1)

关于按钮,您可以创建可以存储的对象数组。请参阅下面的NSCoding。

我定义对象的类 - 我写的游戏中的例子:

import Foundation

class ButtonStates: NSObject {

    var sign: String = "+"
    var level: Int = 1
    var problems: Int = 10
    var time: Int = 30
    var skipWrongAnswers = true

    func encodeWithCoder(aCoder: NSCoder!) {
        aCoder.encodeObject(sign, forKey: "sign")
        aCoder.encodeInteger(level, forKey: "level")
        aCoder.encodeInteger(problems, forKey: "problems")
        aCoder.encodeInteger(time, forKey: "time")
        aCoder.encodeBool(skipWrongAnswers, forKey: "skipWrongAnswers")
    }

    init(coder aDecoder: NSCoder!) {
        sign = aDecoder.decodeObjectForKey("sign") as String
        level = aDecoder.decodeIntegerForKey("level")
        problems = aDecoder.decodeIntegerForKey("problems")
        time = aDecoder.decodeIntegerForKey("time")
        skipWrongAnswers = aDecoder.decodeBoolForKey("skipWrongAnswers")
    }

    override init() {
    }
}

我归档和检索这些对象的类:

import Foundation

class ArchiveButtonStates:NSObject {

    var documentDirectories:NSArray = []
    var documentDirectory:String = ""
    var path:String = ""

    func ArchiveButtons(#buttonStates: ButtonStates) {
        documentDirectories = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
        documentDirectory = documentDirectories.objectAtIndex(0) as String
        path = documentDirectory.stringByAppendingPathComponent("buttonStates.archive")

        if NSKeyedArchiver.archiveRootObject(buttonStates, toFile: path) {
            //println("Success writing to file!")
        } else {
            println("Unable to write to file!")
        }
    }

    func RetrieveButtons() -> NSObject {
        var dataToRetrieve = ButtonStates()
        documentDirectories = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
        documentDirectory = documentDirectories.objectAtIndex(0) as String
        path = documentDirectory.stringByAppendingPathComponent("buttonStates.archive")
        if let dataToRetrieve2 = NSKeyedUnarchiver.unarchiveObjectWithFile(path) as? ButtonStates {
            dataToRetrieve = dataToRetrieve2 as ButtonStates
        }
        return(dataToRetrieve)
    }
}

从ViewController检索数据的示例:

let buttonStates = ArchiveButtonStates().RetrieveButtons() as ButtonStates

从ViewController存储数据的示例:

ArchiveGameData().ArchiveResults(dataSet: gameDataArray)

答案 3 :(得分:-2)

UIButton-[NSObject setValue:forKey:]-[NSObject valueForKey:]是Objective-C Cocoa API。所以你的代码不能用于相应的Objective-C代码不起作用的完全相同的原因:

id obj = [[UIButton alloc] init];
[obj setValue:@"James" forKey:@"owner"];
[obj valueForKey:@"owner"];

一旦你明白了,你就会发现你的代码存在问题。