【iOS】—— iOS持久化

iOS持久化

      • 1. 数据持久化的目的
      • 2. iOS持久化的方案
      • 3. 数据持久化方式的分类
        • 内存缓存
        • 磁盘缓存
      • 4. 沙盒机制
      • 5. 沙盒的目录结构
        • 获取应用程序的沙盒路径
        • 每次编译代码会生成新的沙盒路径,每次运行获得的沙盒路径都不一样。
        • 访问沙盒目录常用C函数介绍
        • 沙盒目录介绍
      • 6. 持久化的存储方式
        • XML属性列表
        • Preference 偏好设置(UserDefaults)
        • NSKeyedArchiver归档解档
        • 数据库存储
        • 什么是序列化和反序列化? 用来做什么?

1. 数据持久化的目的

  1. 快速展示,提升体验

    • 已经加载过的数据,用户下次查看时,不需要再次从网络(磁盘)加载,直接展示给用户
  2. 节省用户流量(节省服务器资源)

    • 对于较大的资源数据进行缓存,下次展示无需下载消耗流量
    • 同时降低了服务器的访问次数,节约服务器资源。(图片)
  3. 离线使用。

    • 用户浏览过的数据无需联网,可以再次查看。
    • 部分功能使用解除对网络的依赖。(百度离线地图、图书阅读器)
    • 无网络时,允许用户进行操作,等到下次联网时同步到服务端。
  4. 记录用户操作

    • 草稿:对于用户需要花费较大成本进行的操作,对用户的每个步骤进行缓存,用户中断操作后,下次用户操作时直接继续上次的操作。
    • 已读内容标记缓存,帮助用户识别哪些已读。
    • 搜索记录缓存

2. iOS持久化的方案

  • NSUserDefault 简单数据快速读写
  • Property list (属性列表)文件存储
  • Archiver (归档)
  • SQLite 本地数据库
  • CoreData

3. 数据持久化方式的分类

内存缓存

定义:对于使用频率较高的数据,从网络或者磁盘加载数据到内存以后,使用后并不会马上销毁,下次使用直接从内存加载。

内存指当前程序的运行空间,缓存速度快,容量小,是临时存储文件用的。他是在内存中存储,关闭程序后内存就又回到原来的空间

  • 案例:
    • iOS系统图片加载—— [UIImage imageNamed:@“imageName”]
    • 网络图片加载第三方库SDWebImage
磁盘缓存

定义:将从网络加载的,用户操作产生的数据写入到磁盘,用户下次查看、继续操作时,直接从磁盘加载使用。

磁盘是程序的储存空间,缓存容量大,速度慢,可持有化。与内存不同的是磁盘是永久存储东西的。

  • 案例:
    • 用户输入内容草稿缓存
    • 搜索历史缓存
    • 网络图片加载三方库 SDWebImage

4. 沙盒机制

iOS中的沙盒机制是一种安全体系,为了保证系统安全,iOS每个应用程序在安装的时候,会创建属于自己的沙盒文件,应用只能访问自己的沙盒文件,不能访问其他应用的沙盒文件,当应用程序需要向外部请求或接收数据时,都需要经过权限认证,否则,无法获取到数据。所有的非代码文件都要保存在此,例如属性文件plist、文本文件、图像、图标、媒体资源等,其原理是通过重定向技术,把程序生成和修改的文件定向到自身文件夹中。

5. 沙盒的目录结构

获取应用程序的沙盒路径
 NSString *path = NSHomeDirectory();NSLog(@"%@", path);

在这里插入图片描述

每次编译代码会生成新的沙盒路径,每次运行获得的沙盒路径都不一样。

在这里插入图片描述

