iOS ------ 持久化

news/2024/12/23 3:35:50/

一,数据持久化的目的

1,快速展示,提升体验

  • 已经加载过的数据,用户下次查看时,不需要再次从网络(磁盘)加载,直接展示给用户

2.节省用户流量

  • 对于较大的资源数据进行缓存,下次展示无需下载消耗流量
  • 同时降低了服务器的访问次数,节约服务器资源

3,离线使用

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

4,记录用户操作

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

二,数据持久化方式分类

1,内存缓存

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

内存是指当前程序的运行空间,缓存速度快容量小,是临时存储文件用的,供CPU直接读取。打开一个程序,他是在内存中存储,关闭程序后内存就又回到原来的空闲空间;

  • iOS系统图片加载——[UIImage imageNamed:@“imageName”]
  • 网络图片加载三方库:SDWebImage

2,磁盘缓存

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

磁盘是程序的存储空间,缓存容量大、速度慢、可持久化。与内存不同的是磁盘是永久存储东西的,只要里面存放东西,不管运行不运行 ,他都占用空间。

  • 用户输入内存草稿缓存(评论,文本编辑)
  • 网络图片加载第三方库:SDWebImage
  • 搜索历史缓存

三,缓存策略

硬件的存储设施是有限的,仅能存储有限的数据,但我们需要更高的命中率。就需要缓存算法。

  • FIFO(First in First out)

核心思想:一个数据最先进入缓存中,则应该最早淘汰掉。类似实现一个按照时间先后顺序的队列来管理缓存,将淘汰最早访问的数据缓存。

  • LFU(LeastFrequentlyUsed)

记录用户对数据的访问次数,将访问次数多的数据降序排列在一个容器中,淘汰访问次数最少的数据。

  • LRU(LeastRecentlyUsed)

LRU ,该算法维护一个缓存项队列,队列中的缓存项按每项的最后被访问时间排序。当缓存空间已满时,将处于队尾,即删除最后一次被访问时间距现在最久的项,将新的区段放入队列首部。

  • LRU_K (leastRecentlyUsed)

具体来说它多维护一个队列,记录所有缓存数据被访问的历史。仅当数据的访问次数达到K次的时候,才将数据放入缓存。当需要淘汰数据时,LRU-K会淘汰第K次访问时间距当前时间最大的数据。

  • 2Q (Two queues)

2Q算法类似于LRU-2,不同点在于2Q将LRU-2算法中的访问历史队列(注意这不是缓存数据的)改为一个FIFO缓存队列,即:2Q算法有两个缓存队列,一个是FIFO队列,一个是LRU队列。

  • MQ(Multiu Queue)

MQ算法根据优先级(访问频率)将数据划分为多个LRU队列,其核心思想是:优先缓存访问次数多的数据

四,数据持久化方案

1,内存缓存

实现内存缓存的技术手段包括苹果官方提供的NSURLCacheNSCache,还有性能和API上比较有优势的开源缓存库YYCachePINCache等。

NSCache
  • NSCache是苹果提供的一套缓存机制,用法和NSMutableDictionary类似,在AFNetworkingSDWebImageKingfisher中都有用到。
  • 当内存不足时NSCache会自动释放内存。NSCache设置缓存对象数量和占用的内存大小,当缓存超出了设置会自动释放内存。
  • NSCacheKey-Value数据结构,通过key来获取缓存对象。
  • NSCache中的数据在APP重启后会消失,因为NSCache只是将数据保存在内存的
  • NSCacheNSMutableDictionary的区别:NSCache是线程安全的,不需要加线程锁,而NSMutableDictionary线程不安全。

2,磁盘缓存

NSUserDefault

适合小规模数据,弱业务相关数据的缓存。

keychain

Keychain是苹果提供的带有可逆加密的存储机制,普遍用在各种存用户名、密码的需求上。另外,Keychain是系统级存储,还可以被iCloud同步,即使App被删除,Keychain数据依然保留,用户下次安装App,可以直接读取,通常会用来存储用户唯一标识串。所以需要加密、同步iCloud的敏感小数据,一般使用Keychain存取。

文件存储
  • Plist:一般结构化的数据可以Plist的方式去持久化
  • archive:Archive方式可以存取遵循协议的数据,比较方便的是存取使用的都是对象,不过中间的序列化和反序列化需要花费一定的性能,可以在想要使用对象直接进行磁盘存取时使用。
  • Stream:指文件存储,一般用来存图片、视频文件等数据
数据库存储

数据库适合存取一些关系型的数据;可以在有大量的条件查询排序类需求时使用。

  • Core Data:苹果官方封装的ORM(Object Relational Mapping)
  • FMDB:github最受欢迎的iOS sqlite 封装开源库之一
  • WCDB:微信团队在自己使用的sqlite封装基础上的开源实现,具有ORM(Object Relational Mapping)的特性,支持iOS、Android。
  • Realm:由Y Combinator孵化的创业团队开源出来的一款跨平台(iOS、Android)移动数据库。
FMDB

FMDB是iOS平台的SQLite的数据库框架,以OC的方式封装了SQLite的C语言API。

优点:

  • 使用起来更加面向对象,省去了很多麻烦冗余的C语言代码
  • 对比苹果自带的Core Data框架,更加轻量级和灵活。
  • 提供了多线程安全的数据库操作方法,有效地防止数据混乱。

FMDB有三个主要的类
FMDatabase:一个FMDatabase对象就代表一个单独的SQLite数据库
用来执行SQL语句。
FMResultSet:使用FMDatabase执行查询后的结果集。
FMDatabaseQueue:用于在多线程中执行多个查询或更新,它是线程安全的。

// 建表
NSString *sql = [NSString stringWithFormat:@"CREATE TABLE IF NOT  EXISTS t_test_1 ('%@' INTEGER PRIMARY KEY AUTOINCREMENT,'%@' TEXT NOT NULL, '%@' TEXT NOT NULL, '%@' TEXT NOT NULL, '%@' TEXT NOT NULL, '%@' TEXT NOT NULL, '%@' TEXT NOT NULL, '%@' TEXT NOT NULL, '%@' TEXT NOT NULL, '%@' INTEGER NOT NULL, '%@' FLOAT NOT NULL)", KEY_ID, KEY_MODEL_ID, KEY_MODEL_NAME, KEY_SERIES_ID, KEY_SERIES_NAME, KEY_TITLE, KEY_PRICE, KEY_DEALER_PRICE, KEY_SALES_STATUS, KEY_IS_SELECTED, KEY_DATE];
FMDatabaseQueue *_dbQueue = [FMDatabaseQueue databaseQueueWithPath:@"path"];
[_dbQueue inDatabase:^(FMDatabase *db) {BOOL result = [db executeUpdate:sql];if (result) {//}
}];// 插入一条数据
NSString *insertSql = [NSString stringWithFormat:@"INSERT INTO 't_test_1'(%@,%@,%@,%@,%@,%@,%@,%@,%@,%@) VALUES(\"%@\",\"%@\",\"%@\",\"%@\",\"%@\",\"%@\",\"%@\",\"%@\",%d,%.2f)", KEY_MODEL_ID, KEY_MODEL_NAME, KEY_SERIES_ID, KEY_SERIES_NAME, KEY_TITLE, KEY_PRICE, KEY_DEALER_PRICE, KEY_SALES_STATUS, KEY_IS_SELECTED, KEY_DATE, model.model_id, model.model_name, model.Id, model.Name, model.title, model.price, model.dealer_price, model.sales_status, isSelected,time];
[_dbQueue inDatabase:^(FMDatabase *db) {BOOL result = [db executeUpdate:sql];if (result) {//}
}];// 更新
NSString *sql = @"UPDATE t_userData SET userName = ? , userAge = ? WHERE id = ?";
[_dbQueue inDatabase:^(FMDatabase *db) {BOOL res = [db executeUpdate:sql,_nameTxteField.text,_ageTxteField.text,_userId];if (result) {//}
}];// 删除
NSString *str = [NSString stringWithFormat:@"DELETE FROM t_userData WHERE id = %ld",userid];
[_dbQueue inDatabase:^(FMDatabase *db) {BOOL res = [db executeUpdate:str];if (res) {//}
}];// 查找
[_dbQueue inDatabase:^(FMDatabase *db) {FMResultSet *resultSet = [db executeQuery:@"SELECT * FROM message"];NSMutableArray<Message *> *messages = [[NSMutableArray alloc] init];while ([resultSet next]) {Message *message = [[Message alloc] init];message.localID = [resultSet intForColumnIndex:0];message.content = [resultSet stringForColumnIndex:1];message.createTime = [NSDate dateWithTimeIntervalSince1970:[resultSet doubleForColumnIndex:2]];message.modifiedTime = [NSDate dateWithTimeIntervalSince1970:[resultSet doubleForColumnIndex:3]];[messages addObject:message];}
}];

沙盒储存

沙盒:iOS中每个应用程序都有一个独立的文件夹,这个文件夹就是沙盒。沙盒用来存储app的本地文件,例如:音频、视频、图片文件等。并且每个app的沙盒都是独立的,即当前app没有权限访问其他app的沙盒,所以说沙盒存储较之更安全。

沙盒的层次结构

获取沙盒根目录

NSString *directory = NSHomeDirectory();NSLog(@"directory:%@", directory);

打印结果

/Users/fuchuang/Library/Developer/CoreSimulator/Devices/021352E7-E025-419B-9045-0BA88DD4BE35/data/Containers/Data/Application/3A470BFA-2A06-44E3-879C-34B13DB37A39

获取路径

在这里插入图片描述

  • Documents:保存应用运行的时生成的需要持久化的数据,会被自动备份在iCloud中。
    一般我们在项目中,我们会把一些用户的登录信息以及搜索历史记录等一些关键数据存储到这里。
  • Library:默认存放设置和其他状态信息,除了caches子目录之外其他目录都会被iclude同步。
    • Application Support:此目录包含应用程序用来运行但应对用户隐藏的文件,如游戏的新关卡等文件。
    • Caches:目录用于存储应用程序的缓存数据,比如下载的文件、图像缓存、网络请求缓存等。这些数据可以在应用程序的后续运行中快速访问,以提高性能和用户体验。iOS 系统可能会在设备存储空间紧张时清理 Caches 目录中的文件。Caches 目录中的文件不会被备份到 iCloud,因此适合存储可以重新生成或重新下载的数据
    • Cooikes:系统会自动将App中网络请求的cookie保存为文件。
    • Preferences:保存应用的所有偏好设置。UserDefaults 生成的 plist 文件就会保存该目录下。
    • SplashBoard:存储启动屏缓存,缓存文件格式为 ktx,本质上就是图片,如果启动屏不生效的问题可以考虑从删除该路径下相关缓存文件这个角度解决。
  • SystemData:存放系统数据,无对外暴露的接口。
  • tmp:临时文件夹(系统会不定期删除里面的文件)。

http://www.ppmy.cn/news/1503561.html

相关文章

GitHub 详解教程

1. 引言 GitHub 是一个用于版本控制和协作的代码托管平台&#xff0c;基于 Git 构建。它提供了强大的功能&#xff0c;使开发者可以轻松管理代码、追踪问题、进行代码审查和协作开发。 2. Git 与 GitHub 的区别 Git 是一个分布式版本控制系统&#xff0c;用于跟踪文件的更改…

cf168(div2):D.Maximize the Root(树)

题目 给你一棵有根的树&#xff0c;由 &#x1d45b;n 个顶点组成。树中的顶点编号为 11 至 &#x1d45b;n &#xff0c;根顶点为 11 。值 &#x1d44e;&#x1d456;ai 写在第 &#x1d456;i 个顶点上。 您可以执行以下任意次数(可能为零)的操作&#xff1a;选择一个顶点…

黑马JavaWeb后端案例开发(包含所有知识点!!!)

目录 1.准备工作 环境搭建 开发规范 REST&#xff08;REpresentation State Transfer&#xff09;,表述性状态转换&#xff0c;它是一种软件架构风格 注意事项 统一响应结果 2.部门管理功能 查询部门 删除部门 新增部门 RequestMapping 3.员工管理功能 分页查询 批…

『 Linux 』基于阻塞队列的生产者消费者模型

文章目录 生产者-消费者模型概述生产者消费者模型的高效性虚假唤醒信号丢失生产者消费者模型的模拟实现参考代码 生产者-消费者模型概述 生产者消费者模型是一种多线程设计模式,常见于解决多个生产者线程和多个消费者线程之间如何安全有效地共享数据; 该模型中存在三种关系,两个…

传统自然语言处理(NLP)与大规模语言模型(LLM)详解

自然语言处理&#xff08;NLP&#xff09;和大规模语言模型&#xff08;LLM&#xff09;是理解和生成人类语言的两种主要方法。本文将介绍传统NLP和LLM的介绍、运行步骤以及它们之间的比较&#xff0c;帮助新手了解这两个领域的基础知识。 传统自然语言处理&#xff08;NLP&…

JavaScript异步编程的Promise

目录 1.对Promise的了解 &#xff08;1&#xff09;介绍 &#xff08;2&#xff09;Promise 的优缺点 2.Promise的基本用法 &#xff08;1&#xff09;创建Promise对象 &#xff08;2&#xff09;Promise方法then() &#xff08;3&#xff09;Promise方法catch() &…

C语言实现三子棋

通过一段时间的学习&#xff0c;我们已经能够较为熟练地使用分支语句&#xff0c;循环语句&#xff0c;创建函数&#xff0c;创建数组&#xff0c;创建随机数等。之前我们做过一个扫雷游戏&#xff0c;今天让我们再尝试创作一个三子棋游戏吧~ 一、三子棋游戏的思路 三子棋的游…

语音交互、AI问答,等你来体验!

功能背景 在实际大屏应用中&#xff0c;用户向大屏直接下达语音指令显的越来越便捷&#xff0c;其中体现的交互感也比通过动作指令来的更加强烈&#xff0c;给用户带来更高效的服务体验。目前EasyV平台开发的自定义事件交互已经很完善&#xff0c;组件之间可以进行触发联动。 …