美文网首页
iOS开发-Realm数据库(单表)

iOS开发-Realm数据库(单表)

作者: 余鹤龄 | 来源:发表于2020-08-13 09:25 被阅读0次

Realm

Realm-Object-c,见:

https://realm.io/cn/docs/objc/latest/

Realm官网:

https://realm.io

使用流程

导入头文件#import < Realm/Realm.h >.

创建类,继承于RLMObject.

在类中生成数据模型.

在需要的地方创建实例,使用Realm方法调用.

数据模型

创建简单数据模型

简单地,继承RLMObject创建类,在.h中通过属性定义不同的内容.

RLMResults <0x7fe5e3d22ec0>(    [0]Data {time=2016-01-0805:51:12+0000;title= test;    })

生成如上的数据结构,只需创建类如下:

// .h#import <Realm/Realm.h>

@interfaceData:RLMObject

@property(nonatomic,strong)NSDate*time;

@property(nonatomic,copy)NSString*title;

@end// .m

#import "Data.h"

@implementationData

@end

生成主键(Primary Keys)

重写 +primaryKey 可以设置模型的主键。声明主键之后,对象将被允许查询,更新速度更加高效,并且要求每个对象保持唯一性。 一旦带有主键的对象被添加到 Realm 之后,该对象的主键将不可修改。

@interfacePerson:RLMObject

@propertyNSIntegerid;@propertyNSString*name;

@end

@implementationPerson

+ (NSString*)primaryKey {return@"id";}

@end

忽略属性(Ignored Properties)

重写 +ignoredProperties 可以防止 Realm 存储数据模型的某个属性。Realm 将不会干涉这些属性的常规操作,它们将由成员变量(ivar)提供支持,并且您能够轻易重写它们的 setter 和 getter。

@interfacePerson : RLMObject

@propertyNSInteger tmpID;

@property(readonly) NSString *name;// 只读属性将被自动忽略

@propertyNSString *firstName;

@propertyNSString *lastName;

@end

@implementation Person

+ (NSArray *)ignoredProperties 

{

return@[@"tmpID"];

}

-(NSString *)name

{return[NSString stringWithFormat:@"%@ %@", self.firstName, self.lastName];}

@end

属性默认值

重写+defaultPropertyValues可以在每次对象创建之后为其提供默认值。

@interfaceBook:RLMObject

@propertyfloatprice;

@propertyNSString*title;

@end

@implementation Book

+ (NSDictionary*)defaultPropertyValues

 {return@{@"price": @0,@"title":@""};}

@end

创建嵌套数据模型

数据结构:Person具有name、birthdate、dogs,Dog具有name、owner< Person >。

RLMResults<0x7fb431f2bd60>(    [0] Person {        name = crylown;birthdate =2016-01-0806:02:23 +0000;        dogs = RLMArray<0x7fb431f2fcd0>(            [0] Dog {                name = myDog;                owner = Person {                    name = crylown;birthdate =2016-01-0806:02:23 +0000;                    dogs =;                };            },            [1] Dog {                name = yourDog;                owner = Person {                    name = crylown;birthdate =2016-01-0806:02:23 +0000;                    dogs =;                };            }        );

    }

)

生成如上的数据结构,创建数据模型代码如下:

// .h#import <Realm/Realm.h>@classPerson;// 狗狗的数据模型@interfaceDog:RLMObject@propertyNSString*name;@propertyPerson  *owner;@endRLM_ARRAY_TYPE(Dog)// 定义RLMArray<Dog>// 狗狗主人的数据模型@interfacePerson:RLMObject

@propertyNSString*name;

@propertyNSDate*birthdate;// 通过RLMArray建立关系

@propertyRLMArray *dogs;

@end

RLM_ARRAY_TYPE(Person)// 定义RLMArray<Person>// .m

@implementation Dog

@end// 暂无使用

@implementation Person

@end// 暂无使用

使用Realm数据模型

创建对象

一般属性

Data*data= [[Dataalloc] init];data.time = [NSDatedateWithTimeIntervalSinceNow:0];data.title = @"test";

等价于

//字典Data *data = [[Data alloc]initWithValue:@{@"time":[NSDatedateWithTimeIntervalSinceNow:0],@"title":@"test"}];

等价于

//数组Data *data = [[Data alloc]initWithValue:@[[NSDatedateWithTimeIntervalSinceNow:0],@"test"]];

嵌套属性

Person *me =[[Person alloc]init];Dog *myDog =[[Dog alloc]init];myDog.name = @"myDog";myDog.owner = me;Dog *yourDog =[[Dog alloc]init];yourDog.name = @"yourDog";yourDog.owner = me;me.name = @"crylown";me.birthdate =[NSDate dateWithTimeIntervalSinceNow:1];// 将dog添加到 dogs属性中[me.dogs addObject:myDog];[me.dogs addObject:yourDog];

等价于

