美文网首页
realm简单操作介绍

realm简单操作介绍

作者: 翀鹰精灵 | 来源:发表于2017-08-24 17:44 被阅读246次

    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) {
       //迁移第二个版本
    }
    //等等...
    

    相关文章

      网友评论

          本文标题:realm简单操作介绍

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