施展NSString! to swift中的String

时间:2014-09-20 08:14:20

标签: string casting swift nsstring nscoding

我在String

中有一个实例变量名
var name: String

我的类实现了NSCoding协议。所以我的名字是

func encodeWithCoder(aCoder: NSCoder) {
    aCoder.encodeObject(self.name, forKey: kName)
}

required init(coder aDecoder: NSCoder) {
    self.name = aDecoder.decodeObjectForKey(kName) as String  // CRASH HERE
}

结果?我在使用解码器启动时遇到了运行时崩溃。我把init更改为:

var temp = aDecoder.decodeObjectForKey(kName) as NSString!
self.name = aDecoder.decodeObjectForKey(kName) as String

并意识到值temp保持正确的NSString值。所以我认为下面的行将解决它,但它会发出一个链接器错误:

self.name = aDecoder.decodeObjectForKey(kName) as NSString!

问题是如何把温度变成名字?

2 个答案:

答案 0 :(得分:4)

decodeObjectForKey会返回一个可选的AnyObject?,因此您必须保护代码免受可能的nil值的影响。使用强制解包的强制转换听起来不安全。

我无法重现错误(因此问题可能在您的代码中的其他位置),但这是我在初始化name属性时的方法:

    var tempName = aDecoder.decodeObjectForKey("name") as? String
    if let tempName = tempName {
        self.name = tempName
    } else {
        self.name = "some initial value"
    }

注意使用可选的向下转换as?,它总是产生一个结果(nil或有效的类型值)而不是as NSString!,如果无法进行向下转换,则会触发异常(对于实例,如果你期望一个字符串,但它是一个int而不是。)

该代码还允许您更好地调试 - 如果tempNamenil,则该密钥不存在或相应的值为不同类型。

答案 1 :(得分:0)

我需要做两件事才能让它发挥作用:

  1. 清除构建并删除派生数据文件夹
  2. 出于某种原因,NSString和String之间的桥接在这种情况下不起作用。所以铸造应该分两个阶段完成

    if let name = aDecoder.decodeObjectForKey(kName) as? NSString {
        self.name = name as String
    } else {
        assert(false, "ERROR: could not decode")
        self.name = "ERROR"
    }