Realm的一些特性介绍

14 篇文章 0 订阅

之前做ios开发,数据存储这块基本上用的都是sqllite,15年下半年在做一个产品时,因为时间比较宽裕,便决定在项目中尝试使用realm数据存储框架。之前在做技术调研时,了解到了很多它的优点,速度快、类似core data的机制、文档详尽、简单易用等。而整个项目下来,也确实感觉到了realm的不负众望,优点很多:开发效率得到了大大提高(省去了数据模型与表存储之间转化的很多工作);框架虽然推出不久,但功能覆盖已经趋于完备了,基本都满足了我的需求;有一个十分好用的可视化数据库查看工具;最终的运行表现也很让人满意。但是,在使用中确实也发现了realm框架中存在的一些坑与需要适应的地方的,最近,无意中又回想起了这个框架,发现版本已经更新到了2.1.1,于是决定回顾一下,看看原来的这些地方有没有什么变化,顺便也总结一下这些问题,供大家参考。


1.不支持联合主键

+ (nullable NSString *)primaryKey;
realm不支持数据库中联合主键的概念,如果你之前的设计中用到了联合主键,那只能重新设计,在设计层面上规避这个问题了。


2.不支持自增长主键

同上,设计层面解决


3.不能跨线程共享realm实例

    RLMRealm *realm = [RLMRealm defaultRealm];
    
    Course *course = [[Course alloc] init];
    course.courseId = @"001";
    course.courseName = @"数学";
    [realm beginWriteTransaction];
    [Course createOrUpdateInRealm:realm withValue:course];
    [realm commitWriteTransaction];
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//        RLMRealm *realm = [RLMRealm defaultRealm];
        [realm beginWriteTransaction];
        Course *course2 = [[Course alloc] init];
        course2.courseId = @"002";
        course2.courseName = @"语文";
        [Course createOrUpdateInRealm:realm withValue:course2];
        [realm commitWriteTransaction];
    });

上面这段代码会运行错误,需要把注释语句打开

Using a Realm Across Threads
To access the same Realm file from different threads, 
you must initialize a new Realm to get a different instance for every thread of your app. As long as you specify the same configuration, all Realm instances will map to the same file on disk

不同线程中,都要创建独立的realm实例,只要配置(configuration)相同,它们操作的就是同一个实体数据库


4.存取只能以对象为单位,不能只查某个属性

使用sql时,可以单独查询某个(几个)独立属性,比如 select courseName from Courses where courseId = "001"

而在realm中 

+ (RLMResults *)objectsWhere:(NSString *)predicateFormat, ...;
+ (RLMResults *)objectsInRealm:(RLMRealm *)realm where:(NSString *)predicateFormat, ...;
+ (RLMResults *)objectsInRealm:(RLMRealm *)realm withPredicate:(nullable NSPredicate *)predicate;
......
查询相关函数,得到的都是对象的集合,相对不够灵活


5.注意RLMResults中的对象

    RLMResults *results = [Course objectsWhere:@"courseId = '001'"];
    Course *getCourse = [results objectAtIndex:0];
    getCourse.courseName = @"英语";

上面代码运行时会产生错误,被查询出的对象,任何的修改都会被直接同步到数据库中,所以对对象的修改都必须被包裹在beginWriteTransaction中,使用时要注意


6.RLMResults与线程

    RLMResults *results = [Course objectsWhere:@"courseId = '001'"];
    Course *getCourse = [results objectAtIndex:0];
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"%@",results);
        NSLog(@"%@",getCourse.courseName);
    });

上面这段代码会在运行时产生错误,results、getCourse是在主线程中被查询出来的,如果在别的线程中被访问,都是不被允许的

7.Auto-Updating机制

RLMObject instances are live, auto-updating views into the underlying data, which means objects never have to be refreshed. Modifying the properties of an object will immediately reflect in any other instances referring to the same object.

    RLMRealm *realm = [RLMRealm defaultRealm];
    Course *course = [[Course alloc] init];
    course.courseId = @"001";
    course.courseName = @"语文";
    [realm transactionWithBlock:^{
        [realm addObject:course];
    }];
    
    Course *getCourse1 = [Course objectsWhere:@"courseId = '001'"].firstObject;
    NSLog(@"%@",getCourse1);
    [realm transactionWithBlock:^{
        getCourse1.courseName = @"体育";
    }];
    
    NSLog(@"%@",course);
