Ios 在Swift中,对于任何对象,如何设置value(),然后调用valueForKey()
我想在任何对象中存储一个值,然后按如下方式检索它:Ios 在Swift中,对于任何对象,如何设置value(),然后调用valueForKey(),ios,xcode,swift,Ios,Xcode,Swift,我想在任何对象中存储一个值,然后按如下方式检索它: 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.'
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.'
如何做到这一点?您不能为UIButton分配任意键。有些类确实允许这样做(我想到的是CALayer和CAAnimation,当然还有NSDictionary),但UIButton和AnyObject都不是这样的类,而且都没有
owner
属性-因此试图设置它是毫无意义的,这就是运行时崩溃的原因。可以使用键设置按钮的现有属性,但不能像这样发明自己的键。关于按钮,可以创建可存储的对象数组。请参见下面的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
ArchiveGameData().ArchiveResults(dataSet: gameDataArray)
存储来自ViewController的数据的示例:
let buttonStates = ArchiveButtonStates().RetrieveButtons() as ButtonStates
ArchiveGameData().ArchiveResults(dataSet: gameDataArray)
您不能只是动态地向对象添加属性。斯威夫特不是这样工作的。你可以用Javascript(还有一点Obj-C)但不能用Swift 有几种简单的方法可以解决您的问题:
OwnedButton
owner
属性。然后您就可以设置button.owner=…
owner.addButton(按钮)
ui按钮
、-[NSObject setValue:forKey:][/code>和-[NSObject valueForKey:][/code>都是Objective-C Cocoa API。因此,您的代码不工作的原因与相应的Objective-C代码不工作的原因完全相同:
id obj = [[UIButton alloc] init];
[obj setValue:@"James" forKey:@"owner"];
[obj valueForKey:@"owner"];
一旦你明白了这一点,你就会明白代码的问题。UIButton和AnyObject都没有属性所有者,那么你在这里期待什么呢?@matt,“所有者”只是任何用户定义的键。主要问题是如何使用可用于任何对象(编译)的.setValue和.valueForKey方法?您使用它们很好。这就是你的应用程序编译的原因。但当你的应用程序运行时,结果是没有这样的密钥。正如我在下面的回答中所说,UIButton或AnyObject没有“用户定义键”。运行时对象关联是否容易从Swift获得?@Tommy否。在大多数语言中,它们很难获得,因为对象的内存布局是固定的。但是很少需要该功能,因为它需要动态访问属性(使用其名称),并且有更简单的方法来实现相同的功能,例如封装、继承或单独的字典。斯威夫特不是,汤米,你真正想做的是什么?也许有一个更简单的方法。。。在我看来,你提出了一个错误的问题——你假设了一种实现目标的方式,而不是问如何实现这个目标;我真正想做的就是借此机会了解Swift对Objective-C运行时特性的访问(如果有的话)。我还没有太多机会使用Swift。对不起,我不知道谁是谁。