iOS 数据持久化方案-Realm的使用(上)

简介: iOS 数据持久化方案-Realm的使用(上)

总体内容

1、Realm介绍

2、使用教程与辅助工具

3、Realm的具体使用


一、Realm介绍



  • 1.1、Realm 是一个跨平台移动数据库引擎,支持iOSOS XObjective-CSwift)以及Android,核心数据引擎C++打造,并不是建立在SQLite之上的ORM, 是拥有独立的数据库存储引擎,具体详情


ORM:对象-关系映射(OBJECT/RELATIONALMAPPING,简称ORM),ORM技术是在对象和关系之间提供了一条桥梁。


  • 1.2、Realm性能:sqlite, coredata牛逼
  • 1.3、Realm使用方面:相比于sqlite, coredata, 使用起来更加简单, 更易入门


二、使用教程与辅助工具




image.png


,打开后等待一下会自动转化为中文界面

在上面的教程里面我们可以看到有很多语言,我们关注的是 SwiftOC,导入Realm方式如下:


  • 导入方式一:CocoaPods 导入


  • Swift


pod 'RealmSwift'
  • OC


pod 'Realm'


建议在终端运行 pod repo update以使CocoaPods最新的Realm版本。

  • pod install 失败解决方法:
  • 首次(或者安装新版本)pod realm的时候,会下载sync-cocoa文件,这个文件有点大,所以pod install会很慢,且因身居404之内,所以易失败。手动下载可以加速 pod install
  • 这里以10.2.1 版本为例: pod 'RealmSwift', '10.2.1', 把 v10.2.0 替换为你对应realm的版本号即可:https://github.com/realm/realm-cocoa/blob/v10.2.0/dependencies.list


image.png



  • 下面的 10.1.3 是上图的对应的:REALM_SYNC_VERSION


curl https://static.realm.io/downloads/core/realm-core-10.1.3.tar.bz2 -o realm-core-10.1.3.tar.bz2
mkdir $TMPDIR/core_bin
mv realm-core-10.1.3.tar.bz2 $TMPDIR/core_bin
  • 然后进入项目,执行 pod install


  • 导入方式二:手动导入,步骤如下


根据自己的需要选择相应的 Realm.framework


  • <2>、前往 Xcode 工程的 “General” 设置选项卡中,从 ios/dynamic/osx/tvos/ 或者 watchos/ 目录中,将 Realm.framework 拖曳到 “Embedded Binaries” 部分内。请确保勾选了 Copy items if needed(除非项目中有多个平台都需要使用 Realm ),然后单击 Finish按钮;


提示:在把 Realm.framework拖进项目后一定要在 TARGET->General->Embedded Binaries里面把这 Realm.framework添加进来,否则运行会崩溃


image.png

  • <3>、在单元测试目标的 “Build Settings” 中,将 Realm.framework 的父目录添加到 “Framework Search Paths” 部分中;


提示这一步一般在你把 Realm.framework 拖进项目就会自动完成


  • <4>、如果使用了 Realm Swift,请将 Swift/RLMSupport.swift 文件拖曳到 Xcode 工程的文件导航栏中,请确保选中了 Copy items if needed 选择框;
  • <5>、如果在 iOS、watchOS 或者 tvOS 工程中使用 Realm,请在应用目标的 “Build Phases” 中创建一条新的 “Run Script Phase”,然后将下面这段代码粘贴到脚本文本框内:


bash "${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}/Realm.framework/strip-frameworks.sh"


添加后的效果:


image.png


  • 2.2、Realm 辅助工具


  • <1>、Realm Browser: 可视化访问 Realm 数据库,与SqliteManger 打开 Sqlite数据库一样,Realm Browser 用来打开 Realm 数据库



image.png

<2>、Realm在xcode里面使用的插件Alcatraz(有点大),它 可以快速创建Realm可存储模型对象


image.png


下载后,打开运行一下


image.png

查看是否插件安装成功,创建一个类,滚到最下面看是否有如下图所示


image.png


三、Realm的具体使用,Demo



3.1、简单的数据操作:使用 RLMRealm 对象, 保存指定模型


