Swift UnsafePointer <t>(data.bytes).memory在某些(但不是全部)情况下崩溃

时间:2015-04-28 01:38:17

标签: swift struct nsuserdefaults nsdata

我有以下结构:

struct Identity {
    var id: Int
    var createdAt: NSDate
    var string: String
    var apnsToken: String
}

在我的应用程序执行过程中,此结构的实例(?)变为NSData(使用以下代码)并存储在NSUserDefaults中:

var id = Identity(id: 0, createdAt: NSDate(), string: "string", apnsToken: "<apns-token-here>")
var data = NSData(bytesNoCopy: &id, length: sizeof(Identity),freeWhenDone:false)

当我尝试从NSData实例获取结构时,它崩溃了一个EXC_BAD_ACCESS(它是代码1):

var id = UnsafePointer<Identity>(userDefaultsData.bytes).memory

但是,这只发生在我从NSUserDefaults获取NSData实例时。如果我做了类似下面的事情,它可以毫无崩溃地工作。

var id = Identity(id: 0, createdAt: NSDate(), string: "string", apnsToken: "<apns-token-here>")
var data = NSData(bytesNoCopy: &id, length: sizeof(Identity),freeWhenDone:false)
var idPrime = UnsafePointer<Identity>(data.bytes).memory

and指令之后,EXC_BAD_ACCESS转储的汇编代码位于objc_retain的中间位置。

更新:

我并不完全诚实。数据从ObjC中的钥匙串中检索,bridge_transfer从CF数据对象转换为NSData。 CF对象来自SecItemCopy()作为out param。我认为NSUserDefaults会更加相关。

1 个答案:

答案 0 :(得分:2)

这是因为这一行:

var data = NSData(bytesNoCopy: &id, length: sizeof(Identity),freeWhenDone:false)

String(或任何其他类型,将其自己的内存分配,如数组)呈现为字节形式。相反,它所做的就是将指针序列化为字符串的内存为NSData个字节。

如果记忆不再存在,这显然会导致爆炸。这就是为什么当你一次性完成所有操作时它似乎工作的原因,但是当你存储到用户默认值时,然后,甚至在不同的过程中,甚至在不同的过程中,都可以将其恢复原状。

相反,你需要做一些事情,比如将字符串存储到他们自己的NSData对象中(比如NSData(base64EncodedString:options:)),然后存储它。