Reputation: 13
i am currently working with SpriteKit on Xcode 7 and ios 9 and i encountered that suggested URLByAppendingPathComponent method for accessing local urls for files with combination with archiveRootObject is not saving the object to the documents destination but in the Data folder. Here is the code
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!")
}
}
This, however save the data but in the Data folder near the Bundle folder. (I havent tested it on a real device though).
In debugger the constant fp is holding correct NSURL string so i simply just dont get what am i doing wrong.
However, using let fp = docPath + "/savedObject.data"
and subsequently in the archiveRootObject function saves the object in correct location although in debugger the strings are identical.
My question is, could someone please explain me, what is wrong with the first approach?
Upvotes: 0
Views: 1286
Reputation: 118691
Nowadays, the best API to use for this is NSFileManager. You should also use NSURL path
method instead of String()
. I would recommend this:
if let docDir = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first,
let filePath = docDir.URLByAppendingPathComponent("savedObject.data").filePathURL?.path
{
// ...Write to the path
}
More on String(x)
:
I've copied the String initializer's definition below. You can see that it tries several different string representations and is mostly for debugging purposes — in the case of NSURL and many other NSObject subclasses, it calls the Obj-C description
method. You should not rely on the result of description
. Instead you should use whatever situation-specific methods are available, like path
in this case.
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)
...
Upvotes: 2