【问题标题】:Save Data to .plist File in Swift在 Swift 中将数据保存到 .plist 文件
【发布时间】:2014-09-25 20:09:04
【问题描述】:

我正在尝试将数据快速保存到 plist 文件中,但数据没有显示,因为它是在读取 plist 时保存的。这是我使用的代码。

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)

编辑:我听说最好的方法是写入文档目录,所以我的问题是我应该如何写入该目录中的文件?

【问题讨论】:

标签: ios swift plist nsdocumentdirectory


【解决方案1】:

显然该文件不在可写位置,所以我在文档目录中创建了它。

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)

然后,它必须从文档目录中读取。

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

【讨论】:

  • 什么是数据? (与 data.setObject(...) 一样)
  • 数据是可变字典
  • 在swift 5.0中使用appeding
  • 在 SWift5 中使用 let path = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] .appendingPathComponent(plistName)
【解决方案2】:

斯威夫特 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

【讨论】:

    【解决方案3】:

    签入 Xcode 10 swift 4.1

    //TODO: for wtite in .plist file
            let docsBaseURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
            let customPlistURL = docsBaseURL.appendingPathComponent("custom.plist")
            print(customPlistURL.absoluteString)
            let dic:[String:Any] = ["key":"val"]
            // Swift Dictionary To Data.
            do  {
            let data = try PropertyListSerialization.data(fromPropertyList: dic, format: PropertyListSerialization.PropertyListFormat.binary, options: 0)
                do {
                    try data.write(to: customPlistURL, options: .atomic)
                    print("Successfully write")
                }catch (let err){
                    print(err.localizedDescription)
                }
            }catch (let err){
                print(err.localizedDescription)
            }
    

    【讨论】:

      【解决方案4】:

      使用writeToFile:options:error: 并查看错误内容:

      var error: NSError?
      var bytes = NSKeyedArchiver.archivedDataWithRootObject(data)
      if !bytes.writeToFile(path, options: nil, error: &error) {
          if let actualError = error {
              println(actualError)
          }
      }
      

      【讨论】:

      • 当我尝试构建时,这会给出错误“Extra argument 'error' in call”
      • 您使用的是什么版本的 Xcode?这在最新的测试版中编译并运行良好。
      • @trumpeter201 哦,我没有注意到data 不是NSData 的实例。 NSMutableDictionary 没有返回错误的writeToFile。相反,您可以先将字典转换为 NSData。我更新了我的答案。
      • 我在运行时收到错误“无法识别的选择器发送到实例”
      • FWIW,这种模式是错误的:你应该检查writeToFile(_:options:error:)的返回值,只有当它是YES时才打印出error
      【解决方案5】:
      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
          }
      }
      }
      

      现在,在您的视图控制器中实现以下功能。

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

      【讨论】:

        【解决方案6】:

        来自您的信息属性列表

          Privacy - Photo Library Additions Usage Description
        

        类型

          String
        

        价值

          "Your App Name" would like to access the photo gallery to manage your profile picture
        

        【讨论】:

          【解决方案7】:

          更新了 Rebeloper 的 swift 代码:

          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
          

          【讨论】:

            猜你喜欢
            • 2017-05-30
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-05-31
            • 2013-12-15
            • 1970-01-01
            • 1970-01-01
            • 2016-08-17
            相关资源
            最近更新 更多