ios - write - Save Data to.plist File in Swift




write to plist swift 4 (4)

Swift 3:

func loadData() {
    let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true) as NSArray
    let documentDirectory = paths[0] as! String
    let path = documentDirectory.appending("myData.plist")
    let fileManager = FileManager.default
    if(!fileManager.fileExists(atPath: path)){
        if let bundlePath = Bundle.main.path(forResource: "myData", ofType: "plist"){
            let result = NSMutableDictionary(contentsOfFile: bundlePath)
            print("Bundle file myData.plist is -> \(result?.description)")
            do{
                try fileManager.copyItem(atPath: bundlePath, toPath: path)
            }catch{
                print("copy failure.")
            }
        }else{
            print("file myData.plist not found.")
        }
    }else{
        print("file myData.plist already exits at path.")
    }

    let resultDictionary = NSMutableDictionary(contentsOfFile: path)
    print("load myData.plist is ->\(resultDictionary?.description)")

    let myDict = NSDictionary(contentsOfFile: path)
    if let dict = myDict{
        myItemValue = dict.object(forKey: myItemKey) as! String?
        txtValue.text = myItemValue
    }else{
        print("load failure.")
    }
}

Read and Write plist file in swift

I am trying to save data to a plist file in swift, but the data isn't showing up as it was saved when the plist is read. This is the code I was using.

var documentsDirectory = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as NSString
var path : NSString = documentsDirectory.stringByAppendingPathComponent("data.plist")
var data : NSMutableDictionary = NSMutableDictionary(contentsOfFile: path)
data.setObject(self.object, forKey: "key")
data.writeToFile(path, atomically: true)

Edit: I've heard that the best way to do this is write to the documents directory, so my question would be how should I write to a file in that directory?


Apparently the file is not in a writable location, so I created it in the documents directory.

var paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String
var path = paths.stringByAppendingPathComponent("data.plist")
var fileManager = NSFileManager.defaultManager()
if (!(fileManager.fileExistsAtPath(path)))
{
    var bundle : NSString = NSBundle.mainBundle().pathForResource("data", ofType: "plist")
    fileManager.copyItemAtPath(bundle, toPath: path, error:nil)
}
data.setObject(object, forKey: "object")
data.writeToFile(path, atomically: true)

Then, it has to be read from the documents directory.

var paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String
var path = paths.stringByAppendingPathComponent("data.plist")
let save = NSDictionary(contentsOfFile: path)

updated swift code of Rebeloper:

let BedroomFloorKey = "BedroomFloor"
let BedroomWallKey = "BedroomWall"
var bedroomFloorID: AnyObject = 101
var bedroomWallID: AnyObject = 101

 func saveGameData()
    {
        let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) as NSArray
        let documentsDirectory = paths.objectAtIndex(0) as! NSString
        let path = documentsDirectory.stringByAppendingPathComponent("GameData.plist")
        let dict: NSMutableDictionary = ["XInitializerItem": "DoNotEverChangeMe"]

        //saving values
        dict.setObject(bedroomFloorID, forKey: BedroomFloorKey)
        dict.setObject(bedroomWallID, forKey: BedroomWallKey)
        //...
        //writing to GameData.plist
        dict.writeToFile(path, atomically: false)
        let resultDictionary = NSMutableDictionary(contentsOfFile: path)
        print("Saved GameData.plist file is --> \(resultDictionary?.description)")

        self.loadGameData()

    }//eom


    func loadGameData() {
        // getting path to GameData.plist

        let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) as NSArray
        let documentsDirectory = paths[0] as! NSString
        let path = documentsDirectory.stringByAppendingPathComponent("GameData.plist")

//        let path = documentsDirectory.stringByAppendingPathComponent("GameData.plist")
        let fileManager = NSFileManager.defaultManager()

        //check if file exists
        if(!fileManager.fileExistsAtPath(path))
        {
            // If it doesn't, copy it from the default file in the Bundle

            if let bundlePath = NSBundle.mainBundle().pathForResource("GameData", ofType: "plist")
            {
                let resultDictionary = NSMutableDictionary(contentsOfFile: bundlePath)
                print("Bundle GameData.plist file is --> \(resultDictionary?.description)")

                do
                {
                    try fileManager.copyItemAtPath(bundlePath, toPath: path)
                    print("copy")
                }
                catch _
                {
                    print("error failed loading data")
                }
            }
            else
            {
                print("GameData.plist not found. Please, make sure it is part of the bundle.")
            }
        }
        else
        {
            print("GameData.plist already exits at path.")
            // use this to delete file from documents directory
            //fileManager.removeItemAtPath(path, error: nil)
        }

        let resultDictionary = NSMutableDictionary(contentsOfFile: path)
        print("Loaded GameData.plist file is --> \(resultDictionary?.description)")
        let myDict = NSDictionary(contentsOfFile: path)

        if let dict = myDict {
            //loading values
            bedroomFloorID = dict.objectForKey(BedroomFloorKey)!
            bedroomWallID = dict.objectForKey(BedroomWallKey)!
            //...
        }
        else
        {
            print("WARNING: Couldn't create dictionary from GameData.plist! Default values will be used!")
        }

    }//eom

struct Plist {

enum PlistError: ErrorType {
    case FileNotWritten
    case FileDoesNotExist
}

let name:String

var sourcePath:String? {
    guard let path = NSBundle.mainBundle().pathForResource(name, ofType: "plist") else { return .None }
    return path
}

var destPath:String? {
    guard sourcePath != .None else { return .None }
    let dir = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0]
    return (dir as NSString).stringByAppendingPathComponent("\(name).plist")
}

init?(name:String) {

    self.name = name

    let fileManager = NSFileManager.defaultManager()

    guard let source = sourcePath else { return nil }
    guard let destination = destPath else { return nil }
    guard fileManager.fileExistsAtPath(source) else { return nil }

    if !fileManager.fileExistsAtPath(destination) {

        do {
            try fileManager.copyItemAtPath(source, toPath: destination)
        } catch let error as NSError {
            print("Unable to copy file. ERROR: \(error.localizedDescription)")
            return nil
        }
    }
}


func getValuesInPlistFile() -> NSDictionary?{
    let fileManager = NSFileManager.defaultManager()
    if fileManager.fileExistsAtPath(destPath!) {
        guard let dict = NSDictionary(contentsOfFile: destPath!) else { return .None }
        return dict
    } else {
        return .None
    }
}

func getMutablePlistFile() -> NSMutableDictionary?{
    let fileManager = NSFileManager.defaultManager()
    if fileManager.fileExistsAtPath(destPath!) {
        guard let dict = NSMutableDictionary(contentsOfFile: destPath!) else { return .None }
        return dict
    } else {
        return .None
    }
}

func addValuesToPlistFile(dictionary:NSDictionary) throws {
    let fileManager = NSFileManager.defaultManager()
    if fileManager.fileExistsAtPath(destPath!) {
        if !dictionary.writeToFile(destPath!, atomically: false) {
            print("File not written successfully")
            throw PlistError.FileNotWritten
        }
    } else {
        throw PlistError.FileDoesNotExist
    }
}
}

Now, implement below in your view controller.

        if let plist = Plist(name: "plist file name") {
        let dict = plist.getMutablePlistFile()!
        dict["key"] = value

        do {
            try plist.addValuesToPlistFile(dict)
        } catch {
            print(error)
        }
            print(plist.getValuesInPlistFile())
        } else {
           print("Unable to get Plist")
        }




plist