(1)、创建一个模型 Student继承于 RLMObject,看准了不是继承于 NSObject,如果在 2.2 里面安装了插件并运行后,插件生效,就可以快速创建 Realm的model了,如下图


image.png

  • (2)、在Student类里面定义属性:由于Realm 在自己的引擎内部有很好的语义解释系统,所以 Objective‑C 的许多属性特性将被忽略,如nonatomic, atomic, strong, copy 和 weak 等。 因此为了避免误解,官方推荐在编写数据模型的时候不要使用任何的属性特性。


/** 学生的唯一ID */
@property int studentId;
/** 学生的名字 */
@property NSString *studentName;
  • (3)、创建对象的方式
  • 方式一:普通创建


Student *student = [[Student alloc]init];
student.studentId = @1;
student.studentName = @"小王";
  • 方式二:通过父类 RLMObject 中的方法 initWithValue 快速创建,可以放字典,也可以放数组,如下


// 数组
Student *student = [[Student alloc]initWithValue:@[@2,@"小冯"];
// 字典
Student *student = [[Student alloc]initWithValue:@{@"studentId":@2,@"studentName":@"小冯"}];


提示:数组要与 model 里面的属性顺序保持一致,放字典的话键值保持一致

注意:所有的必需属性都必须在对象添加到 Realm 前被赋值


  • (4)、使用 RLMRealm 对象, 保存指定模型,如下,我们采用 initWithValue 快速创建并保存


// 获取RLMRealm对象
RLMRealm *realm = [RLMRealm defaultRealm];
// 创建对象
Student *student = [[Student alloc]initWithValue:@{@"studentId":@2,@"studentName":@"小冯"}];
  • 保存模型方式一:开启事务,写入数据,关闭事务


// 开启事务
[realm beginWriteTransaction];
// 写入数据
[realm addObject:student];
// 关闭事务
[realm commitWriteTransaction];
  • 保存模型方式二:使用 block


[realm transactionWithBlock:^{
    [realm addObject:student];
}];
  • 保存模型方式三


[realm transactionWithBlock:^{
   [Student createInRealm:realm withValue:@{@"studentId": @3, @"studentName": @"王小二"}];
}];


提示:所有的必需属性都必须在对象添加到 Realm 前被赋值,并且使用 Realm 对象写入值保存模型

  • 还可以开启线程来保存模型


  • 3.2、使用 RLMRealm 对象, 更新指定模型
  • 更新模型方式一:在事务中直接更新对象


Student *student = [[Student alloc]initWithValue:@{@"studentId":@3,@"studentName":@"王小二"}];
RLMRealm *realm = [RLMRealm defaultRealm];
// 保存模型
[realm transactionWithBlock:^{
    // 写入数据
    [realm addObject:student];
}];
// 更新模型:这里的更新模型一定是被realm所管理的模型
[realm transactionWithBlock:^{
    // 写入数据
    student.studentName = @"王冲";
}];


提示:上面的 student 已经被 realm 所管理,而且已经和磁盘上的对象进行地址映射

  • 更新模型一定是被 realm 所管理的模


  • 更新模型方式二根据 主键 进行更新
  • (1)、上面的Student我们还没有设置主键,现在在 Student.m 里面设置一下 主键


/** 设置主键 */
+(NSString *)primaryKey{
     return @"studentId";
}
  • (2)、在事务中调用方法:[realm addOrUpdateObject:stu2];,如下


Student *student = [[Student alloc]initWithValue:@{@"studentId":@3,@"studentName":@"王小二"}];
RLMRealm *realm = [RLMRealm defaultRealm];
// 在事务里面做处理
[realm transactionWithBlock:^{
     // 根据主键更新模型
     [realm addOrUpdateObject:student];
}];


  • 更新模型方式三也是根据 主键 进行更新
  • (1)、设置主键和上面的一样
  • (2)、在事务中调用方法:[模型类名 createOrUpdateInRealm:realm withValue:值];,举例如下:


RLMRealm *realm = [RLMRealm defaultRealm];
[realm transactionWithBlock:^{
      [Student createOrUpdateInRealm:realm withValue:@{@"studentId":@3,@"studentName":@"二蛋子"}];
}];


提示:withValue:后面还可以跟数组,但是传值要和模型里面属性的顺序一致,如:[Student createOrUpdateInRealm:realm withValue:@[@3,@"二蛋子"]]; }];


  • 3.3、Realm 删除模型数据 :删除的模型一定是 realm 所管理的
  • 分析:我们要删除模型,首先要获取模型,不能是我们自己创建出来的模型,必须是从 realm 数据库里面获取出来的模型,如下:
  • (1)、根据主键获取模型(结果只能是一个或者没有,所以直接用查询的模型接收)


Student *student = [Student objectForPrimaryKey:@2];
  • (2)、通过sql 语句查询模型:因为根据名字查询的结果可能多个模型,采用 RLMResults 结果数组接收


RLMResults *results2 = [Student objectsWhere:@"studentName = '二傻'"];
  • 删除方式一:删除单个模型


// 根据主键获取模型
Student *student = [Student objectForPrimaryKey:@2];
RLMRealm *realm = [RLMRealm defaultRealm];
// 删除单个模型
[realm transactionWithBlock:^{
   [realm deleteObject:student];
}];
  • 删除方式二:通过sql 语句查询模型:因为根据名字查询的结果可能多个模型


// 通过sql 语句查询模型:因为根据名字查询的结果可能多个模型
RLMResults *results2 = [Student objectsWhere:@"studentName = '二傻'"];
RLMRealm *realm = [RLMRealm defaultRealm];
// 删除查询出来的 模型 数组
[realm transactionWithBlock:^{
     [realm deleteObjects:results2];
}];

当然你可以可以对 RLMResults 进行遍历删除或者for循环逐个删除,但是上面的删除还是挺方便的,Realm 内部做了遍历删除


  • 删除方式三:删除某一特定类型的模型所有数据,如删除 Student 模型的所有数据


// 获取 Student 模型的所有数据
RLMResults *results = [Student allObjects];
RLMRealm *realm = [RLMRealm defaultRealm];
// 在事务里面删除模型里面的所有数据
[realm transactionWithBlock:^{
    [realm deleteObjects:results];
}];
  • 删除方式四: 删除 Realm 里面所有的模型数据(比如删除 Student、Dog 模型等等,全部数据删除)


RLMRealm *realm = [RLMRealm defaultRealm];
[realm transactionWithBlock:^{
    [realm deleteAllObjects];
}];

提示:删除的操作一定要放到 事务里面,我一般采用block的事务方式,当然你可以选择其他的方式,如上面 3.1 中的 (4)


  • 3.4、 使用 RLMRealm 对象, 查询数据
  • (1)、注意事项
  • 所有的查询(包括查询和属性访问)在 Realm 中都是延迟加载的,只有当属性被访问时,才能够读取相应的数据。


解释:当我们在获取一个查询 RLMResults *results = [Student allObjects]; 时,并没有读取到数据,当真正的操作数据的属性的时候才能够读取相应的数据。


  • 查询结果并不是数据的拷贝:修改查询结果(在写入事务中)会直接修改硬盘上的数据。


解释:在我们查询一个模型后,所获取的数据不是拷贝出来的,而是直接操控数据库的


  • 一旦检索执行之后, RLMResults 将随时保持更新


解释:在下面代码中第一次打印 results会把数据库中的结果打印出来,当添加一个数据后,再次打印会把添加的数据和之前的数据都会打印出来,这就是所谓的:一旦检索执行之后, RLMResults 将随时保持更新



RLMResults *results = [Student allObjects];
NSLog(@"第 1 次打印结果:%@",results);
Student *student = [[Student alloc]initWithValue:@{@"studentId":@1,@"studentName":@"小王"}];
RLMRealm *realm = [RLMRealm defaultRealm];
[realm transactionWithBlock:^{
     [realm addObject:student];
}];
NSLog(@"第 2 次打印结果:%@",results);
  • (2)、查询方式一:查询某一个模型的查询所有内容


RLMResults *results = [Student allObjects];
NSLog(@"打印结果:%@",results);
  • (3)、查询方式二:条件查询(可以编辑自己需要的sql语句),更多的sql语句可以参考的的 Mysql的笔记,里面有更多的 sql 查询语句