上面的代码得到的是当前程序应用目录的路径,该目录下就是应用程序的沙盒,在该目录下有4个文件夹:DocumentsLibrarySystemDatatmp当前应用程序只能访问该目录下的文件。

  1. Documents 目录:您应该将所有的应用程序数据文件写入到这个目录下。这个目录用于存储用户数据。该路径可通过配置实现iTunes共享文件。可被iTunes备份。
  2. AppName.app 目录:这是应用程序的程序包目录,包含应用程序的本身。由于应用程序必须经过签名,所以您在运行时不能对这个目录中的内容进行修改,否则可能会使应用程序无法启动。
  3. Library 目录:这个目录下有两个子目录:
    • Preferences 目录:包含应用程序的偏好设置文件。您不应该直接创建偏好设置文件,而是应该使用NSUserDefaults类来取得和设置应用程序的偏好。
    • Caches 目录:用于存放应用程序专用的支持文件,保存应用程序再次启动过程中需要的信息。
  4. tmp 目录:这个目录用于存放临时文件,保存应用程序再次启动过程中不需要的信息。该路径下的文件不会被iTunes备份。
访问沙盒目录常用C函数介绍
 //文件路径搜索
FOUNDATION_EXPORT NSArray<NSString *> *NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory directory, NSSearchPathDomainMask domainMask, BOOL expandTilde);

该方法返回值为一个数组,在iphone中由于只有一个唯一路径,所以直接取数组第一个元素即可。

  • 参数一 NSSearchPathDirectory directory:指定搜索的目录名称,比如这里用NSDocumentDirectory表明我们要搜索的是Documents目录。如果我们将其换成NSCachesDirectory就表示我们搜索的是Library/Caches目录。
  • 参数二 NSSearchPathDomainMask domainMask:搜索主目录的位置,NSUserDomainMask表示搜索的范围限制于当前应用的沙盒目录。还可以写成NSLocalDomainMask(表示/Library)、NSNetworkDomainMask(表示/Network)等。
  • 参数三 BOOL expandTilde:是否获取完整的路径,我们知道在iOS中的全写形式是/User/userName,该值为YES即表示写成全写形式,为NO就表示直接写成“~”。
 typedef NS_OPTIONS(NSUInteger, NSSearchPathDomainMask) {NSUserDomainMask = 1,       // 用户目录 - 基本上就用这个。 NSLocalDomainMask = 2,      // 本地NSNetworkDomainMask = 4,    // 网络 NSSystemDomainMask = 8,     // 系统NSAllDomainsMask = 0x0ffff  // 所有 
};//常用的NSSearchPathDirectory枚举值
typedef NS_ENUM(NSUInteger, NSSearchPathDirectory) {NSApplicationDirectory = 1,             // supported applications (Applications)NSDemoApplicationDirectory,             // unsupported applications, demonstration versions (Demos)NSAdminApplicationDirectory,            // system and network administration applications (Administration)NSLibraryDirectory,                     // various documentation, support, and configuration files, resources (Library)NSUserDirectory,                        // user home directories (Users)NSDocumentationDirectory,               //  Library 下的(Documentation)模拟器上没有创建NSDocumentDirectory,                    // documents (Documents)
};

在这里插入图片描述

沙盒目录介绍
  • Documents:保存持久化数据,会备份。一般用来存储需要持久化的数据。
    一般我们在项目中,我们会把一些用户的登录信息以及搜索历史记录等一些关键数据存储到这里。
 NSString *documentfileName = [documentDirectory stringByAppendingPathComponent:@"data.txt"];NSLog(@"%@", documentfileName);

这样这个filename就是完整的.txt文件的目录。

  • Library:默认存放设置和其他状态,除了cache子目录之外都会被iCloud同步。

    • Application Support:包含程序用来运行但应对用户隐藏的文件。
    • Caches:保存应用运行时生成的需要持久化的数据,一般存储体积大、不需要备份的非重要数据,如网络请求的音视频与图片等的缓存。
    • Cookies:系统会将App中的网络请求cookies保存为文件。
    • Preferences:保存应用的所有偏好设置,UserDefaults生成的plist文件保存到该目录下。
    • SplashBoard:存储启动屏缓存,缓存文件格式为 ktx,本质上就是图片,如果启动屏不生效的问题可以考虑从删除该路径下相关缓存文件这个角度解决。
  • SystemData:存放系统数据,无对外暴露的接口。

  • tmp:临时文件夹(系统会不定期删除里面的文件)。

6. 持久化的存储方式

XML属性列表

属性列表是一种XML格式的文件,拓展名为plist