Dog *myDog =[[Dog alloc]init];myDog.name = @"myDog";Dog *yourDog =[[Dog alloc]init];yourDog.name = @"yourDog";Person *me =[[Person alloc]initWithValue:@[@"crylown",[NSDate dateWithTimeIntervalSinceNow:1],@[myDog,yourDog]]];yourDog.owner = me;myDog.owner = me;

等价于

// 多重嵌套// dog.owner无法在这里设置Person *me = [[Person alloc]initWithValue:@[@"crylown",[NSDatedateWithTimeIntervalSinceNow:1],@[@[@"myDog"],@[@"yourDog"]]]];

使用Realm进行数据管理

在数据管理的过程中,常用的方法有:

RLMRealm *realm = [RLMRealm defaultRealm];// 开放RLMRealm事务[realm beginWriteTransaction];// 在开放开放/提交事务之间进行数据处理// 提交事务[realm commitWriteTransaction];

等价于

[realm transactionWithBlock:^{

// 进行数据处理

}];

添加数据

RLMRealm *realm =[RLMRealm defaultRealm];//    开放RLMRealm事务[realm beginWriteTransaction];//    添加到数据库 me为RLMObject[realm addObject:me];//    提交事务[realm commitWriteTransaction];

查询数据

数据库查询

// 查询默认的 Realm 数据库RLMResults *dogs = [Dog allObjects];// 从默认的 Realm 数据库中,检索所有狗狗

如果有需要,也可以查询指定的数据库

// 查询指定的 Realm 数据库RLMRealm *petsRealm = [RLMRealmrealmWithPath:@"pets.realm"];// 获得一个指定的 Realm 数据库RLMResults *otherDogs = [DogallObjectsInRealm:petsRealm];// 从该 Realm 数据库中,检索所有狗狗

条件查询

1.使用断言字符串查询:

RLMResults*tanDogs = [Dog objectsWhere:@"color = '棕黄色' AND name BEGINSWITH '大'"];

2.// 使用 NSPredicate 查询

NSPredicate *pred = [NSPredicatepredicateWithFormat:@"color = %@ AND name BEGINSWITH %@",                                                @"棕黄色", @"大"];RLMResults *tanDogs = [DogobjectsWithPredicate:pred];

3.链式查询

如果我们想获得获得棕黄色狗狗的查询结果,并且在这个查询结果的基础上再获得名字以“大”开头的棕黄色狗狗。

RLMResults *tanDogs = [DogobjectsWhere:@"color = '棕黄色'"];RLMResults *tanDogsWithBNames = [tanDogsobjectsWhere:@"name BEGINSWITH '大'"];

修改数据

内容直接更新

// author为数据库内RLMObject[realm beginWriteTransaction];author.name = @"托马斯·品钦";[realm commitWriteTransaction];

根据主键更新

如果您的数据模型中设置了主键的话,那么您可以使用+[RLMObject createOrUpdateInRealm:withValue:]来更新对象,或者当对象不存在时插入新的对象。

// 创建一个带有主键的“书籍”对象,作为事先存储的书籍Book *cheeseBook = [[Book alloc] init];cheeseBook.title =@"奶酪食谱";cheeseBook.price = @9000;cheeseBook.id = @1;// 通过 id = 1 更新该书籍[realm beginWriteTransaction];[Book createOrUpdateInRealm:realm withValue:cheeseBook];[realm commitWriteTransaction];

键值编码

RLMObject、RLMResult 以及 RLMArray 都遵守键值编码(Key-Value Coding)(KVC)机制。

