realm简单操作介绍

realm是跨平台开发,使用C++编写,并是不对sqlite的封装,是有独立的数据库存储引擎.比sqlite和coredate性能还好.
官网介绍的realm支持的数据类型

1-4.png

说明:为方便测试,这里我使用Xcode自带的单元测试来操作.
准备工作:
1.去官网下载realm,我这里选择的是realm-Objc
2.下载realm-objc安装包,打开realm-objc-2.9.1-->plugin-->RealmPlugin,安装realm的插件.直接编译运行即可,安装完成后即有个realm的模型
1-1.png

realm简单使用步骤
1.新建一个工程,通过cocoapods方式继承到项目中.
首次安装时间可能久点,看到以下信息代表安装成功

Sending stats
      - Realm, 3.0.0-beta.2

-> Pod installation complete! There is 1 dependency from the Podfile and 1 total pod installed.

2创建单元测试模块

1-2.png

这里我们直接在RealmDemoTests文件中导入#import <Realm/Realm.h>可能会报Realm/Realm.h file not found 的错(如果没有报错,请自动忽略.)
1-3.png

解决办法只需修改Podfile文件,只需pod install即可.
原Podfile文件内容

platform :ios, '9.0'
target 'RealmDemo' do
  use_frameworks!
  # Pods for RealmDemo
    pod 'Realm', '~> 3.0.0-beta.2'
end


修改方案1:(推荐方法)

target 'RealmObjc' do

  # Pods for RealmObjc
    pod 'Realm', '~> 3.0.0-beta.2'

  target 'RealmObjcTests' do
    inherit! :search_paths
    # Pods for testing
  end

end


修改方案2:

 platform :ios, '9.0'

target 'RealmDemo' do
  use_frameworks!
  # Pods for RealmDemo
    pod 'Realm', '~> 3.0.0-beta.2'
end


target 'RealmDemoTests' do
    use_frameworks!
    # Pods for RealmDemoTests
    pod 'Realm', '~> 3.0.0-beta.2'
end

3.创建一个继承于RLMObject的model,我们在.h文件中生命对应的属性.
注意:这里生命属性的时候最好不要有(nonatomic,strong)属性的修饰,官网也建议我们不要有修饰,避免出错.
例:官网标准写法

// Define your models like regular Objective‑C classes
interface Dog : RLMObject
property NSString *name;
property NSData   *picture;
property NSInteger age;
@end
@implementation Dog
@end
RLM_ARRAY_TYPE(Dog)

所以我们的生命也是如下的写法:

@interface Stu : RLMObject
@property int num;
@property NSString *name;
@end
4.数据库操作

4..1创建模型------

//方法1:
  Stu *stu = [[Stu alloc]initWithValue:@[@2,@"土豆"]];
    RLMRealm *realm = [RLMRealm defaultRealm];
    [realm beginWriteTransaction];
    [realm addObject:stu];
    [realm commitWriteTransaction];

//方法2:
    Stu *stu = [[Stu alloc]initWithValue:@[@2,@"土豆"]];
    RLMRealm *realm = [RLMRealm defaultRealm];
   [realm transactionWithBlock:^{
        [realm addObject:stu];
   }];

//方法3:
  RLMRealm *realm = [RLMRealm defaultRealm];
    [realm transactionWithBlock:^{
        [Stu createInRealm:realm withValue:@{@"num":@3,@"name":@"哈哈"}];
    }];

4.2.删除数据 ------

//1.删除所有模型
   RLMRealm *realm = [RLMRealm defaultRealm];
    //删除的模型,一定要求是被realm所管理的
    [realm transactionWithBlock:^{
        [realm deleteAllObjects];
    }];
    
    
//2.删除某条数据
    RLMRealm *realm = [RLMRealm defaultRealm];
     Stu *stu = [[Stu alloc]initWithValue:@[@2,@"土豆"]];
    //删除的模型,一定要求是被realm所管理的
    [realm transactionWithBlock:^{
        [realm deleteObject:stu];
    }];


//3. 删除某一特定类型的所有模型
    RLMRealm *realm = [RLMRealm defaultRealm];
    RLMResults *stuRes = [Stu allObjects];
    for (Stu *stu in stuRes) {
        [realm transactionWithBlock:^{
            [realm deleteObject:stu];
        }];
    }
    
