swift - 将 AnyObject 转换为 T

标签 swift

代码:

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 其中 TBool 太远了。这仍然可能是一个编译器错误,因为它应该与没有泛型的情况相同,但这正是问题发生的地方。

您需要将泛型函数专门化为NSNumber:

get {
return Bool(get("BoolProperty", defaultValue: NSNumber(bool: false)))
}

打开雷达可能仍然值得。无论是否使用泛型,它的行为都不应该有所不同。

也就是说,部分问题在于 AnyObject 的使用。 Bool 不是 AnyObject。这是一个 Any。当您尝试将其分配给 AnyObject 时,它会转换为 NSNumber。我不知道这方面的任何文件;我已经在 Playground 上凭经验解决了这个问题。比较 let a:AnyObject = falselet a:Any = false 的结果。

理论上,这应该可以解决所有问题:

var anyObject: Any? = getValue(key)

但它目前会使编译器崩溃。

关于swift - 将 AnyObject 转换为 T,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25217882/

相关文章:

swift - 如果我的类位于另一个类中,如何访问该变量的属性?

swift - 应用程序名称未显示在 xcode 控制台输出中

swift - 按名称删除 SKSpriteNode

ios - 将 NSData 数组保存到 CoreData

swift - 执行 IAP 时出现 Firebase 错误

ios - AlamofireObjectMapper/ObjectMapper是否支持struct类型映射

ios - 如何在 Swift 2.0 中创建 CTRunDelegate

swift - 使类可编码

Swift:以编程方式使 UILabel 变粗而不改变其大小?

Swift 枚举关联值