realm简单操作介绍

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

realm简单操作介绍_第1张图片
1-4.png

说明:为方便测试,这里我使用Xcode自带的单元测试来操作.
准备工作:
1.去 官网下载realm,我这里选择的是realm-Objc
2.下载realm-objc安装包,打开realm-objc-2.9.1-->plugin-->RealmPlugin,安装realm的插件.直接编译运行即可,安装完成后即有个realm的模型
realm简单操作介绍_第2张图片
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创建单元测试模块

realm简单操作介绍_第3张图片
1-2.png

这里我们直接在RealmDemoTests文件中导入 #import 可能会报 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  *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:
realm简单操作介绍_第4张图片
bug01.png

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

错误2:

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

realm简单操作介绍_第5张图片
bug03.png

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

realm简单操作介绍_第6张图片
tips02.png
realm简单操作介绍_第7张图片
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}];,再次运行,会报一下的错误信息

realm简单操作介绍_第8张图片
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简单操作介绍)