Why does writing to plist fail in Swift? - ios

I am trying to write the contents of an NSMutableDictionary to a plist in Swift 3. This is the structure I used in Objective-C but it does not work in Swift. When running the code below, it results in an error. Does anyone have any idea what might be wrong here?
let array1 = "\(Int(Value1))"
let array2 = "\(Int(Value2))"
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let plistpath = NSURL(fileURLWithPath: paths[0]).appendingPathComponent("myplist9.plist")!.absoluteString
let dictionary: NSMutableDictionary = ["String":"String"]
dictionary["Value 1"] = array1
dictionary["Value 2"] = array2
if dictionary.write(toFile: plistpath, atomically: false) {
print("Success")
}
else {
print("Error")
}

You can't get convert an NSURL to a file path using the absoluteString method. You need to use the path method.
Change:
let plistpath = NSURL(fileURLWithPath: paths[0]).appendingPathComponent("myplist9.plist")!.absoluteString
to:
let plistpath = NSURL(fileURLWithPath: paths[0]).appendingPathComponent("myplist9.plist")!.path
And since you are using Swift 3, use URL, not NSURL.
let plistpath = URL(fileURLWithPath: paths[0]).appendingPathComponent("myplist9.plist")!.path
Or you can use the NSDictionary write(to:atomically:) method that takes a URL.

Related

(iOS Swift) plist work on simulator but not on device

This plist work correctly on simulator...read and write plist data without problems!Work correctly also deleting data. It don't crash!!
If instead launch the app on device don't read nothing data!
I am using Swift 3 version 8.3.2.
Any idea?
thanks in advance!
read plist
let paths = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true) as NSArray
let documentsDirectory:AnyObject = paths[0] as AnyObject
let path = documentsDirectory.appending("orari_marcate.plist")
let fileManager = FileManager.default
let fileExists:Bool = fileManager.fileExists(atPath: path)
let lista_marcate : NSMutableDictionary = NSMutableDictionary()
var marcate2 = NSMutableArray()
if fileExists == false {
marcate2 = NSMutableArray()
} else {
marcate2 = NSMutableArray(contentsOfFile: path)!
}
write plist
lista_marcate.setValue(risultato_Ora.text, forKey: "fine_Ora")
lista_marcate.setValue(risultato_Min.text, forKey: "fine_Min")
marcate2.add(lista_marcate)
marcate2.write(toFile: path, atomically: true)

Read Write array data to plist not working

func readWriteData(){
let paths = NSSearchPathForDirectoriesInDomains(.CachesDirectory, .UserDomainMask, true)
let cachePath = paths.first
// let bundleName = NSBundle.mainBundle().infoDictionary?["CFBundleVersion"] as? String
let filePath = NSURL(fileURLWithPath: cachePath!).URLByAppendingPathComponent("cachedProducts.plist").path
var isDir : ObjCBool = false
var error: NSError?
if NSFileManager.defaultManager().fileExistsAtPath(filePath!, isDirectory: &isDir) {
var plistArray = NSArray(contentsOfFile: filePath!)
print(plistArray)//retrieving stored data
}else {
do {
try NSFileManager.defaultManager().createDirectoryAtPath(filePath!, withIntermediateDirectories: false, attributes: nil)
var cachedArray = [AnyObject]()
cachedArray.append("Harsh")
let cachedProductarray : NSArray = cachedArray
cachedProductarray.writeToFile(filePath!, atomically: true)
//Storing data to plist
} catch let error as NSError {
NSLog("\(error.localizedDescription)")
}
}
}
when i try to print plistArray it's returning nil. Please help me with the solution. I tried this using cachesDirectory and Document Directory it's the same scenario with both
The cache directory is supposed to be created at cachePath, not at filePath.
Rather than using the quite primitive writeToFile method of NSArray I'd recommend to use NSPropertyListSerialization in conjunction with NSData's writeToFile:options:error (still better writeToURL...) method to get meaningful error messages.

plist file gets written in swift 1.2 but its not get written or works in swift 2.0, what should i do?