//4. 根据主键 删除一个模型
    //1.根据主键,查询到这个模型(这个模型,就是被realm数据库管理的模型)
    Stu *stuDel = [Stu objectInRealm:realm forPrimaryKey:@2];
    //2.删除该模型
    [realm transactionWithBlock:^{
        [realm deleteObject:stuDel];
    }];

4.3.更新模型属性的值 ------

//写法1:
- (void)testUpdate{
    Stu *stu = [[Stu alloc]initWithValue:@[@2,@"土豆"]];
    RLMRealm *realm = [RLMRealm defaultRealm];
    //这个模型stu已经被realm管理,而且已经和磁盘上的对象进行了地址映射
    [realm transactionWithBlock:^{
        [realm addObject:stu];
        NSLog(@"num:%d name: %@",stu.num,stu.name);

    }];
    //这里面修改的模型,一定是被realm所管理的模型
    [realm transactionWithBlock:^{
        stu.name = @"拉阿拉";
        NSLog(@"num:%d name: %@",stu.num,stu.name);

    }];
}


//写法2:
    RLMResults *results = [Stu objectsWhere:@"name = '拉阿拉'"];
    Stu *stu =  results.firstObject;
    
    [realm transactionWithBlock:^{
        stu.name = @"xxxxxxx拉阿拉xxxxxxxx";
        NSLog(@"num:%d name: %@",stu.num,stu.name);

    }];



//方法3:
    Stu *stu = [[Stu alloc]initWithValue:@[@2,@"土豆"]];
    RLMRealm *realm = [RLMRealm defaultRealm];
    [realm transactionWithBlock:^{
        [realm addOrUpdateObject:stu];
         NSLog(@"num:%d name: %@",stu.num,stu.name);

    }];

//方法4:
    RLMRealm *realm = [RLMRealm defaultRealm];
    [realm transactionWithBlock:^{
        [Stu createOrUpdateInRealm:realm withValue:@{@"num":@3,@"name":@"哈哈"}];
    }];

4.4.查找数据 ------

方法1: 
//查询所有对象
//所有的查询(包括查询和属性访问)在realm中都是延迟加载的,终于当属性被访问时,才能够读取相应的数据
    RLMResults *result = [Stu allObjects];
    NSLog(@"%@",result);

方法2:
//带条件的查询
    RLMResults <Stu *> *result2 = [Stu objectsWhere:@"name = '土豆'"];
    NSLog(@"%@",result2);

方法3:
//对查询结果升序降序
    RLMResults *sorRes =  [result sortedResultsUsingKeyPath:@"name" ascending:YES];
    NSLog(@"%@",sorRes);

方法4:
    //链式查询 在sorRes的结果集里查找结果.
    RLMResults *subRes = [sorRes objectsWhere:@"name = '哈哈'"];
    NSLog(@"%@",subRes);
    

小结:
常见错误总结:

错误1:
bug01.png

一般这种错误的原因都是因为你修改了模型的属性,或者增加了模型的属性字段造成的.
解决办法:详见5.数据库迁移操作--适用于修改了表结构的情况

错误2:

这种错误的原因一般都是因为模型中有必填的字段,而你却没有给该字段赋值造成的.
解决办法:给改字段赋值即可.

bug03.png

小技巧:
realm中如果想要更改数据库的名字,只需要在保存对象前调用一下这个方法即可

tips02.png
tips01.png
- (void)setDefaultRealmForUser:(NSString *)username{
    RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
    //使用默认的目录,使用用户名来替换默认的文件名
    config.fileURL = [[[config.fileURL URLByDeletingLastPathComponent]URLByAppendingPathComponent:username]URLByAppendingPathExtension:@"realm"];
    //将这个配置应用到默认的realm数据库中
    [RLMRealmConfiguration setDefaultConfiguration:config];
}

5.数据库迁移操作--适用于修改了表结构的情况
5.1数据结构的迁移

操作步骤:
1.创建一个Stu的模型,并声明一个name的属性

