简体   繁体   中英

Swift 3: cannot write data to plist file

I am trying to use a file called Data.plist to store some simple unstructured data, and I placed this file at the root folder of my app. To make it simple to read/write to this file, I created the following DataManager struct. It can read Data.plist file with no problem, but it cannot write data to the file. I am not sure where the problem is, could anyone spot where might be wrong?

struct DataManager {

    static var shared = DataManager()        

    var dataFilePath: String? {        
        return Bundle.main.path(forResource: "Data", ofType: "plist")
    }

    var dict: NSMutableDictionary? {
        guard let filePath = self.dataFilePath else { return nil }
        return NSMutableDictionary(contentsOfFile: filePath)
    }

    let fileManager = FileManager.default

    fileprivate init() {

        guard let path = dataFilePath else { return }
        guard fileManager.fileExists(atPath: path) else {
            fileManager.createFile(atPath: path, contents: nil, attributes: nil) // create the file
            print("created Data.plist file successfully")
            return
        }
    }

    func save(_ value: Any, for key: String) -> Bool {
        guard let dict = dict else { return false }

        dict.setObject(value, forKey: key as NSCopying)
        dict.write(toFile: dataFilePath!, atomically: true)

        // confirm
        let resultDict = NSMutableDictionary(contentsOfFile: dataFilePath!)
        print("saving, dict: \(resultDict)") // I can see this is working

        return true
    }

    func delete(key: String) -> Bool {
        guard let dict = dict else { return false }
        dict.removeObject(forKey: key)
        return true
    }

    func retrieve(for key: String) -> Any? {
        guard let dict = dict else { return false }

        return dict.object(forKey: key)
    }
}

You cannot modify the files inside your app bundle. So all the files that you get with Bundle.main.path(forResource:ofType:) are readable but not writable.

If you want to modify this file you will need to copy it inside your app's document directory first.

let initialFileURL = URL(fileURLWithPath: Bundle.main.path(forResource: "Data", ofType: "plist")!)
let documentDirectoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last!
let writableFileURL = documentDirectoryURL.appendingPathComponent("Data.plist", isDirectory: false)

do {
    try FileManager.default.copyItem(at: initialFileURL, to: writableFileURL)
} catch {
    print("Copying file failed with error : \(error)")
}

// You can modify the file at writableFileURL

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM