Realm入门指北

作者: ISwiftUI | 来源:发表于2017-01-17 15:35 被阅读292次

    简介

    接触Realm已经有一段时间了,但是一直忙着项目,一直没有时间做一下笔记。趁着项目闲着之际,我开始着手记录我自己使用Realm过程遇到的坑。Realm是一个跨平台的数据库,就拿iOS来说,数据库常用的几种无非是Sqlite、FMDB、CoreData这几种,每一种数据库都在某些方面有着特别的优势。对于coreData,在每次使用的时候都要创建一大堆的代码,个人是累觉不爱。而对于Sqlite是基于C语言的,用起来也是相对麻烦,FMDB是基于Sqlite的封装,用起来还相对友好一点,但是还是要写一大堆的sql语句,但是无可否认的是,在API上FMDB还是蛮简单上手的。但是今天重点介绍的是Realm.

    Realm是由Y Combinator孵化的创业团队开源出来的一款可以用于iOS(同样适用于Swift&Objective-C)和Android的跨平台移动数据库。目前最新版是Realm 2.0.2,支持的平台包括Java,Objective-C,Swift,React Native,Xamarin。

    安装方法主要有四种(在这就不做说明)
    1.Dynamic Framework(动态库)
    2.CocoaPod
    3.Carthage(仅支持iOS8以上)
    4.Static Framework

    Realm 中的相关术语

    为了能更好的理解Realm的使用,先介绍一下涉及到的相关术语。

    RLMRealm:Realm是框架的核心所在,是我们构建数据库的访问点,就如同Core Data的管理对象上下文(managed object context)一样。出于简单起见,realm提供了一个默认的defaultRealm( )的便利构造器方法。

    RLMObject:这是我们自定义的Realm数据模型。创建数据模型的行为对应的就是数据库的结构。要创建一个数据模型,我们只需要继承RLMObject,然后设计我们想要存储的属性即可。

    关系(Relationships):通过简单地在数据模型中声明一个RLMObject类型的属性,我们就可以创建一个“一对多”的对象关系。同样地,我们还可以创建“多对一”和“多对多”的关系。

    写操作事务(Write Transactions):数据库中的所有操作,比如创建、编辑,或者删除对象,都必须在事务中完成。“事务”是指位于write闭包内的代码段。

    查询(Queries):要在数据库中检索信息,我们需要用到“检索”操作。检索最简单的形式是对Realm( )数据库发送查询消息。如果需要检索更复杂的数据,那么还可以使用断言(predicates)、复合查询以及结果排序等等操作。

    RLMResults:这个类是执行任何查询请求后所返回的类,其中包含了一系列的RLMObject对象。RLMResults和NSArray类似,我们可以用下标语法来对其进行访问,并且还可以决定它们之间的关系。不仅如此,它还拥有许多更强大的功能,包括排序、查找等等操作。

    Realm 的基本使用

    1.创建数据库
    • 1.使用系统默认的数据库
    • 2.自定义数据库(代码实现的是自定义的数据库)

    Object-C

    RLMRealm *realm = [RLMRealm defaultRealm];
    
     - (BOOL) initRealm {
        RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
        config.fileURL = [[[config.fileURL URLByDeletingLastPathComponent]
                           URLByAppendingPathComponent:[NSString stringWithFormat:@"Message%lu",(unsigned long)self.messageType]]
                          URLByAppendingPathExtension:@"realm"];
        debugLog(@"Realm file path: %@", config.fileURL);
        NSError *error;
        _realm = [RLMRealm realmWithConfiguration:config error:&error];
        if (nil != error) {
            NSLog(@"Create Realm Error");
            return NO;
        }
        debugLog(@"create realm success");
        return YES;
    }
    

    Swift

        // MARK: - 初始化Rleam数据库
        func createDataBase() {
            var config = Realm.Configuration()
            config.fileURL = config.fileURL?.deletingLastPathComponent().appendingPathComponent("HJQ").appendingPathExtension("Realm")
            var realm: Realm?
            do {
               realm =  try Realm.init(configuration: config)
            } catch  {
                debugLog(error)
            }
            debugLog(realm)
        }
    
    2.建表

    Object-C

    #import <Foundation/Foundation.h>
    #import <Realm/Realm.h>
    
    @interface UserMessageList : RLMObject
    
    @property NSString *title;
    @property NSInteger linkType;
    @property NSInteger messageId;
    @property BOOL readStatus;
    @property NSString *content;
    @property long long createTime;
    @property NSString *picUrl;
    
    @end
    RLM_ARRAY_TYPE(UserMessageList);
    
    @interface GFBUserMessageMD : RLMObject
    
    @property NSString *username;
    @property RLMArray<UserMessageList> *userMessageList;
    
    @end
    RLM_ARRAY_TYPE(GFBUserMessageMD);
    

    注意,RLMObject 官方建议不要加上 Objective-C的property attributes(如nonatomic, atomic, strong, copy, weak 等等)假如设置了,这些attributes会一直生效直到RLMObject被写入realm数据库。

    RLM_ARRAY_TYPE宏创建了一个协议,从而允许 RLMArray<GFBUserMessageMD>语法的使用。如果该宏没有放置在模型接口的底部的话,您或许需要提前声明该模型类。

    关于RLMObject的的关系

    1.对一(To-One)关系

    对于多对一(many-to-one)或者一对一(one-to-one)关系来说,只需要声明一个RLMObject子类类型的属性即可

    2.对多(To-Many)关系(重点介绍)
    通过 RLMArray类型的属性您可以定义一个对多关系。如上面代码例子,@property RLMArray<UserMessageList> *userMessageList;

    3.反向关系(Inverse Relationship)

    #import "GFBUserMessageMD.h"
    
    @implementation GFBUserMessageMD
    // 为了保证表的唯一性,设置主键
    + (NSString *)primaryKey {
        return @"username";
    }
    
    @end
    @implementation UserMessageList
    
    @end
    

    Swift

    import UIKit
    import RealmSwift
    >
    class UserMessageMD: Object {
        dynamic var title: String?
        dynamic var messageID: String!
    }
    >
    class UserMD: Object {
        dynamic var userID: String!
        dynamic var name: String!
        >
        // List 是个泛型
        var userMessages = List<UserMessageMD>()
        >
        // MARK: - 设置主键
        override static func primaryKey() -> String? {
            return "userID"
        }
    }
    
    3.数据的插入

    Object-C

    - (void) insertOrCreateData:(GFBSysMessageListMD *)md {
        GFBUserMessageMD *userMD;
        NSString *userId = [QFUserInfo shareInfo].username;
        if (! userId) {
            return;
        }
        // 查询当前是否有这个表
        if ([GFBUserMessageMD objectInRealm:_realm forPrimaryKey:userId]) {
            userMD = [GFBUserMessageMD objectInRealm:_realm forPrimaryKey:userId];
        }else {
            userMD = [GFBUserMessageMD new];
            userMD.username = userId;
        }
        [_realm transactionWithBlock:^{
            for (int i = 0; i < md.data.content.count; i++) {
                SysMessageListContent *model = md.data.content[i];
                UserMessageList *userMessageMD;
                NSPredicate *pred = [NSPredicate predicateWithFormat:@"messageId = %li",model.id];
                if([userMD.userMessageList indexOfObjectWithPredicate:pred] != NSNotFound) { // 如果该数据已经存在则无需重新插入
                    NSUInteger index = [userMD.userMessageList indexOfObjectWithPredicate:pred];
                    userMessageMD = userMD.userMessageList[index];
                    debugLog(@"我是查询的结果%lu",index);
                }else{
                    // 插入新的数据
                    userMessageMD = [UserMessageList new];
                    userMessageMD.title = model.title;
                    userMessageMD.messageId = model.id;
                    userMessageMD.content = model.content;
                    userMessageMD.createTime = model.createTime;
                    userMessageMD.readStatus = NO;
                    userMessageMD.linkType = model.linkType;
                    userMessageMD.picUrl = model.picUrl;
                    [userMD.userMessageList addObject:userMessageMD];
                }
            }
            [GFBUserMessageMD createOrUpdateInRealm:_realm withValue:userMD];
        }];
    }
    

    Swift

    // MARK: - 建表插入数据
        func insertData() {
            let realm = try! Realm()
            // 通过主键查找到对应的数据
            var userMD = realm.object(ofType: UserMD.self,forPrimaryKey: "")
            if userMD == nil {
                userMD = UserMD()
            }
            let messageID = "10000"
            try! realm.write {
                var userMessageMD: UserMessageMD? = nil
                let pred = NSPredicate(format: "messageID = \(messageID) ")
                let resultIndex = userMD!.userMessages.index(matching: pred)
                if resultIndex != NSNotFound { // 已经存在
                    userMessageMD = userMD!.userMessages[resultIndex!]
                }else {
                    userMessageMD = UserMessageMD()
                    // 不存在则继续追加
                    userMD?.userMessages.append(userMessageMD!)
                }
                realm.add(userMD!, update: true)
            }
        }
    
    4.数据的更新
    - (void) updateReadStatus:(NSInteger) index {
        GFBUserMessageMD *userMD;
        NSString *userId = [QFUserInfo shareInfo].username;
        if (! userId) {
            return;
        }
        // 查询当前是否有这个表
        if ([GFBUserMessageMD objectInRealm:_realm forPrimaryKey:userId]) {
            userMD = [GFBUserMessageMD objectInRealm:_realm forPrimaryKey:userId];
        }
        if (userMD) {
            [_realm transactionWithBlock:^{
                UserMessageList *userMessageMD = userMD.userMessageList[index];
                userMessageMD.readStatus = YES;
                [GFBUserMessageMD createOrUpdateInRealm:_realm withValue:userMD];
            }];
        }
    }
    
    5.数据的查询

    Object-C

    // 查找所有的数据
    - (void) queryAllData {
        GFBUserMessageMD *userMD;
        NSString *userId = [QFUserInfo shareInfo].username;
        if (! userId) {
            return;
        }
        // 查询当前是否有这个表
        if ([GFBUserMessageMD objectInRealm:_realm forPrimaryKey:userId]) {
            userMD = [GFBUserMessageMD objectInRealm:_realm forPrimaryKey:userId];
        }
        if (userMD) {
            debugLog(@"当前存在的数据%@",userMD.userMessageList);
        }
    }
    

    Swift

        // MARK: - 查询数据
        func queriesDatas() {
            let realm = try! Realm()
            // 通过主键查找到对应的数据
            let userMD = realm.object(ofType: UserMD.self,forPrimaryKey: "")
            debugLog(userMD)
        }
    

    相关文章

      网友评论

      本文标题:Realm入门指北

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