xcode 在 Swift 中,对于 AnyObject,我如何 setValue() 然后调用 valueForKey()
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26667380/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
In Swift, for AnyObject, how do I setValue() then call valueForKey()
提问by yjsa
I'd like to store a value in AnyObject then retrieve it later as follows:
我想在 AnyObject 中存储一个值,然后按如下方式检索它:
var obj:AnyObject = UIButton()
obj.setValue("James", forKey: "owner")
obj.valueForKey("owner")
However, AnyObject does not allow it even if these methods are available as shown by the error:
但是,即使这些方法可用, AnyObject 也不允许这样做,如错误所示:
setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key owner.'
How could this be done?
这怎么可能?
回答by matt
You cannot assign to an arbitrary key of a UIButton. Some classes do permit this (CALayer and CAAnimation come to mind, and NSDictionary of course), but neither UIButton nor AnyObject is such a class, and neither has an owner
property — so trying to set it is nonsense, and that is what causes the crash at runtime. You can set a button's existingproperty using a key, but you can't just invent your own key like this.
您不能分配给 UIButton 的任意键。某些类确实允许这样做(想到 CALayer 和 CAAnimation,当然还有 NSDictionary),但是 UIButton 和 AnyObject 都不是这样的类,并且都没有owner
属性 - 所以试图设置它是无稽之谈,这就是导致崩溃的原因在运行时。您可以使用键设置按钮的现有属性,但您不能像这样发明自己的键。
回答by Sulthan
You cannot just add properties to objects dynamically. That's not how Swift works. You could get away with it in Javascript (and a bit in Obj-C) but not in Swift.
您不能只是动态地向对象添加属性。这不是 Swift 的工作方式。你可以在 Javascript 中摆脱它(在 Obj-C 中有点),但在 Swift 中则不然。
There are several simple ways out of your problem:
有几种简单的方法可以解决您的问题:
- Encapsulation - create a class encapsulating a button and its owner, e.g.
OwnedButton
. - Inheritance - Override UIButton, adding it a new
owner
property. Then you will be able to just setbutton.owner = ...
. - Let the owner save the buttons it owns
owner.addButton(button)
- Save the relation separately, e.g. using a button-owner dictionary.
- 封装 - 创建一个封装按钮及其所有者的类,例如
OwnedButton
. - 继承 - 覆盖 UIButton,为它添加一个新
owner
属性。然后你就可以设置了button.owner = ...
。 - 让所有者保存其拥有的按钮
owner.addButton(button)
- 单独保存关系,例如使用按钮所有者字典。
回答by Steve Rosenberg
Regarding your buttons, you can create array of objects that can be stored. See use of NSCoding below.
关于您的按钮,您可以创建可以存储的对象数组。请参阅下面的 NSCoding 使用。
Class where I define objects - example from a game I wrote:
我在其中定义对象的类 - 我编写的游戏示例:
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() {
}
}
Class where I archive and retrieve these objects:
我归档和检索这些对象的类:
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)
}
}
example of retrieving the data from a ViewController:
从 ViewController 检索数据的示例:
let buttonStates = ArchiveButtonStates().RetrieveButtons() as ButtonStates
example of storing data from a ViewController:
从 ViewController 存储数据的示例:
ArchiveGameData().ArchiveResults(dataSet: gameDataArray)
回答by newacct
UIButton
, -[NSObject setValue:forKey:]
and -[NSObject valueForKey:]
are Objective-C Cocoa APIs. So your code does not work for the exact same reason that the corresponding Objective-C code does not work:
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"];
Once you figure that out, you will have figured out the problem with your code.
一旦你弄清楚了,你就会发现代码的问题。