I had written a code when i was working with swift 1.2 which its function is loading and saving the data from plist. it was working fine with swift 1.2 but now that im working on swift 2. the code still loads the value but it doesnt save the value.
i run the application on device and not the simulator.
you can see the codes below:
func loadGameData() {
let path = NSBundle.mainBundle().pathForResource("GameData", ofType: "plist")!
let myDict = NSDictionary(contentsOfFile: path)
if let dict = myDict {
highscore = dict.objectForKey("highscore")!
} else {
print("WARNING: Couldn't create dictionary from GameData.plist! Default values will be used!")
}
}
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"]
dict.setObject(highscore.integerValue, forKey: "highscore")
//writing to GameData.plist
dict.writeToFile(path, atomically: true)
let resultDictionary = NSMutableDictionary(contentsOfFile: path)
print("Saved GameData.plist file is --> \(resultDictionary?.description)")
}
the console message after saving the code is:
Saved GameData.plist file is --> Optional("{\n XInitializerItem = DoNotEverChangeMe;\n highscore = 25;\n}")
does anyone know a different code which works with swift 2 ? this one worked fine with the previous versions.
Tnx for the help
Problem is you are reading from Main bundle while writing into Documents directly.
Reading Path: NSBundle.mainBundle().pathForResource("GameData", ofType: "plist")!
Writing Path: NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) as NSArray
To fix this, change your reader code like:
func loadGameData() {
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) as NSArray
let documentsDirectory = paths.objectAtIndex(0) as! NSString
let path = documentsDirectory.stringByAppendingPathComponent("GameData.plist")
let myDict = NSDictionary(contentsOfFile: path)
if let dict = myDict {
highscore = dict.objectForKey("highscore")!
} else {
print("WARNING: Couldn't create dictionary from GameData.plist! Default values will be used!")
}
}

Trying to read a plist file from the Document directory using swift 2.0

Ok, Managed to put this code together, created a plist file with Xcode which I copied {using iTunes} to the app folder, it doesn't work...
import Foundation
class getBeaconConfiguration {
var myBeaconsDict: NSDictionary?
func getBeacons() {
let documentsPath : AnyObject = NSSearchPathForDirectoriesInDomains(.DocumentDirectory,.UserDomainMask,true)[0]
let sourcePath:NSString = documentsPath.stringByAppendingString("/beacons.plist")
let dict = NSDictionary(contentsOfFile: sourcePath as String)
print("dict",dict)
}
}
The path is good, and the plist is there, but the NSDictionary returned is a null pointer it seems. How do you do this in swift 2.0.
Get Create a URL to the file and then create a dictionary from it.
let filename = "beacons.plist"
guard
let fileURL = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first?.URLByAppendingPathComponent(filename)
else { fatalError("Unable to get file") }
let dict = NSDictionary(contentsOfURL: fileURL)
A little different in Swift 2.0, String no longer has stringByAppendingPathComponent, and you should be using this method when working with file paths.
let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as NSString
let sourcePath = documentsPath.stringByAppendingPathComponent("beacons.plist")
let dictionary = NSDictionary(contentsOfFile: sourcePath as String)
print("dict: \(dictionary)")

read/write to array plist with Swift

Im trying to read a plist that contains an Array of Ints .
This is my first time using them , and i can read them in fine , but the plist doesn't update when i write to it.
here's my code for the reading and writing..
class FavouritesManager {
var myArray:NSMutableArray = [0]
func loadDataPlist(){
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) as NSArray
let documentsDirectory = paths.objectAtIndex(0)as NSString
let path = documentsDirectory.stringByAppendingPathComponent("FavouriteIndex.plist")
let fileManager = NSFileManager.defaultManager()
if(!fileManager.fileExistsAtPath(path))
{
let bundle = NSBundle.mainBundle().pathForResource("FavouriteIndex", ofType: "plist")
fileManager.copyItemAtPath(bundle!, toPath: path, error:nil)
}
myArray = NSMutableArray(contentsOfFile: path)!
println(myArray)
}
func writeToPlist(indexValue:Int) {
if let path = NSBundle.mainBundle().pathForResource("FavouriteIndex", ofType: "plist"){
myArray.addObject(indexValue)
myArray.addObject(indexValue+5)
myArray.addObject(indexValue+10)
myArray.addObject(indexValue+15)
myArray.writeToFile(path, atomically: true)
}
}
The purpose of this code is to store the index of the tableViewCell that has been favourited so that I can display that row in my favourite tableViewControllwe
BTW - my plist looks like this...
Thanks !
Your problem is that you are loading the plist into your documents directory in loadDataPlist(), but you are still pulling the plist from it's original location in your writeToPlist(indexValue:) function. So you are trying to write to a plist at a readonly location. Change your write function to this:
func writeToPlist(indexValue:Int) {
var paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String
var path = paths.stringByAppendingPathComponent("MyPlist.plist")
if var plistArray = NSMutableArray(contentsOfFile: path) {
plistArray.addObject(indexValue)
plistArray.addObject(indexValue+5)
plistArray.addObject(indexValue+10)
plistArray.addObject(indexValue+15)
plistArray.writeToFile(path, atomically: false)
}
}
Note that instead of adding the values to myArray I'm only writing to the plist. You'll have to decide if you want to maintain the two arrays (the local variable myArray and the array in the plist) depending on what you're using this for. Either way, this should fix your problem.

Resources