关于数据持久化操作一直是大家非常关注的问题,我最近看了好多关于数据存储方式的文章,小编在这里写下我的见解,希望能对大家有所帮助!

谈到数据储存,首先要明确区分两个概念,数据结构和储存方式。所谓数据结构就是数据存在的形式。除了基本的Dictionary、Array和Set这些对象,还有更复杂的如:关系模型、对象图和属性列表多种结构。而存储方式则简单的分为两种:内存与闪存。内存存储是临时的,运行时有效的,但效率高,而闪存则是一种持久化存储,但产生I/O消耗,效率相对低。把内存数据转移到闪存中进行持久化的操作称成为归档。

目前数据存储方式大致上可以归纳为以下几种:

1、UserDefaults;这种存储方式非常常用,它操作方便,这是系统给的一个单例类,直接操作沙盒中的Library中的Preferences中的一个名为本应用的BundleID的plist文件。但是它只适合存储用户的一些偏好设置,不易存储大量数据,它在软件升级后不会被删除。
2、writeToFile写入;该方法是一次性向文件中写入内容,本次写入会覆盖文件中原来的内容,所以适合存储经常不易变动的数据文件,可以配合plist文件使用。
3、NSCoding归档;它跟其他存储方式略有不同,他可以存储对象,能把任何对象都直接保存成文件的方式来存储,但该对象必须遵循NSCoding协议,NSKeyedArchiver存储,NSKeyedUnarchiver读取,由于它可以直接对对象进行存储,所以也很常用,比较受大家喜欢。
4、SQLite3数据库;这种方法最实用但是操作也最麻烦,于是GitHub上就出现了好多关于对SQLite3的封装,其中评星最高的有FMDB(OC)、SQLite.Swift(Swift),这两种我都试着用了一下,感觉还是有点儿麻烦,后来也对这两个库进行了2次封装,凑合着用了,这里我不是专门说它,就不拿出来献丑了,我想好多人对数据库操作不是很了解,关于对数据库的操作,我推荐看它:http://www.runoob.com/sqlite/sqlite-create-table.html。
5、Core Data(苹果官方推荐);它其实是对SQLite3的封装,哈哈,苹果也感觉直接使用SQLite3过于麻烦,于是乎…就出现了Core Data,它更加面向对象,苹果强烈推荐使用,但是每次总是需要建好多的文件,可我不习惯,看个人喜好了。
6、Realm;这是什么鬼,据说它有志于替代SQLite数据库,不过我还没仔细研究过,只是在网上看到过,评价还挺高,怎么用不清楚,但是我想不会比SQLite3操作更麻烦了,附上GitHub上地址。

好了,说了这么多,该回到正题了,今天我主要是说plist,全名PropertyList,即属性列表文件,它是一种用来存储串行化后的对象的文件。这种文件,在ios开发过程中经常被用到。这种属性列表文件的扩展名为.plist,因此通常被叫做plist文件。plist文件用source code方式打开,它其实是xml格式的。Plist文件是以key-value的形式来存储数据。既可以用来存储用户设置,也可以用来存储一些需要经常用到而不经常改动的信息。

plist存储方式操作简单,但是只适合存储小数据,像哪些以M为单位的数据就不易用这种方法了,因为它有个很大的缺点,在上面我也说到了:它每次写入都会覆盖文件中原来的内容。也就是说,每次你都需要先把文件里面的内容全部读取出来先放到内存中,然后修改好root dictionary里的内容之后再写入进去,你说是不是很鸡肋,如果你存储了几十M的东西,这样一下子写来写去的,你内存吃的消吗,况且这么大的数据读取和写入多耗时间啊。纵是如此我还是很喜欢用这种方式,小的数据没问题啊···

下面呢,我专门写了一个类来管理plist文件的操作,使用很简单,给大家分享一下:

