user8962230
user8962230

Reputation:

Swift 4: Adding dictionaries to Plist

So, i have an empty plist, i am trying to create these values in the plist

using this code :

 let dictionary:[String:String] = ["key1" : "value1", "key2":"value2", "key3":"value3"]

let documentDirectoryURL =  FileManager().urls(for: .documentDirectory, in: .userDomainMask).first!
let fileURL = documentDirectoryURL.appendingPathComponent("dictionary.plist")
if NSKeyedArchiver.archiveRootObject(dictionary, toFile: fileURL.path) {
    print(true)
}

if let loadedDic = NSKeyedUnarchiver.unarchiveObject(withFile: fileURL.path) as? [String:String] {
    print(loadedDic)   // "["key1": "value1", "key2": "value2", "key3": "value3"]\n"
}

everything is fine here, but the question is, when i click the plist in my xcode project, its empty, these values are only printed not inserted to the plist

Upvotes: 7

Views: 6687

Answers (3)

vadian
vadian

Reputation: 285072

NSKeyedUnarchiver is the wrong way to save property lists.

There is a dedicated struct PropertyListSerialization to load and save property lists.

First declare a computed property plistURL

var plistURL : URL {
    let documentDirectoryURL =  try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
    return documentDirectoryURL.appendingPathComponent("dictionary.plist")
}

and two methods for loading and saving

func savePropertyList(_ plist: Any) throws
{
    let plistData = try PropertyListSerialization.data(fromPropertyList: plist, format: .xml, options: 0)
    try plistData.write(to: plistURL)
}


func loadPropertyList() throws -> [String:String]
{
    let data = try Data(contentsOf: plistURL)
    guard let plist = try PropertyListSerialization.propertyList(from: data, format: nil) as? [String:String] else {
        return [:]
    }
    return plist
}

Create the dictionary and save it

do {
    let dictionary = ["key1" : "value1", "key2":"value2", "key3":"value3"]
    try savePropertyList(dictionary)
} catch {
    print(error)
}

To update a value read it, update the value and save it back

do {
    var dictionary = try loadPropertyList()
    dictionary.updateValue("value4", forKey: "key4")
    try savePropertyList(dictionary)
} catch {
    print(error)
}

Upvotes: 17

Jitendra Modi
Jitendra Modi

Reputation: 2394

Here is my answer

 //MARK: User.plist Save & retrive data 
    func saveUserDataWithParams(userData: AnyObject) -> Void { 
        let documentsDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString 
        let path : NSString = documentsDirectory.appendingPathComponent("User.plist") as NSString 
        //userData.write(path as String, atomically: true) 
        userData.write(toFile: path as String, atomically: true) 
    } 

    func getUserPlistData() -> NSMutableDictionary { 
        let documentsDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString 
        let path : NSString = documentsDirectory.appendingPathComponent("User.plist") as NSString 

        let fileManager = FileManager.default 
        if (!(fileManager.fileExists(atPath: path as String))) 
        { 
            let documentsDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString 
            let path : NSString = documentsDirectory.appendingPathComponent("User.plist") as NSString 
            let data : NSMutableDictionary = NSMutableDictionary() 
            data.write(toFile: path as String, atomically: true) 
        } 
        let data : NSMutableDictionary = NSMutableDictionary(contentsOfFile: path as String)! 
        return data 
    } 

Upvotes: -1

Guoye Zhang
Guoye Zhang

Reputation: 519

Have you tried using PropertyListEncoder instead of NSKeyedArchiver?

do {
    try PropertyListEncoder().encode(dictionary).write(to: fileURL)
} catch {
    print(error)
}

Decode:

do {
    let data = try Data(contentsOf: fileURL)
    try PropertyListDecoder().decode([String: String].self, from: data)
} catch {
    // Handle error
}

Upvotes: 3

Related Questions