我有下面的代码,用来获取一个已经归档的对象的路径
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/