Reputation: 21
I'm making a game on iPad
(v10.2.1) with Xcode(version 8.2.1)
and while I'm trying to save some data in documents folder in the sandbox, I found that all ways I tried failed: createDirectory
and createFile(using file manager)
, and writeToUrl(using NSData
). I ran the program on 2 iPads and 1 iPhone and no success.
I was able to read from a plist I created, and convert it to a dictionary, using the function convertDataFrom()
.
I'm new to data persistence or file manipulation and my game stuck here. would appreciate any help!
func loadData()->NSDictionary{
let fm = FileManager()
let sourceUrl = Bundle.main.url(forResource: "Data", withExtension: "plist")!
var appSupportDir = fm.urls(for: .documentDirectory, in: .userDomainMask).first! as? NSURL
appSupportDir = appSupportDir!.appendingPathComponent("UserData", isDirectory: true) as NSURL?
let urlForSave = (appSupportDir!.appendingPathComponent("Data.plist"))!
//load data, or if file doesn't exist yet, create one
var isDirectory: ObjCBool = false
if fm.fileExists(atPath: urlForSave.absoluteString, isDirectory: &isDirectory) {
let data = convertDataFrom(url: urlForSave)
print("data file exists")
print(isDirectory)
return data as NSDictionary
} else {
do { try fm.createDirectory(atPath: appSupportDir!.absoluteString!, withIntermediateDirectories: true, attributes: nil) }catch let Error {
print("create directory failed")
print(Error)
}
let originalData = NSData.init(contentsOf: sourceUrl)
print("\(urlForSave)")
do { try originalData?.write(toFile: urlForSave.absoluteString, options: .atomic) } catch let Error {
print(Error)
}
if (!fm.createFile(atPath: urlForSave.absoluteString, contents: originalData as Data?, attributes: nil)) {
fatalError("file creation failed")
}
let data = convertDataFrom(url: urlForSave)
print("\(data)")
print(isDirectory)
return data as NSDictionary
}
}
func convertDataFrom(url: URL)->Dictionary<String, Any> {
let dictionary = NSDictionary.init(contentsOf: url) as! Dictionary<String, Any>
return dictionary
}
Error messages for "createDirectory": Error Domain=NSCocoaErrorDomain Code=513 "You don’t have permission to save the file “UserData” in the folder “Documents”." UserInfo={NSFilePath=file:///var/mobile/Containers/Data/Application/F7F41E0D-D3F6-489B-A59E-B7AC401EC402/Documents/UserData/, NSUnderlyingError=0x174053f50 {Error Domain=NSPOSIXErrorDomain Code=1 "Operation not permitted"}} file:///var/mobile/Containers/Data/Application/F7F41E0D-D3F6-489B-A59E-B7AC401EC402/Documents/UserData/Data.plist
and for "createFile" (fatalError if createFile fails) Error Domain=NSCocoaErrorDomain Code=4 "The file “Data.plist” doesn’t exist." UserInfo={NSFilePath=file:///var/mobile/Containers/Data/Application/F7F41E0D-D3F6-489B-A59E-B7AC401EC402/Documents/UserData/Data.plist, NSUnderlyingError=0x174055bd0 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}} fatal error: file creation failed: file /Users/chanwu/Desktop/Math_DownStairs/Math_DownStairs/
Upvotes: 2
Views: 2086
Reputation: 131408
Your code checks to see if urlForSave
(the final file) exists, and if it doesn't, you then try to create the UserData directory.
If the final file doesn't exist, but the UserData directory does, I would expect the exact outcome you describe.
You should probably change your test to see if the UserData directory exists instead of testing for the final file. That way if the directory doesn't exist you'll create it, and then call write(toFile:)
, which will create the file if it doesn't exist.
Upvotes: 1