RLMResults *persons = [Person allObjects];[[RLMRealm defaultRealm]transactionWithBlock:^{  [[persons firstObject]setValue:@YESforKeyPath:@"isFirst"];// 将每个人的 planet 属性设置为“地球”[personssetValue:@"地球"forKeyPath:@"planet"];}];

删除数据

删除某个在Realm数据库中的数据。

Book *cheeseBook = ...// 存储在 Realm 中的 Book 对象// 在事务中删除一个对象[realm beginWriteTransaction];[realm deleteObject:cheeseBook];[realm commitWriteTransaction];

删除数据库中的所有数据。

// 从 Realm 中删除所有数据[realm beginWriteTransaction];[realm deleteAllObjects];[realm commitWriteTransaction];

数据排序

RLMResults 允许您指定一个排序标准,从而可以根据一个或多个属性进行排序。比如说,下列代码将上面例子中返回的狗狗根据名字升序进行排序:

// 排序名字以“大”开头的棕黄色狗狗RLMResults *sortedDogs = [[DogobjectsWhere:@"color = '棕黄色' AND name BEGINSWITH '大'"]                        sortedResultsUsingProperty:@"name"ascending:YES];

数据库配置

一般地,我们使用的为默认的Realm数据库,即调用[RLMRealm defaultRealm]来初始化以及访问我们的realm变量。这个方法将会返回一个 RLMRealm对象,并指向您应用的 Documents (iOS) 或者 Application Support (OS X)文件夹下的一个名为“default.realm”的文件。

许多 Realm API 中的方法都支持两种默认的数据库访问方式,一种是RLMRealm实例,另一种是访问默认 Realm 数据库的便捷版本。例如 [RLMObject allObjects] 等同于 [RLMObject allObjectsInRealm:[RLMRealm defaultRealm]]。

Realm配置

通过RLMRealmConfiguration您可以配置诸如 Realm 文件在何处存储之类的信息。

配置同时也可以在每次您需要使用 Realm 实例的时候传递给[RLMRealm realmWithConfiguration:config error:&err],或者您也可以通过 [RLMRealmConfiguration setDefaultConfiguration:config] 来为默认的 Realm 数据库进行配置。

比如说,假设有这样一个应用,用户必须登录到您的网站后台才能够使用,然后您希望这个应用支持快速帐号切换功能。 您可以为每个帐号创建一个特有的 Realm 文件,通过对默认配置进行更改,就可以直接使用默认的 Realm 数据库来直接访问了,如下所示:

+ (void)setDefaultRealmForUser:(NSString *)username {  

RLMRealmConfiguration *config= [RLMRealmConfiguration defaultConfiguration];// 使用默认的目录,但是使用用户名来替换默认的文件名

config.path= [[[config.pathstringByDeletingLastPathComponent]     stringByAppendingPathComponent:username]                  stringByAppendingPathExtension:@"realm"];

// 将这个配置应用到默认的 Realm 数据库当中[RLMRealmConfiguration setDefaultConfiguration:config];}

其他的Realm数据库

有的时候,在不同位置存储多个 Realm 数据库是十分有用的。 例如,如果您需要将您应用的某些数据打包到一个 Realm 文件中,作为主要 Realm 数据库的扩展。 您可以像以下代码这样做:

RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];// 获取需要打包文件的路径config.path = [[NSBundle mainBundle]pathForResource:@"MyBundledData"ofType:@"realm"];// 以只读模式打开文件,因为应用数据包并不可写config.readOnly = YES;// 通过配置打开 Realm 数据库RLMRealm *realm = [RLMRealmrealmWithConfiguration:config];// 从打包的 Realm 数据库中读取某些数据RLMResults *dogs = [DogobjectsInRealm:realmwhere:@"age > 5"];

请注意,使用自定义路径来初始化 Realm 数据库需要拥有路径所在位置的写入权限。 通常存储可写 Realm 文件的地方是位于 iOS 上的“Documents”文件夹以及位于 OS X 上的“Application Support”文件夹。 具体情况,请遵循苹果的 iOS 数据存储指南, 它推荐将文件存储在<Application_Home>/Library/Caches目录下

错误处理

在数据的处理中可能会出现失败的情况,在查看错误的时候,有相关方法可以使用:

提交事务失败

[realm commitWriteTransaction:(NSError* _Nullable __autoreleasing * _Nullable)]

也可以使用

[realm transactionWithBlock:^{

}error:(NSError* _Nullable __autoreleasing * _Nullable)]

配置数据库失败

RLMRealm*realm = [RLMRealm realmWithConfiguration:configerror:&error];

要处理在指定线程中初次 Realm 数据库导致的错误, 给 error 参数提供一个 NSError 指针。

数据迁移

当您使用任意一个数据库时,您随时都可能打算修改您的数据模型。通过设置 RLMRealmConfiguration.schemaVersion 以及RLMRealmConfiguration.migrationBlock 可以定义一个迁移操作以及与之关联的架构版本。 迁移闭包将会提供提供相应的逻辑操作,以让数据模型从之前的架构转换到新的架构中来。 每当通过配置创建完一个 RLMRealm 之后,迁移闭包将会在迁移需要的时候,将给定的架构版本应用到更新 RLMRealm 操作中。

如下所示是最简单的数据迁移的必需流程:

// 在 [AppDelegate didFinishLaunchingWithOptions:] 中进行配置RLMRealmConfiguration *config= [RLMRealmConfiguration defaultConfiguration];

// 设置新的架构版本。这个版本号必须高于之前所用的版本号(如果您之前从未设置过架构版本,那么这个版本号设置为 0)config.schemaVersion=1;

// 设置闭包,这个闭包将会在打开低于上面所设置版本号的 Realm 数据库的时候被自动调用config.migrationBlock= ^(RLMMigration *migration, uint64_t oldSchemaVersion) {

// 目前我们还未进行数据迁移,因此 oldSchemaVersion == 0if(oldSchemaVersion <1) {

// 什么都不要做!Realm 会自行检测新增和需要移除的属性,然后自动更新硬盘上的数据库架构}};

// 告诉 Realm 为默认的 Realm 数据库使用这个新的配置对象[RLMRealmConfiguration setDefaultConfiguration:config];

// 现在我们已经告诉了 Realm 如何处理架构的变化,打开文件之后将会自动执行迁移[RLMRealm defaultRealm];

相关文章

网友评论

      本文标题:iOS开发-Realm数据库(单表)

      本文链接:https://www.haomeiwen.com/subject/mylpdktx.html