如果对象是NSStringNSDictionaryNSArrayNSDataNSNumber等类型,就可以使用
writeToFile:atomically:方法直接将对象写到属性列表文件中,举例说明:

 //获取文件目录NSArray<NSString*> *document = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);NSString *documentDirectory = [document firstObject];NSLog(@"documentDirectory:%@", documentDirectory);NSString *documentfileName = [documentDirectory stringByAppendingPathComponent:@"data.txt"];NSLog(@"%@", documentfileName);//存字典   将字典数据存储到plist文件NSDictionary *dict = @{@"name": @"cuiyang", @"boom": @"9527"};[dict writeToFile:documentfileName atomically:YES];//取字典NSDictionary *msgDict = [NSDictionary dictionaryWithContentsOfFile:documentfileName];NSLog(@"%@", msgDict);

在这里插入图片描述

进入该项目的沙盒目录,可以看到Document目录下多了我们建立的test.plist文件。
在这里插入图片描述

能看到我们存储的字典类型的文件已经存放:
在这里插入图片描述

Preference 偏好设置(UserDefaults)

很多iOS应用都支持偏好设置,提供了一套标准的解决方案来为应用加入偏好设置功能,比如保存用户名,字体大小,密码,是否自动登录等。

每个应用都有个NSUserDefaults实例,可以通过它来存取偏好设置,不需要路径。其本身的创建类似于单例模式,我们在后面用不同的属性名再次申请创建,会覆盖之前的数据。

NSUserDefaults:简单数据快速读写,不能存储自定义类型。
UserDefaults设置数据时,不是立即写入,而是根据时间戳定时地把缓存中的数据写入本地磁盘。所以调用了set方法之后数据有可能还没有写入磁盘应用程序就终止了。出现以上问题,可以通过调用synchornize方法[defaults synchornize];强制写入。

偏好设置存储的优点

  • 不需要关心文件名,系统会自动帮你生成一个文件名。
  • 快速做键值对的存储。
 - (void)preference {NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];// 存储数据,快速键值对/[defaults setObject:@"hanjiawei" forKey:@"username"];[defaults setObject:@"9527-2004" forKey:@"password"];[defaults synchronize];// 需要验证账号密码的地方,获取偏好设置对象NSUserDefaults *defaultsA = [NSUserDefaults standardUserDefaults];NSString *name = [defaultsA objectForKey:@"username"];NSString *password = [defaultsA objectForKey:@"password"];NSLog(@"name:%@ password:%@", name, password);}

在这里插入图片描述

NSKeyedArchiver归档解档

NSKeyedArchiver(归档):归档一般都是保存自定义对象的时候,使用归档。因为plist文件不能够保存自定义对象。如果一个字典中保存有自定义对象,如果把这个对象写入到文件当中,就不会生成plist文件。如果对象是NSStringNSDictionaryNSArrayNSDataNSNumber等类型,可以直接用NSKeyedArchiver进行归档和恢复。

在使用解档和归档的时候,必须遵守NSSecureCoding协议才行,但是新版本就必须的遵守NSSecureCoding协议,NSSecureCoding协议也遵循了原来NSCoding这个协议,不过我们还需要遵循它的一个supportsSecureCoding方法,这样我们才能归档成功。

因为NSSecureCoding协议也遵循了原来NSCoding这个协议,所以他也就有了- (void)encodeWithCoder:(NSCoder *)coder方法和- (id)initWithCoder:(NSCoder *)coder方法:

  1. - (void)encodeWithCoder:(NSCoder *)coder方法:每次归档对象,都调用这个方法。在这个方法里面指定如何归档对象中的每个实例变量。可以使用encodeObject:forKey:方法归档实例变量。
  2. - (id)initWithCoder:(NSCoder *)coder方法:每次从文件中恢复对象的时候,都会调用这个方法,在这个方法里面指定如何解码文件中的数据为对象的实例变量,可以使用decodeObject:forKey方法解码实例变量。

除了这两个方法之外,NSSecureCoding协议还有**+ (BOOL)supportsSecureCoding方法**,只有当这个方法为YES的时候,才可以归档成功。

利用归档解档尝试存储一个Person对象