//    RLMRealm *realm = [RLMRealm defaultRealm];
//    Course *course = [[Course alloc] init];
//    course.courseId = @"001";
//    course.courseName = @"语文";
//    [realm beginWriteTransaction];
//    [Course createOrUpdateInDefaultRealmWithValue:course];
//    [realm commitWriteTransaction];
//    
//    Course *getCourse1 = [Course objectsWhere:@"courseId = '001'"].firstObject;
//    NSLog(@"%@",getCourse1);
//    [realm beginWriteTransaction];
//    getCourse1.courseName = @"数学";
//    [Course createOrUpdateInDefaultRealmWithValue:getCourse1];
//    [realm commitWriteTransaction];
//    NSLog(@"%@",course);

getCourse1进行修改后,course的属性也随之自动更新了.但是,同样的功能逻辑,如果按注释部分的方式去写,auto updating机制却并未起作用,不知道是不是realm框架的问题,所以对auto updating机制的把握还是要多在实践中总结、观察。

    RLMRealm *realm = [RLMRealm defaultRealm];
    Course *course = [[Course alloc] init];
    course.courseId = @"001";
    course.courseName = @"语文";
    [realm beginWriteTransaction];
    [Course createOrUpdateInDefaultRealmWithValue:course];
    [realm commitWriteTransaction];
    
    RLMResults *result = [Course allObjects];
    NSLog(@"%@",result);
    
    Course *course2 = [[Course alloc] init];
    course2.courseId = @"002";
    course2.courseName = @"数学";
    [realm beginWriteTransaction];
    [Course createOrUpdateInDefaultRealmWithValue:course2];
    [realm commitWriteTransaction];
    
    NSLog(@"%@",result);

第一次查询后,result中有一条记录,后面即便没有执行重新查询,新加入的数据,自动就被同步到了result

    RLMRealm *realm = [RLMRealm defaultRealm];
    Course *course = [[Course alloc] init];
    course.courseId = @"001";
    course.courseName = @"语文";
    [realm beginWriteTransaction];
    [Course createOrUpdateInDefaultRealmWithValue:course];
    [realm commitWriteTransaction];
    
    Course *getCourse1 = [Course objectsWhere:@"courseId = '001'"].firstObject;
    NSLog(@"%@",getCourse1);
    Course *getCourse2 = [Course objectsWhere:@"courseId = '001'"].firstObject;
    [realm beginWriteTransaction];
    getCourse2.courseName = @"体育";
    [realm commitWriteTransaction];
    NSLog(@"%@",getCourse1);

开始查询出课程id001的课程模型getCourse1getCourse2的课程名为语文,后面仅对getCourse2进行修改后,getCourse1的属性也被自动同步更新了

    Course *getCourse1 = [Course objectsWhere:@"courseId = '001'"].firstObject;
    NSLog(@"%@",getCourse1);
    
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        RLMRealm *realm = [RLMRealm defaultRealm];
        Course *getCourse2 = [Course objectsWhere:@"courseId = '001'"].firstObject;
        [realm beginWriteTransaction];
        getCourse2.courseName = @"体育";
        [realm commitWriteTransaction];
        NSLog(@"%@",getCourse2);
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"%@",getCourse1);
        });
    });

同样,在别的线程中的修改,也会被同步过来

realm这种auto-updating机制确实十分方便,并保证了数据的实时性,但是在个别情况下,也许这种机制并不是开发者想要的,可能会导致一些意外,开发时需要注意


8.setter/getter方法失效

#import "Course.h"

@implementation Course

-(void)setCourseName:(NSString *)courseName
{
    _courseName = courseName;
}

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

@end
Course *getCourse = [Course objectsWhere:@"courseId = '001'"].firstObject;
[realm beginWriteTransaction];
getCourse.courseName = @"英文";//不会走进setCourseName方法
[realm commitWriteTransaction];
从realm数据库读取出的数据模型,setter/getter方法会失效

Since Realm overrides setters and getters to back properties directly by the underlying database, you cannot override them on your objects. 

Note that Realm ignores Objective‑C property attributes likenonatomic,atomic, strong, copy, weak, etc. This is done because Realm has its own optimized storage semantics under the hood. So to avoid being misleading, we recommend writing models without any property attributes at all. However, if you do set property attributes, they will be used until an RLMObject is added to a Realm. Custom names for getters and setters work normally regardless of whether or not anRLMObject is managed by a Realm.










  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值