【问题标题】:Write and Read a plist in swift with simple data使用简单数据快速写入和读取 plist
【发布时间】:2015-02-14 09:30:48
【问题描述】:

我试图了解如何在 plist 中保存一个简单的值,一个整数。 但我在网上找到了保存字典和数组的唯一解决方案,我不明白我可以改变什么来只为整数工作。 这是目前的代码...

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


【解决方案1】:

您不能将数组或字典以外的任何内容作为 plist 中的根对象。这是因为 plist 文件本质上是特殊的 xml 文件,因此当您尝试读取文件时,您会在 key 处请求对象或在索引处请求对象,否则您将无法获取数据。此外,在将数字插入 plist 时,您必须将它们包装在 NSNumber 类中。要保存您的对象,请查看此answer

【讨论】:

    【解决方案2】:

    Swift 4 更新

    我已经创建了 SwiftyPlistManager。在 GiHub 上查看并按照以下视频说明进行操作:

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

    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 ?? "")")
    }
    

    这是我用来快速读取/写入 plist 文件的方法:

    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)")
    }
    

    plist 文件是这样的:

    <?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>
    

    【讨论】:

      【解决方案3】:

      我在 swift 上读取和写入 .plist 的变体函数,在设备上进行了测试。

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

      功能:

      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")
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多