#import <Foundation/Foundation.h>NS_ASSUME_NONNULL_BEGIN@interface Person : NSObject<NSSecureCoding>
@property (nonatomic, strong) NSString *name;
@property (nonatomic, assign) int age;- (void)saveData;
- (void)readData;@endNS_ASSUME_NONNULL_END#import "Person.h"
@implementation Person- (void)encodeWithCoder:(nonnull NSCoder *)coder {[coder encodeObject:_name forKey:@"name"];[coder encodeInt:_age forKey:@"age"];
}- (nullable instancetype)initWithCoder:(nonnull NSCoder *)coder {if (self = [super init]) {_name = [coder decodeObjectForKey:@"name"];_age = [coder decodeIntForKey:@"age"];}return self;
}
// 返回YES才能成功归档
+ (BOOL)supportsSecureCoding {return YES;
}- (void)saveData {Person *p = [[Person alloc] init];p.name = @"hanjiawei";p.age = 20;NSError *error;// 2.归档模型对象// 3.获得 Documents 的全路径NSString *docu = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];// 4.获得新文件的全路径,即新建一个 person.data 文件来存储我们要归档的数据NSString *path = [docu stringByAppendingString:@"/person.plist"];NSLog(@"%@", path);// 5.将对象封装为 Data 数据并归档NSData *data = [NSKeyedArchiver archivedDataWithRootObject:p requiringSecureCoding:YES error:&error];if (error) {NSLog(@"sodufosuf%@", error);}[data writeToFile:path atomically:YES];}// 读档,将数据从文件中读出
- (void)readData {NSError *error;// 1.获得 Documents 的全路径NSString *docu = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];// 2.获得文件的全路径,即获取我们要解档文件的路径NSString *path = [docu stringByAppendingString:@"/person.plist"];// 3.从 path 路径中获取 Data 数据NSData *unData = [NSData dataWithContentsOfFile:path];// 4.从文件中读取Person对象Person *person = (Person *)[NSKeyedUnarchiver unarchivedObjectOfClass:[Person class] fromData:unData error:&error];// 打印结果NSLog(@"name: %@ age: %d",person.name, person.age);
}@end

Document多了一个plist文件
在这里插入图片描述

我们一定要遵守NSSecureCoding协议,并实现它的归档解档方法,以及+ (BOOL)supportsSecureCoding方法!!!

数据库存储
  • SQLite:
    是目前主流的嵌入式关系型数据库,其最主要的特点就是轻量级、跨平台,当前很多嵌入式操作系统都将其作为数据库首选。

  • CoreData:
    CoreData是iOS5之后才出现的一个框架,本质上是对SQLite的一个封装,它提供了对象-关系映射(ORM)的功能,即能够将OC对象转化成数据,保存在SQLite数据库文件中,也能够将保存在数据库中的数据还原成OC对象,在这个过程中不需要手动编写任何SQL语句,CoreData封装了数据库的操作过程,以及数据库中数据和OC对象的转换过程。通过CoreData管理应用程序的数据模型,可以极大程度减少需要编写的代码数量。

  • FMDB:

    是一个处理数据存储的第三方框架,框架是对sqlite的封装,整个框架非常轻量级但又不失灵活性,而且更加面向对象。

SQLite和CoreData的区别:

  • CoreData可以在一个对象更新时,其关联的对象也会随着更新,相当于你更新一张表时,其关联的其他表的也会随着更新。
  • CoreData供更简单的性能管理机制,可以限制查询记录的总数,这个类会自动更新其缓存。
  • 多表查询方面,CoreData没有SQL直观,没有类似外连接,左连接等操作。
什么是序列化和反序列化? 用来做什么?
  • 序列化:把对象转化为字节序列的过程
  • 反序列化:把字节序列恢复成对象
  • 作用:把对象写到文件或者数据库中,并且读取出来

iOS中怎么实现序列化?

在iOS实际开发中,我们也会使用到序列化,归档就是我们在iOS开发中使用序列化的场景!
在iOS中一个自定义对象是无法直接存入到文件中的,必须先转化成二进制流才行。从对象到二进制数据的过程我们一般称为对象的序列化(Serialization),也称为归档(Archive)。同理,从二进制数据到对象的过程一般称为反序列化或者反归档(解档)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3281546.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

Tomcat IntelliJ IDEA整合

一、下载及安装Tomcat 下载官网&#xff1a;Apache Tomcat - Welcome! 1.点击红色框中的任意一个版本 2.点击下载 3.解压后放在任意路径&#xff08;我的是放在D盘&#xff09; 4.在bin目录下找到startup.bat&#xff0c;点击启动Tomcat 5.如果双击启动后&#xff0c;终端出…

什么是通孔,盲孔,埋孔

通孔&#xff1a;贯穿所有层的孔&#xff0c;容易被逆向破解。 盲孔&#xff1a;表层和内层中间的孔&#xff0c;破解难度加大。 埋孔&#xff1a;内层的孔&#xff0c;破解难度极大。 贯通孔&#xff0c; 浪费了许多宝贵的布线通道&#xff0c;为解决这一矛盾&#xff0c;出…

【综合案例】使用DevEco Studio编写人气卡片

效果展示 知识点 绝对定位 作用&#xff1a;控制组件位置&#xff0c;可以实现层叠效果 特点&#xff1a; 参照 父组件左上角 进行偏移绝对定位后的组件 不再占用自身原有位置 语法&#xff1a;.position(位置对象) 参数&#xff1a;{ x: 水平偏移量 , y: 垂直偏移量} z…

(三)延时任务篇——通过redis的zset数据结构,实现延迟任务实战

前言 在前一篇内容中我们介绍了如何使用redis key过期失效的监控&#xff0c;完成任务延时关闭的功能&#xff0c;同时官方并不支持使用此种方式实现&#xff0c;由于其安全性较低&#xff0c;存在数据丢失的情况。本节内容是对延迟任务的又一实现方案&#xff0c;通过redis z…

多线程上下文切换:详解与优化

多线程上下文切换&#xff1a;详解与优化 一、什么是多线程上下文切换&#xff1f;二、对性能的影响2.1 优点2.2 缺点 三、优化策略 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 一、什么是多线程上下文切换&#xff1f; 多线程上下文切…

使用pfld模型进行表盘读数检测

目录 1. 下载项目和数据集2. 配置环境3. 训练和测试3.1 训练3.2 测试 4. 参考 使用pfld模型对压力表进行读表检测 1. 下载项目和数据集 下载项目&#xff1a; git clone https://github.com/zhouayi/pfld.git下载数据集&#xff1a; wget https://github.com/zhouayi/pfld/r…

钢琴模拟器

文章目录 钢琴模拟器代码结构HTML结构CSS样式JavaScript功能 源码效果图 钢琴模拟器 代码结构 HTML结构 <html>: HTML文档的根元素。 <head>: 包含文档的元数据。 <base>: 指定相对URL的基准。 <title>: 指定页面的标题。 <style>: 包含嵌入的…

Linux中进程间通信和理解管道

管道文件为内存及文件&#xff0c;没有名称&#xff08;匿名管道&#xff09; 如何让两个进程看到同一个管道文件&#xff1f; 通过fork创建子进程完成。 匿名管道可以用于父子进程之间的通信。 匿名管道是一个固定大小的缓冲区&#xff0c;写端写满后就会阻塞&#xff0c;…

Python自动发送邮件如何设置邮件内容格式?

Python自动发送邮件时&#xff0c;如何自动化发送HTML格式邮件&#xff1f; Python是一种功能强大且灵活的编程语言&#xff0c;广泛用于各种自动化任务&#xff0c;其中包括自动发送邮件。AokSend将介绍在使用Python自动发送邮件时&#xff0c;如何设置邮件内容的格式&#x…

Mongodb集合操作

文章目录 1、进入容器2、如果数据库不存在&#xff0c;则创建数据库&#xff0c;否则切换到指定数据库3、在 MongoDB 中&#xff0c;创建集合不是必须操作。当你插入一些文档时&#xff0c;MongoDB 会自动创建集合。4、查看数据库列表5、查看集合6、显示创建集合7、删除集合 1、…

创新突破 | OpenCSG发布StarShip CodeReview v1.0.0 Beta版

1. 代码审查很关键但耗时耗力 在软件开发过程中&#xff0c;代码审查是确保代码质量的关键环节。代码审查有助于维护代码标准和发现潜在错误&#xff0c;但也常常耗费大量时间和精力。审查者不仅需要深入理解代码逻辑&#xff0c;还要在繁复的逻辑中识别Bug&#xff0c;这个过…

Python_Flask学习笔记

1.配置 查询字符串的形式传参 app.route(/book/list) def book_list():page request.args.get(page,default1,typeint)return f"您获取的是{page}的图书列表&#xff01;"if __name__ __main__:app.run()3.HTML模版渲染 from flask import Flask,render_templa…

C#知识|对象序列化与反序列化

哈喽,你好啊,我是雷工! 前面练习了将数据存储到TXT文件,今天接着学习对象系列化与XML文件基础的应用, 以下为学习笔记。 01 对象的序列化 序列化是在开发中非常常见的,无论是WinForm开发,还是Web开发都会用得到序列化。 1.1、文本保存对象的缺点 txt文件可以用记事本直…

【p-export-excel】一个轻松实现Excel文件导出的JavaScript插件

p-export-excel&#xff08;github&#xff1a;https://github.com/pbstar/p-export-excel&#xff09;是一个功能强大的JavaScript插件&#xff0c;专门用于导出Excel文件。它支持xlsx和csv两种格式&#xff0c;且提供了丰富的配置选项&#xff0c;允许开发者根据实际需求进行…

贝斯和吉他的区别,怎么打贝斯谱子?一来看看贝斯和吉他的区别,怎么打贝斯谱子的相关内容

在音乐的浩瀚宇宙中&#xff0c;贝斯与吉他作为两大支柱性乐器&#xff0c;虽外观相仿&#xff0c;实则内在差异显著&#xff0c;各自以独特的音色与演奏技法在乐队中发挥着不可或缺的作用。 首先&#xff0c;从音乐功能来看&#xff0c;贝斯以其深沉有力的低音线条&#xff0c…

飞书打卡 快捷指令

使用快捷指令定时飞书打卡 在网上找了一圈&#xff0c;只有钉钉打卡的快捷指令&#xff0c;但是公司换飞书&#xff0c;哪个打工人不怕忘记打卡呢&#xff0c;所以自己研究了一下&#xff0c;其实也很简单。 找url 问题的最关键是打开飞书的打卡界面 如果只是打开飞书APP 很…

iPhone 上的误删的联系人去哪了?如何从 iPhone 上找回联系人的 4 种方法

如果您丢失了所有 iPhone 联系人&#xff0c;那将是一场灾难&#xff0c;因为许多人没有记住电话号码的习惯。iPhone 联系人恢复可以让整个过程变得更容易。如果您仍然对如何在 iPhone 上恢复联系人感到困惑&#xff0c;您可以找到有关 5 个出色解决方案的更多详细信息。只需阅…

C++11 可变参数模板

C11的新特性可变参数模板能够创建可以接受可变参数的函数模板和类模板&#xff0c;相比C98/03&#xff0c;类模版和函数模版中只能含固定数量的模版参数&#xff0c;可变模版参数无疑是一个巨大的改进。然而由于可变模版参数比较抽象&#xff0c;使用起来需要一定的技巧&#x…

书面表达优化助手

大家在写文章时肯定被自己的文章写的不够好而烦恼&#xff0c;但是自己又往往看不出问题在哪里&#xff0c;那么有没有一款工具可以根据自己写的文章&#xff0c;给出一个内容优化建议呢&#xff1f; 下面给大家介绍一下书面表达优化助手&#xff0c;它可以根据你的文章给出一个…

已经10岁的K8S,在很多方面仍需努力

/ K8S 已经 10 岁了&#xff0c;但仍然有许多方面要继续努力 / Kubernetes 于 2014 年 6 月推出&#xff0c;自那时起&#xff0c;它在推广云原生应用设计和支持更多微服务部署方面发挥了巨大作用。容器部署的增长非常迅速&#xff0c;而 Kubernetes 对于企业管理这些部署至关重…