代码:
class User
{
class var BoolProperty: Bool
{
get {
var anyObject: AnyObject? = getValue("BoolProperty")
if let value = anyObject as? Bool {
return value
}
else {
return false
}
}
set(value) {
setValue("BoolProperty", value: value)
}
}
private class func getValue(key: String) -> AnyObject?
{
var store = NSUserDefaults.standardUserDefaults();
return store.objectForKey(key) as AnyObject?
}
}
通过测试:
class UserTests: XCTestCase
{
func testFields()
{
User.BoolProperty = true
var result = User.BoolProperty
XCTAssertEqual(true, result)
}
}
但下面的代码没有通过相同的测试,它使用 T 而不是 Bool 进行转换:
class User
{
class var BoolProperty: Bool
{
get {
return get("BoolProperty", defaultValue: false)
}
set(value) {
setValue("BoolProperty", value: value)
}
}
private class func getValue(key: String) -> AnyObject?
{
var store = NSUserDefaults.standardUserDefaults();
return store.objectForKey(key) as AnyObject?
}
private class func get<T>(key: String, defaultValue: T) -> T
{
var anyObject: AnyObject? = getValue(key)
if let value = anyObject as? T {
return value
}
else {
return defaultValue
}
}
}
似乎出于某种原因 if let value = anyObject as? T
在转换为 T 时总是返回 false。
在 C# 中,这是使用无类型集合的经典示例,我想知道在 Swift 中实现相同目的的正确方法是什么。
最佳答案
问题是 NSNumber
不是 Bool
。它看起来像一个Bool
,也可以转换成一个Bool
,但它实际上是不同的类型。您的 anyObject
实际上是一个 NSNumber
,并要求它成为 as? T
其中 T
是 Bool
太远了。这仍然可能是一个编译器错误,因为它应该与没有泛型的情况相同,但这正是问题发生的地方。
您需要将泛型函数专门化为NSNumber
:
get {
return Bool(get("BoolProperty", defaultValue: NSNumber(bool: false)))
}
打开雷达可能仍然值得。无论是否使用泛型,它的行为都不应该有所不同。
也就是说,部分问题在于 AnyObject
的使用。 Bool
不是 AnyObject
。这是一个 Any
。当您尝试将其分配给 AnyObject
时,它会转换为 NSNumber
。我不知道这方面的任何文件;我已经在 Playground 上凭经验解决了这个问题。比较 let a:AnyObject = false
和 let a:Any = false
的结果。
理论上,这应该可以解决所有问题:
var anyObject: Any? = getValue(key)
但它目前会使编译器崩溃。
关于swift - 将 AnyObject 转换为 T,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25217882/