Write and Read a plist in swift with simple data

2019-01-24 21:21发布

i'm trying to understand how to save a simple value, an integer, in a plist. but i'm finding on the net only solution for save dictionary and array and i don't understand what i can change to work it only for an integer. this is the code for the moment...

var musicalChoice = 1
var musicString : String = "5"

override func viewDidLoad() {
    super.viewDidLoad()
    musicString = String(musicalChoice)}


override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

func writePlist() {
    let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) as NSArray
    let documentsDirectory = paths.objectAtIndex(0) as NSString
    let path = documentsDirectory.stringByAppendingPathComponent("Preferences.plist")
    musicString.writeToFile(path, atomically: true, encoding: NSUTF8StringEncoding, error:nil )
}

func readPlist() {

}

标签: swift plist
3条回答
forever°为你锁心
2楼-- · 2019-01-24 21:58

You can't have anything other than an array or dictionary as the root object in a plist. This is because plist files are essentially special xml files so when you are trying to read the file you ask for object at key or object at index, otherwise you have no means of obtaining your data. Also, when inserting numbers into a plist, you must wrap them in the NSNumber class. To save your objects, check out this answer.

查看更多
爱情/是我丢掉的垃圾
3楼-- · 2019-01-24 22:08

Update for Swift 4

I have created SwiftyPlistManager. Take a look at it on GiHub and follow these video instructions:

YouTube Documentation

https://www.youtube.com/playlist?list=PL_csAAO9PQ8bKg79CX5PEfn886SMMDj3j

Update for Swift 3.1

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

func loadGameData() {

  // getting path to GameData.plist
  let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true) as NSArray
  let documentsDirectory = paths.object(at: 0) as! NSString
  let path = documentsDirectory.appendingPathComponent("GameData.plist")

  let fileManager = FileManager.default

  //check if file exists
  if !fileManager.fileExists(atPath: path) {

    guard let bundlePath = Bundle.main.path(forResource: "GameData", ofType: "plist") else { return }

    do {
      try fileManager.copyItem(atPath: bundlePath, toPath: path)
    } catch let error as NSError {
      print("Unable to copy file. ERROR: \(error.localizedDescription)")
    }
  }

  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.object(forKey: BedroomFloorKey)!
    bedroomWallID = dict.object(forKey: BedroomWallKey)!
    //...
  } 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.object(at: 0) as! NSString
  let path = documentsDirectory.appendingPathComponent("GameData.plist")

  let dict: NSMutableDictionary = ["XInitializerItem": "DoNotEverChangeMe"]
  //saving values
  dict.setObject(bedroomFloorID, forKey: BedroomFloorKey as NSCopying)
  dict.setObject(bedroomWallID, forKey: BedroomWallKey as NSCopying)
  //...

  //writing to GameData.plist
  dict.write(toFile: path, atomically: false)

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

Here's what I use to read/write a plist file in swift:

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

func loadGameData() {

// getting path to GameData.plist
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) as NSArray
let documentsDirectory = paths[0] as String
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)
    println("Bundle GameData.plist file is --> \(resultDictionary?.description)")

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

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

var myDict = NSDictionary(contentsOfFile: path)

if let dict = myDict {
  //loading values
  bedroomFloorID = dict.objectForKey(BedroomFloorKey)!
  bedroomWallID = dict.objectForKey(BedroomWallKey)!
  //...
} else {
  println("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")

var 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)
println("Saved GameData.plist file is --> \(resultDictionary?.description)")
}

The plist file is this:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>BedroomFloor</key>
    <integer>101</integer>
    <key>BedroomWall</key>
    <integer>101</integer>
    <key>XInitializerItem</key>
    <string>DoNotEverChangeMe</string>
</dict>
</plist>
查看更多
贼婆χ
4楼-- · 2019-01-24 22:15

My variant function to read and write .plist on swift, tested on device.

Exapmle:
var dataVersion = readPlist("Options", key: "dataVersion")
writePlist("Options", key: "dataVersion", data: 1.23)

Function:

func readPlist(namePlist: String, key: String) -> AnyObject{
    let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) as NSArray
    let documentsDirectory = paths.objectAtIndex(0) as! NSString
    let path = documentsDirectory.stringByAppendingPathComponent(namePlist+".plist")

    var output:AnyObject = false

    if let dict = NSMutableDictionary(contentsOfFile: path){
        output = dict.objectForKey(key)!
    }else{
        if let privPath = NSBundle.mainBundle().pathForResource(namePlist, ofType: "plist"){
            if let dict = NSMutableDictionary(contentsOfFile: privPath){
                output = dict.objectForKey(key)!
            }else{
                output = false
                println("error_read")
            }
        }else{
            output = false
            println("error_read")
        }
    }
    return output
}
func writePlist(namePlist: String, key: String, data: AnyObject){
    let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) as NSArray
    let documentsDirectory = paths.objectAtIndex(0) as! NSString
    let path = documentsDirectory.stringByAppendingPathComponent(namePlist+".plist")

    if let dict = NSMutableDictionary(contentsOfFile: path){
        dict.setObject(data, forKey: key)
        if dict.writeToFile(path, atomically: true){
            println("plist_write")
        }else{
            println("plist_write_error")
        }
    }else{
        if let privPath = NSBundle.mainBundle().pathForResource(namePlist, ofType: "plist"){
            if let dict = NSMutableDictionary(contentsOfFile: privPath){
                dict.setObject(data, forKey: key)
                if dict.writeToFile(path, atomically: true){
                    println("plist_write")
                }else{
                    println("plist_write_error")
                }
            }else{
                println("plist_write")
            }
        }else{
            println("error_find_plist")
        }
    }
}
查看更多
登录 后发表回答