带有 archiveRootObject 的 URLByAppendingPathComponent 不能正常工作?

URLByAppendingPathComponent with archiveRootObject not working correctly?

我目前正在 Xcode 7 和 ios 9 上使用 SpriteKit,我遇到了建议的 URLByAppendingPathComponent 方法,该方法用于访问文件的本地 URL 并结合 archiveRootObject 没有将对象保存到文档中目标但在数据文件夹中。这是代码

func saveData(){
   let objectToSave = SomeObject()

    let docPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String
    let path = NSURL(string: docPath)
    let fp = path?.URLByAppendingPathComponent("savedObject.data")
    if NSKeyedArchiver.archiveRootObject(objectToSave, toFile: String(fp)) {
        print("Success writing to file!")
    } else {
        print("Unable to write to file!")
    }

}

不过,这会保存数据,但会在 Bundle 文件夹附近的 Data 文件夹中。 (虽然我还没有在真实设备上测试过)。

在调试器中,常量 fp 保存着正确的 NSURL 字符串,所以我只是不明白我做错了什么。

但是,使用 let fp = docPath + "/savedObject.data" 并随后在 archiveRootObject 函数中将对象保存在正确的位置,尽管在调试器中字符串是相同的。

我的问题是,有人可以解释一下,第一种方法有什么问题吗?

如今,最好的 API 用于此目的是 NSFileManager。您还应该使用 NSURL path 方法而不是 String()。我会推荐这个:

if let docDir = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first,
    let filePath = docDir.URLByAppendingPathComponent("savedObject.data").filePathURL?.path
{
    // ...Write to the path
}

有关 String(x) 的更多信息:

我在下面复制了 String initializer 的定义。您可以看到它尝试了几种不同的字符串表示形式,并且主要用于调试目的——对于 NSURL 和许多其他 NSObject 子类,它调用 Obj-C description 方法。您不应该依赖 description 的结果。相反,您应该使用任何可用的特定情况的方法,例如本例中的 path

extension String {
    /// Initialize `self` with the textual representation of `instance`.
    ///
    /// * If `T` conforms to `Streamable`, the result is obtained by
    ///   calling `instance.writeTo(s)` on an empty string s.
    /// * Otherwise, if `T` conforms to `CustomStringConvertible`, the
    ///   result is `instance`'s `description`
    /// * Otherwise, if `T` conforms to `CustomDebugStringConvertible`,
    ///   the result is `instance`'s `debugDescription`
    /// * Otherwise, an unspecified result is supplied automatically by
    ///   the Swift standard library.
    ///
    /// - SeeAlso: `String.init<T>(reflecting: T)`
    public init<T>(_ instance: T)
    ...