Realm数据库详解

作者: 叫我小詺 | 来源:发表于2016-03-15 11:02 被阅读3716次

    Realm,为移动设备而生。替代 SQLite 和 Core Data。


    官方中文文档:官方文档

    以上是官方文档,大家看过后有个大体了解。

    说一下我对Realm的认识。

    首先它的API调用特别舒服,不繁琐。

    还有一个好处就是省心,不用像CoreData那样复杂的管理。也不用写SQL语句。总之,简单!

    高效,开发中应用测试时,无论是那种操作,都是秒操作。所以性能不是问题。

    下面是具体操作(看过官方文档,有一定认识后在操作)

    我只是复述一下我对官方文档的理解,以及我集成Realm的过程操作


    从这里开始(集成过程)

    Realm是开源的~,下载方式静态库,以及官方Demo。下载 Realm OC版(Swift版和OC版是不能共存的):下载OC版Realm


    准备工作

    使用 Realm 构建应用的基本要求:iOS >= 7, OS X >= 10.9 并且支持 WatchKit。;

    需要使用 Xcode 6.4 或者以后的版本;

    程序支持Objective‑C, Swift 1.2 & Swift 2.x。


    安装 (这里有好多可选的方式,看大家喜欢,我用的是静态库)

    动态框架

    CocoaPod

    Carthage

    静态框架(因为其他的需要些脚本)


    Realm浏览器/数据库管理器

    官方提供了一个名为Realm Browser的Mac应用,用来进行Realm数          据的读取和编辑。(好用,但是每次编译写入新数据的时候,之前打开的会闪退)


    Xcode 插件

    怎么安装就不赘述了,最开始的时候我会用,后来用多了,就自己手动建模型类了。


    API手册

    能查询Realm的完整版API手册,里面包含了所有类和方法等信息。


    示例

    官方Demo里有(好多,而且是英文不是很懂)


    数据模型(Model)

    Realm数据模型是基于标准 Objective‑C 类来进行定义的,使用属性来完成模型的具体定义。

    通过简单的继承RLMObject或者一个已经存在的模型类,您就可以创建一个新的 Realm 数据模型对象。

    Realm模型对象在形式上基本上与其他 Objective‑C 对象相同 - 您可以给它们添加您自己的方法(method)和协议(protocol),和在其他对象中使用类似。

    主要的限制是某个对象只能在其被创建的那个线程中使用, 并且您无法访问任何存储属性的实例变量(ivar)。

    如果您安装了我们的Xcode插件,那么可在”New File…“对话框中会有一个很漂亮的模板,可用来创建接口(interface)和执行(implementation)文件。

    您只需要为对象的类型列表添加目标类型的属性,或者RLMArray,就可以创建数据关系(relationship)和嵌套数据结构(nested data structure)。


    我就不用官方文档里的类说明了,以下就是实际项目(gitDemo)中类的创建以及使用

    导入项目中的DataStore文件夹

    拖进来之后(确保拖入时勾选了 Copy items if needed ),可能会报错,查看报错信息,(一般是缺少libc++.tbd)


    建模型的基类

    我将常用的数据库操作已经做了封装,在Store文件夹下是Realm数据库的管理类,同时每个模型类都需要主键,所以应该抽象出父类来持有primaryKey和realmManager是有必要的。

    模型类需要跟官方文档里描述一致需要继承RLMObject类RLM_ARRAY_TYPE(BasicRealm)定义一个RLMArray类型(不太明白的可以看一下官方源码)

    #import

    #import"RLMObject+JSON.h"

    #import"XMRealmStoreManager.h"

    @interfaceBasicRealm :RLMObject

    /**

    *本地数据库入库的主键ID

    */

    @property(nonatomic,copy)NSString*hostID;

    /**

    *  realm数据管理

    *

    *  @return realm数据管理

    */

    +(XMRealmStoreManager*)realmManager;

    -(XMRealmStoreManager*)realmManager;

    @end

    // This protocol enables typed collections. i.e.:

    // RLMArray

    RLM_ARRAY_TYPE(BasicRealm)

    @interfaceBasicModel :NSObject

    @property(nonatomic,copy)NSString*hostID;

    @end

    .m文件的具体方法请从项目中查看


    建数据模型类

    现在就可以根据项目需求建立明确的模型类,模型类需要继承上述的基类BasicRealm。

    假如现在的需求是Cell的标题下有三张图片(大家自行脑补一下UI),那么我们需要标题属性,以及一个图片链接数组(Realm中不能用NSArray,需要用RLMArray)属性声明如下

    #import"BasicModel.h"

    RLM_ARRAY_TYPE(ImageRealm)//定义一个RLMArray类型

    @interfaceDataRealm :BasicRealm

    @property(nonatomic,copy)NSString*title;

    @property(nonatomic,strong)RLMArray * image_url;

    @end

    @interfaceImageRealm :BasicRealm

    @property(nonatomic,copy)NSString*image;

    @end

    .m中需要重写两个方法

    + (NSDictionary*)JSONInboundMappingDictionary(入库的keyPath对应模型的keyPath)

    + (NSDictionary*)JSONOutboundMappingDictionary(出库的keyPath对应模型的keyPath)

    两个方法一般内容都相同,一般我们写的模型类都是基于服务器返回数据的KeyPath作为我们数据类的属性名。但当服务器返回的数据(比如服务器数据库的主键是id,当然你也可以跟服务端开发商量一下提前做一下key的更改,毕竟好兄弟~)有一些OC的关键词比如id这样的话我们就需要将入(出)库的keyPath对应模型的keyPath做一下映射的更改

    @implementationDataRealm

    + (NSDictionary*)JSONInboundMappingDictionary {

    return@{

    @"hostID":@"hostID",

    @"image_url":@"image_url",

    @"title":@"title",

    };

    }

    + (NSDictionary*)JSONOutboundMappingDictionary {

    return@{

    @"hostID":@"hostID",

    @"image_url":@"image_url",

    @"title":@"title",

    };

    }

    @end

    @implementationImageRealm

    + (NSDictionary*)JSONInboundMappingDictionary {

    return@{

    @"hostID":@"hostID",

    @"image":@"image",

    };

    }

    + (NSDictionary*)JSONOutboundMappingDictionary {

    return@{

    @"hostID":@"hostID",

    @"image":@"image",

    };

    }

    @end


    Realm数据模型类的使用

    用Realm管理类调用数据的增删改差

    //增or改

    -(void)add

    {

    [[DataRealmrealmManager]writeObjectsWithObjectsBlock:^id(XMRealmOperation*operation,RLMRealm*realm) {

    //在这返回一个id对象可以是一个包含多个数据库模型的数组,也可以是单个数据库模型对象可以调用Real自己的解析字典方法,也可以用封装好的方法(根据服务器返回的数据类型)

    return[DataRealmcreateOrUpdateInRealm:realmwithJSONDictionary:@{@"hostID":@"1",@"title":@"好好学习天天向上",@"image_url":@[@{@"hostID":@"1",@"image":@"http://image1"},@{@"hostID":@"2",@"image":@"http://image2"},@{@"hostID":@"3",@"image":@"http://image3"}]}];

    //        return [DataRealm createOrUpdateInRealm:realm withJSONArray:@[]];

    }completion:^(XMRealmStoreManager*store,XMRealmOperation*operation,RLMRealm*realm) {

    //事务完成后回调

    }];

    }

    //删

    -(void)delete{

    [[DataRealmrealmManager]deleteObjectsWithObjectsBlock:^id(XMRealmOperation*operation,RLMRealm*realm) {

    //可以根据sql语句查找删除

    return[DataRealmobjectsWhere:@""];

    //也可以根据主键获得

    return[DataRealmobjectForPrimaryKey:@"1"];

    }completion:^(XMRealmStoreManager*store,XMRealmOperation*operation,RLMRealm*realm) {

    //事务完成回调

    }];

    }

    //查

    -(void)search

    {

    [[DataRealmrealmManager]fetchObjectsWithObjectsBlock:^id(XMRealmOperation*operation,RLMRealm*realm) {

    //可以根据sql语句查找删除

    return[DataRealmobjectsWhere:@""];

    //也可以根据主键获得

    return[DataRealmobjectForPrimaryKey:@"1"];

    }completion:^(XMRealmStoreManager*store,XMRealmOperation*operation,RLMRealm*realm,RLMResults*results,NSString*primaryKey,NSMutableArray*models) {

    //事务完成回调获得查询内容更新UI

    }];

    }


    后语:

    我建议大家将数据分为两种类,一种是数据库类,一种是平常我们不做数据存储的类(我在Demo(由于git文件大小限制不能上传Realm.framework,请大家自行拖入)中是这样操作的)。这样做的好处是分开来易于管理,那些属性内容需要入库就在数据库类中声明,不需要的但是我们UI展示上需要的在单独的数据类中。这样数据库中就不需要冗余的key(当然也可以通过.m的两种方法来控制入库的keyPath)这样做还有一个不算原因的原因,这样做可以用一些字典转模型的解析类框架(比如MJ,YYModel等)。总是这项看个人喜好吧。

    相关文章

      网友评论

      • zhujj_developer:请教 怎么处理 nested
      • zhujj_developer:请教 怎么 在yymode + realm 存储 数字的nsarray 以及 怎么转换对象数组 用yymodel
      • 等这姑娘老在我心里:realm 3层一对多 结构怎么更新数据呢
      • 5b489f67a2b3:请教一下,数据分两种类,在接收到json数据时,是要做两次映射?然后“不做数据存储的类”和入库的类,在使用的时候是怎么结合的呢?还请指点一下。

      本文标题:Realm数据库详解

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