cocoa-touch - NSKeyedArchiver unarchiveObjectWithFile 因 EXC_BAD_INSTRUCTION 而崩溃

标签 cocoa-touch swift nscoding nskeyedunarchiver

我有下面的代码,用来获取一个已经归档的对象的路径

let paths = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)
let path = paths[0] as String
let archivePath = path.stringByAppendingString("archivePath")

当我运行这段代码时,它在显示 lldb 的 NSSearchPathForDirectoriesInDomains 调用时崩溃

Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)

在 Xcode 的 Variables View 中,我看到路径 String 设置如我所料。在 Swift 中获取用于归档/取消归档对象的用户目录的正确方法是什么?

更新:

看起来这实际上是在我使用 NSKeyedUnarchiver 时崩溃:

stopwatches = NSKeyedUnarchiver.unarchiveObjectWithFile(archivePath) as Stopwatch []

Stopwatch 是一个实现 NSCoding 的类,stopwatches 是执行取消存档的 View 所拥有的数据源(一个 Stopwatches 数组)。

更新 2:

被归档的对象图是一个秒表数组。 NSCoding 实现如下:

func encodeWithCoder(aCoder: NSCoder!) {
    aCoder.encodeBool(self.started, forKey: "started")
    aCoder.encodeBool(self.paused, forKey: "paused")
    aCoder.encodeObject(self.startTime, forKey: "startTime")
    aCoder.encodeObject(self.pauseTime, forKey: "pauseTime")
    aCoder.encodeInteger(self.id, forKey: "id")
}

init(coder aDecoder: NSCoder!) {
    self.started = aDecoder.decodeBoolForKey("started")
    self.paused = aDecoder.decodeBoolForKey("paused")
    self.startTime = aDecoder.decodeObjectForKey("startTime") as NSDate
    self.pauseTime = aDecoder.decodeObjectForKey("pauseTime") as NSDate
    self.id = aDecoder.decodeIntegerForKey("id")
    super.init()
}

更新 3: expandTilde 设置为 true 我的路径是 /Users/Justin/Library/Developer/CoreSimulator/Devices/FF808CCD-709F-408D-9416-E‌ E47B306309D/data/Containers/Data/Application/B39CCB84-F335-4B70-B732-5C3C26B4F6AC‌/Documents/ArchivePath

如果我将 expandTilde 设置为 false,我不会崩溃,但文件未存档和未存档,路径为 @"~/Documents/ArchivePath"

删除 Application 文件夹会导致应用程序首次启动不会崩溃,但不允许其在之后重新打开。此外,删除应用程序文件夹后,我现在可以读取 lldb 中的存档路径,而不必打印它。

最佳答案

我遇到过类似的问题,它与 Swift 的名称修改有关。如果您正在读取由编码的 Objective-C 对象生成的文件,并且每个对象都有 Objective-C 类名称 Stopwatch,您将无法直接将其解码为 Swift 对象,因为 Swift 对类名和符号名进行名称重整。您在 Swift 代码中看到的 Stopwatch 在内部类似于 T23323234_Stopwatch_3242

要绕过它,请指定您的 Swift 类应使用特定的 Objective-C 类名导出,例如:

@objc(Stopwatch) class Stopwatch {
  ...
}

其中 Stopwatch 与您归档的 Objective-C 对象的类名相匹配。

编辑:在您在评论中链接的项目代码中,这里有第二个问题,即尝试编码/解码 Swift 特定的功能。只有 Objective-C 对象可以归档和取消归档。遗憾的是,结构、泛型、元组和可选值与 Objective-C 不兼容,无法与 NSCoding 一起使用。解决这个问题的最佳方法是将 Swift 类型编码为 NSDictionary 实例,例如(未经测试):

let encodedLaps = self.laps.map { lap => ["start": lap.start, "end": lap.end] }
aCoder.encodeObject(encodedLaps, forKey: "laps")

编辑 2:与我上面写的相反,这不仅限于从 Swift 读取 Objective-C 实例。似乎 NSCoding 的任何用法都需要您的类的 Objective-C 名称。我想这是因为 Swift 名称修饰可以在编译器的不同运行之间发生变化。

关于cocoa-touch - NSKeyedArchiver unarchiveObjectWithFile 因 EXC_BAD_INSTRUCTION 而崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24538779/

相关文章:

iphone - iPhone用户历史数据库(SQLite?Core-Data?)

cocoa-touch - iOS 上的音频转码

ios - 在不使用图像的情况下更改 iOS 控件的色调/背景颜色

ios - Swift:作为参数传递的字典始终为空

ios - 如何使用 NSCoding 在我的应用程序中保存/加载数据?

cocoa-touch - UIFont带有自定义领导?

ios - swift 。如何将 NSData 中的字节写入另一个 NSData?

swift - fatal error : unexpectedly found nil while unwrapping an Optional value in swift Json parsing

ios - NSCoding 和 NSData 是什么关系?

objective-c - "The data couldn’ 无法写入,因为它的格式不正确“在使用 NSKeyedArchiver 归档自定义类时发生