@interface Stu : RLMObject
@property NSString *name;
@end

  RLMRealm *realm = [RLMRealm defaultRealm];
    Stu *stu = [[Stu alloc]initWithValue:@{@"name":@"Allison"}];
 [realm transactionWithBlock:^{
        [realm addObject:stu];
        NSLog(@" ------- name: %@,stu.name);
    }];

此时运行数据库中会多一个名字为Allison的数据.
但是如果此时我们修改了Stu的模型,如在模型中加一个@property int age;的字段,修改代码中 *Stu stu = [[Stu alloc]initWithValue:@{@"name":@"Allison",@"age":@20}];,再次运行,会报一下的错误信息

bug03.png

这里提示需要迁移数据,原因是因为表的结构变化了,所以需要迁移数据.

5.2.数据迁移

在APPdelegate里的didFinishLaunchingWithOptions方法里面写数据迁移.

  //1.获取默认配置
 RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
    
 //2.叠加版本号(要比上一次的版本号高) 默认版本号0
    int newVersion = 1;
    config.schemaVersion = newVersion;
 //3.具体怎样迁移
   [config setMigrationBlock:^(RLMMigration *migration, uint64_t oldSchemaVersion){
        if (oldSchemaVersion < newVersion) {
            NSLog(@"需要做迁移操作");
        }
    }];
   
//4.让配置生效
  [RLMRealmConfiguration setDefaultConfiguration:config];
    
//5.如果需要立即生效
 [RLMRealm defaultRealm];

这里运行此处的代码,即可完成数据迁移的操作,表结构就会多一个age字段,之前的数据也存在.block中无需做任何事情,就可以完成数据结构和数据的迁移.
但是如果是这样的场景比如说我想合并两列的内容到一列,如fullName = preName + lastName
修改Stu的模型 ,增加preName,lastNamefullName属性.

@interface Stu : RLMObject
@property int age;
@property NSString *name;
@property NSString *preName;
@property NSString *lastName;
@property NSString *fullName;
@end

修改刚代码如下

    RLMRealm *realm = [RLMRealm defaultRealm];
    Stu *stu = [[Stu alloc]init];
    stu.age = 20;
    stu.name = @"Allison";
    stu.preName = @"XXXXX";
    stu.lastName = @"wangjiaojiao";
    [realm transactionWithBlock:^{
        [realm addObject:stu];
    }];

运行数据库中即有preName何lastName数据信息.
修改迁移代码如下

//1.获取默认配置
    RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
    
//2.叠加版本号(要比上一次的版本号高) 0
    int newVersion = 9;
    config.schemaVersion = newVersion;
    
//3.具体怎样迁移
    [config setMigrationBlock:^(RLMMigration *migration, uint64_t oldSchemaVersion){
        if (oldSchemaVersion < newVersion) {

    [migration enumerateObjects:@"Stu" block:^(RLMObject * _Nullable oldObject, RLMObject * _Nullable newObject) {
                newObject[@"fullName"] = [NSString stringWithFormat:@"%@%@",newObject[@"preName"],newObject[@"lastName"]];
            }];
        }
    }];
    
//4.让配置生效
 [RLMRealmConfiguration setDefaultConfiguration:config];
    
//5.如果需要立即生效
 [RLMRealm defaultRealm];
5.3.属性重命名---更名动作

比如说将刚刚的fullName更名为fullName2
只需要修改block中的代码如下

//执行更名动作
  [migration renamePropertyForClass:@"Stu" oldName:@"fullName" newName:@"fullName2"];
            
5.4.多版本增量式迁移

比如:我们线上的版本1.0,数据库版本1.1,用户A,B.C分别装在手机上了,后期我线上的版本升级到了2.0,数据库版本也升级到了2.0,用户A升级到了2.0,但是用户B,C没有升级,手机上依旧是1.0.这个时候我们又迭代了一个版本3.0,数据库版本3.0,这个时候就是这样子
用户A: 数据库版本 2.0
用户B: 数据库版本 1.0
用户C: 数据库版本 1.0

这个时候数据库版本1.0升级到3.0,和2.0升级到3.0操作是不一样的

所以在升级操作的block中应该分开来操作

if (oldSchemaVersion < 1) {
    //迁移第一个版本
}

if (oldSchemaVersion < 2) {
   //迁移第二个版本
}
//等等...
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343

推荐阅读更多精彩内容