关于ios:带有archiveRootObject的URLByAppendingPathComponent无法正常工作?

URLByAppendingPathComponent with archiveRootObject not working correctly?

我目前正在Xcode 7和ios 9上使用SpriteKit,我遇到了建议URLByAppendingPathComponent方法(用于与archiveRootObject结合使用来访问文件的本地URL)不是将对象保存到文档目的地,而是保存在Data文件夹中。这是代码

1
2
3
4
5
6
7
8
9
10
11
12
13
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()。我建议这样做:

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

String(x)的更多信息:

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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)
    ...