import UIKitpublic enum Type :Int{case numbercase stringcase boolcase arraycase dictionarycase nullcase unknowncase data
}class PlistManager: NSObject {private override init() {super.init()}static let defaltManager = PlistManager()private let path = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true)[0]/** 读取根目录 plistName:plist文件名 **/subscript (_ plistName:String) -> Dictionary<String,Any> {get {let filePath = "\(path)/MyDatas/\(plistName).plist"if FileManager.default.fileExists(atPath: filePath) {let rootDic = NSDictionary.init(contentsOfFile: filePath)return rootDic as! Dictionary<String, Any>}return Dictionary<String,Any>()}}/** 读取数据 plistName:文件名,name:字段名 **/subscript (_ plistName:String,_ name:String) -> JHJSON {get {let filePath = "\(path)/MyDatas/\(plistName).plist"if FileManager.default.fileExists(atPath: filePath) {let rootDic = NSDictionary.init(contentsOfFile: filePath)return JHJSON.init(rootDic![name])}return JHJSON.init(nil)}}/** 写入数据 **/func set(value:Any,forKey:String,plistName:String) {if forKey == "" || plistName == ""{return}let filePath = "\(path)/MyDatas/\(plistName).plist"print("plist文件路径 === \(filePath)")if !(FileManager.default.fileExists(atPath: filePath)) {if let dict = value as? Dictionary<String,Any> {//如果存储对象是字典就转化为json字符串,防止字典内存在空值导致写入plist失败let dic = [forKey:dict.toJsonString()] as NSDictionarydic.write(toFile: filePath, atomically: true)}else{let dic = [forKey:value] as NSDictionarydic.write(toFile: filePath, atomically: true)}}else{if let dict = value as? Dictionary<String,Any> {//如果存储对象是字典就转化为json字符串,防止字典内存在空值导致写入plist失败var dic = self[plistName]dic[forKey] = dict.toJsonString()(dic as NSDictionary).write(toFile: filePath, atomically: true)}else{var dic = self[plistName]dic[forKey] = value(dic as NSDictionary).write(toFile: filePath, atomically: true)}}}}/** 用来解析数据 **/
struct JHJSON {fileprivate var rawArray: [Any]!fileprivate var rawDictionary: [String : Any]!fileprivate var rawString: String!fileprivate var rawNumber: NSNumber!fileprivate var rawNull: NSNull = NSNull()fileprivate var rawBool: Bool = falsefileprivate var rawData : Data!fileprivate var type: Type = .nullpublic init(_ object: Any?) {if object != nil {switch object {case let object as [Any] where object.count > 0:self.rawArray = object as [Any]self.type = .arraybreakcase let object as Dictionary<String,Any> where object.count > 0:self.rawDictionary = objectself.type = .dictionarybreakcase let object as String:self.rawString = objectself.type = .stringbreakcase let object as NSNumber:self.rawNumber = objectself.type = .numberbreakcase let object as Bool:self.rawBool = objectself.type = .boolbreakcase let object as Data:self.rawData = objectself.type = .databreakdefault:self.type = .nullbreak}}}/** 转化为String **/public var stringValue: String {get {switch self.type {case .string:return self.rawString ?? ""case .number:return self.rawNumber.stringValuecase .bool:return self.rawBool == true ? "1" : "0"case .data:return String.init(data: self.rawData, encoding: .utf8)!default:return ""}}}/** 转化为Array **/public var arrayValue: [Any] {get {switch self.type {case .array:return self.rawArraydefault:return [Any]()}}}/** 转化为Dictionary **/public var dictionaryValue: Dictionary<String,Any> {get {switch self.type {case .dictionary:return self.rawDictionarycase .data:do {let json = try JSONSerialization.jsonObject(with: self.rawData, options: .mutableContainers)if let dic = json as? Dictionary<String,Any> {return dic}else {print("不是正确的字典格式")return Dictionary<String,Any>()}} catch {print("不是正确的字典格式:\(error.localizedDescription)")return Dictionary<String,Any>()}case .string:let jsonData:Data = self.rawString.data(using: .utf8)!do {let json = try JSONSerialization.jsonObject(with: jsonData, options: .mutableContainers)if let dict = json as? Dictionary<String,Any> {return dict}else {print("不是正确的字典格式")return Dictionary<String,Any>()}} catch {print("不是正确的字典格式:\(error)")return Dictionary<String,Any>()}default:print("不是正确的字典格式")return Dictionary<String,Any>()}}}/** 转化为NSNumber **/public var numberValue: NSNumber {get {switch self.type {case .string:let decimal = NSDecimalNumber(string: self.rawString)if decimal == NSDecimalNumber.notANumber {  // indicates parse errorreturn NSDecimalNumber.zero}return decimalcase .number:return self.rawNumber ?? NSNumber(value: 0)case .bool:return NSNumber(value: self.rawBool ? 1 : 0)default:return NSNumber(value: 0.0)}}}/** 转化为Bool **/public var boolValue: Bool {get {switch self.type {case .bool:return self.rawBoolcase .number:return self.rawNumber.boolValuecase .string:return ["true", "y", "t"].contains() { (truthyString) inreturn self.rawString.caseInsensitiveCompare(truthyString) == .orderedSame}default:return false}}}/** 转data **/public var dataValue: Data {get {switch self.type {case .data:return self.rawDatadefault:return Data.init()}}}}

使用方法:

PlistManager.defaltManager.set(value: 2, forKey: "id", plistName: "MyPlis")//写入
print(PlistManager.defaltManager["MyPlis"])//读取root dictionary
print(PlistManager.defaltManager["MyPlis","data"].dictionaryValue)//根据字段读取

源文件已分享到github,点击下载,喜欢的话给颗星哈。。

关于plist文件存储方式(swift)相关推荐

  1. 所有接口添加plist文件的写法 swift

    第一步  建立plist文件 @interface JMTConfigUtils : NSObject /** *  获取配置文件中友盟key * *  @return NSString */ - ( ...

  2. 示波器的各种文件存储方式与分析

    关于示波器设置或数据的存储功能很多人表示似懂非懂,想对所测的数据进行二次分析却无从下手,存储由此上演了犹抱琵琶半遮面的经典桥段,接下来让我们来揭开它神秘的面纱,让你从此保存文件不再是难题. 示波器的存 ...

  3. Android文件存储方式之openFileOutput与获取数据openFileInput

    一般存储数据无非分为SP存储和数据库还有文件存储,这里我们说下文件存储openFileOutput和取出数据openFileInput 我们在一不小心退出APP如果再无退出之前不将数据保存的话数据是会 ...

  4. oracle文件存储方式,oracle文件存储介质介绍

    oracle文件存储介质介绍 1. 前言 现在我们用户中随着ORACLE的应用越来越复杂,对于ORACLE文件存储也再不象以前这么简单D盘,C盘的规划,特别是linux环境加上RAC的应用对存储介质有 ...

  5. linux文件存储结构,Linux文件存储方式以及软硬链接

    在Linux中,文件包括常规文件.目录.符号链接等.为了方便理解,在本文中,文件指常规文件,目录指常规目录. 文件 1. 文件是如何存储的? 文件是由3部分组成 的: 文件名: dentry 文件元数 ...

  6. oracle怎么存视频地址,oracle的警告文件存储方式和地址

    装了oracle 11g的玩了一下,有点问题,想看一下log日志,找了半天才找到,原来11g的alert log做了变动,从Oracle 11g 开始,Oracle 数据库以XML与传统的文本两种格式 ...

  7. DASH流媒体MPD文件存储

    Android中常见的持久化数据存储方法有三个:文件存储.SharedPreferences存储和数据库存储.文件存储的核心思想是将数据按照streaming的形式保存到本地,这点与C++有共通点.写 ...

  8. Spring Cloud应用开发(七:使用Git存储方式实现分布式配置管理 )

    1.使用Git存储实现管理: 1.1.配置Git.在Git上创建microservice-study-config目录,并在目录中添加开发,预发布和测试的配置文件: 1.2.修改服务端配置文件.将mi ...

  9. Kafka文件存储机制及offset存取

    Kafka是什么 Kafka是最初由Linkedin公司开发,是一个分布式.分区的.多副本的.多订阅者,基于zookeeper协调的分布式日志系统(也可以当做MQ系统),常见可以用于web/nginx ...

最新文章

  1. spring 源码 找不到 taskprovider_一步一步构建Spring5源码
  2. DbExpressionBinding requires an input expression with a collection ResultType. 参数名: input
  3. 模型越复杂越容易惰性_ML模型的惰性预测
  4. 打docker镜像_从安全到镜像流水线,Docker 最佳实践与反模式一览
  5. 科研人看过来!2021腾讯AI Lab犀牛鸟专项研究计划开始申请
  6. 几个不错的开源的.net界面控件[转贴]
  7. [bzoj 2017] [Usaco2009 Nov]硬币游戏
  8. Emacs中打造强大的Python IDE
  9. 调整linux字体渲染,开始使用 Manjaro(添加源+字体渲染去模糊+软件安装+优化配置+常见错误)(30)...
  10. 微信公众号号开发小记(六)使用开源框架开发
  11. Trie树(字典树)
  12. OSPF虚链路配置及认证
  13. 知乎客户端埋点流程、模型和平台技术
  14. 笑一笑-道高一尺魔高一丈
  15. bzoj1758 [Wc2010]重建计划
  16. coffeescript(javascript) this 的理解
  17. 羊皮卷的故事-第五章
  18. python并列排名_Oracle并列排名显示
  19. 清华大学 计算机技术 非全日制,2018年清华大学计算机系计算机技术考研(085211)考试科目、参考书目、复习经验---新祥旭考研...
  20. 金融科技大数据产品推荐:百融信贷决策审批系统

热门文章

  1. SOM网络算法分析与应用(适合入门、快速上手)
  2. Tushare了解并使用
  3. MATLAB 制作抖音同款 立体人物文字海报
  4. 《奇特的一生》——致敬时间的神
  5. HTML爱心动画小玩意儿
  6. 国外大神数据,全球主板厂商信息汇总,A B X系在主板汇总
  7. iOS 最为经典的壁纸送上!安排
  8. 【C#】 enum 还能这么玩
  9. recycleview多条目展示
  10. statistical thinking in Python EDA