RLMResults<Student *> *students = [Student objectsWhere:@"studentName = '小王'"];
NSLog(@"打印结果:%@",students);
  • (4)、查询方式三:对查询结果排序


RLMResults<Student *> *students = [Student allObjects];
NSLog(@"没有排序的结果:%@",students);
RLMResults *soreStudents = [students sortedResultsUsingKeyPath:@"studentId" ascending:YES];
NSLog(@"排序后的结果:%@",soreStudents);



image.pngimage.png

image.png

目录
相关文章
|
3月前
|
测试技术 Linux 虚拟化
iOS自动化测试方案(五):保姆级VMware虚拟机安装MacOS
详细的VMware虚拟机安装macOS Big Sur的保姆级教程,包括下载VMware和macOS镜像、图解安装步骤和遇到问题时的解决方案,旨在帮助读者顺利搭建macOS虚拟机环境。
136 3
iOS自动化测试方案(五):保姆级VMware虚拟机安装MacOS
|
3月前
|
测试技术 开发工具 iOS开发
iOS自动化测试方案(三):WDA+iOS自动化测试解决方案
这篇文章是iOS自动化测试方案的第三部分,介绍了在没有MacOS系统条件下,如何使用WDA(WebDriverAgent)结合Python客户端库facebook-wda和tidevice工具,在Windows系统上实现iOS应用的自动化测试,包括环境准备、问题解决和扩展应用的详细步骤。
253 1
iOS自动化测试方案(三):WDA+iOS自动化测试解决方案
|
3月前
|
测试技术 数据安全/隐私保护 iOS开发
iOS自动化测试方案(四):保姆级搭建iOS自动化开发环境
iOS自动化测试方案的第四部分,涵盖了基础环境准备、iPhone虚拟机设置、MacOS虚拟机与iPhone真机的连接,以及扩展问题和代码示例,确保读者能够顺利完成环境搭建并进行iOS自动化测试。
260 0
iOS自动化测试方案(四):保姆级搭建iOS自动化开发环境
|
3月前
|
测试技术 虚拟化 iOS开发
iOS自动化测试方案(二):Xcode开发者工具构建WDA应用到iphone
这篇文章是iOS自动化测试方案的第二部分,详细介绍了在Xcode开发者工具中构建WebDriverAgent(WDA)应用到iPhone的全过程,包括环境准备、解决构建过程中可能遇到的错误,以及最终成功安装WDA到设备的方法。
182 0
iOS自动化测试方案(二):Xcode开发者工具构建WDA应用到iphone
|
3月前
|
测试技术 开发工具 虚拟化
iOS自动化测试方案(一):MacOS虚拟机保姆级安装Xcode教程
这篇文章提供了一份保姆级的教程,指导如何在MacOS虚拟机上安装Xcode,包括环境准备、基础软件安装以及USB扩展插件的使用,以实现iOS自动化测试方案的第一步。
117 0
iOS自动化测试方案(一):MacOS虚拟机保姆级安装Xcode教程
|
3月前
|
iOS开发 开发者
iOS平台RTMP|RTSP播放器如何实时回调YUV数据
我们在做RTMP、RTSP播放器的时候,有开发者需要自己处理拉取到的YUV数据,做二次分析之用,为此,我们做了以下的设计:InitPlayer之后,再调用SmartPlayerStart()接口之前,设置yuv数据回调即可。
|
6月前
|
移动开发 安全 数据安全/隐私保护
ios安全加固 ios 加固方案
ios安全加固 ios 加固方案
89 1
ios安全加固 ios 加固方案
|
6月前
|
Java iOS开发
iOS的数据序列化(又称持久化)的两类使用方式
iOS的数据序列化(又称持久化)的两类使用方式
65 0
|
6月前
|
移动开发 小程序 API
uniapp通过蓝牙传输数据 (ios)
uniapp通过蓝牙传输数据 (ios)
319 1
|
6月前
|
安全 数据安全/隐私保护 虚拟化
iOS应用加固方案解析:ipa加固安全技术全面评测
iOS应用加固方案解析:ipa加固安全技术全面评测
121 3