Realm从入门到放弃(二)

作者: heweiming 分类: iOS,干货 发布时间: 2017-01-09 23:58

Realm从入门到放弃(二)

上一期跟大家讨论了Realm的特性与某方面的简介,这一期我们着重来聊一下Realm的功能

我们还是介绍Objective-C的使用方法。

说到数据库那就肯定少不了增,删,改,查。但是Realm这个数据库由于是采用自己开发的引擎,而且采用的是对象存储的方式。所以我们不会看到SQL标准的语法。取而代之的是我们熟悉的OC语法

一、准备(一)

使用Realm的途径有四个:

一:在官网上下载发行版

注意:动态框架与 iOS 7 不兼容,要支持 iOS 7 的话请查看“静态框架”。

下载最新的Realm发行版本,并解压;
前往Xcode 工程的”General”设置项中,从ios/dynamic/、osx/、tvos/或者watchos/中将’Realm.framework’拖曳到”Embedded Binaries”选项中。确认Copy items if needed被选中(除非您的项目中需要在多个平台中使用 Realm),点击Finish按钮;
在单元测试 Target 的”Build Settings”中,在”Framework Search Paths”中添加Realm.framework的上级目录;
如果希望使用 Swift 加载 Realm,请拖动Swift/RLMSupport.swift文件到 Xcode 工程的文件导航栏中并选中Copy items if needed;
如果在 iOS、watchOS 或者 tvOS 项目中使用 Realm,请在您应用目标的”Build Phases”中,创建一个新的”Run Script Phase”,并将

bash "${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}/Realm.framework/strip-frameworks.sh"
这条脚本复制到文本框中。 因为要绕过APP商店提交的bug,这一步在打包通用设备的二进制发布版本时是必须的。


二:使用Cocoapods进行管理

安装CocoaPods 0.39.0 或者更高版本;
运行 pod repo update,以确保 CocoaPods 能够获取到 Realm 的最新版本
在您的Podfile中,添加pod 'Realm'到您的 app 目标中,添加pod 'Realm/Headers'到您的测试目标中;
在终端运行pod install或者pod update;
采用 CocoaPods 生成的.xcworkspace来运行工程!
如果需要在 Swift 当中使用的话,将位于 Swift/RLMSupport.swift 的这个文件拖动到您 Xcode 项目的文件导航器当中,检查以确保 Copy items if needed 选项已被勾选。


三:使用Carthage进行管理

安装 Carthage 0.17.0 或者更高版本;
在Carthage 中添加github "realm/realm-cocoa";
运行 carthage update;
从 Carthage/Build/ 目录下对应平台文件夹中,将 Realm.framework 拖曳到您 Xcode 工程”General”设置项的”Linked Frameworks and Libraries”选项卡中;
iOS/tvOS/watchOS: 在您应用目标的“Build Phases”设置选项卡中,点击“+”按钮并选择“New Run Script Phase”。在新建的Run Script中,填写:
/usr/local/bin/carthage copy-frameworks

在“Input Files”内添加您想要使用的框架路径,例如:

$(SRCROOT)/Carthage/Build/iOS/Realm.framework

因为要绕过APP商店提交的bug,这一步在打包通用设备的二进制发布版本时是必须的。 16. 如果需要在 Swift 当中使用的话,将位于 Swift/RLMSupport.swift 的这个文件拖动到您 Xcode 项目的文件导航器当中,检查以确保 Copy items if needed 选项已被勾选。


使用静态框架

下载 Realm 的最新版本并解压;
将 Realm.framework 从 ios/static/ 文件夹拖曳到您 Xcode 项目中的文件导航器当中。确保 Copy items if needed 选中然后单击 Finish;
在 Xcode 文件导航器中选择您的项目,然后选择您的应用目标,进入到** Build Phases** 选项卡中。在 Link Binary with Libraries 中单击 + 号然后添加 libc++.tbd 以及 libz.tbd;
如果你在用 Swift 来使用 Realm,那么将位于 Swift/RLMSupport.swift 的文件拖曳进您 Xcode 项目中的文件导航器当中,确保 Copy items if needed 选中。

二、准备(二)

1、官网的数据库可视化工具

Realm数据库浏览器

2、Xcode插件或者使用Alcatraz进行安装,Xcode8使用插件的方式我这里也提供一下update_xcode_plugins

Xcode插件

提个醒,除非是一开始就想数据库里面有某些逻辑性的数据的话,可以使用这个插件直接生成Realm的数据库,不然我还是觉得用代码生成数据库比较好。

3、官网的API文档

4、官网的使用文档

二、准备(三)

在Objective-C中总是少不了各种各样的模型,而模型往往都是集成 NSObject 。模型是一个类,类就产生对象。我们存储的就是从模型里面init出来的对象,而这个对象就是数据库里的一行数据,而键就是我们在模型类里面写的属性名(关于支持的属性类型在Realm从入门到放弃(一)中已经阐述,在这里就不进行进一步的罗列了)。

而在Realm中我们需要继承的不是 NSObject 而是一个Realm独有的父类 RLMObject ,这个RLMObjectNSObject 相仿,但是里面添加了Realm的一些方法,例如Realm从入门到放弃(一)中提到了主键、索引、属性默认值、对象自更新、忽略属性等方法,更包括增删改查的方法。

模型继承

Realm 允许模型能够生成更多的子类,也允许跨模型进行代码复用,但是由于某些 Cocoa 特性使得运行时中丰富的类多态无法使用。

以下是可以完成的操作:

1.父类中的类方法,实例方法和属性可以被它的子类所继承

2.子类中可以在方法以及函数中使用父类作为参数

以下是不能完成的:

1.多态类之间的转换(例如子类转换成子类,子类转换成父类,父类转换成子类等)

2.同时对多个类进行检索

3.多类容器 (RLMArray 以及 RLMResults)。

另外,如果您的代码实现允许的话,我们建议您使用以下模式,也就是使用类组合模式来构建子类,以便能够包含其他类中的相关逻辑:

// 基础模型
@interface Animal : RLMObject
@property NSInteger age;
@end
@implementation Animal
@end

// 包含有 Animal 的模型
@interface Duck : RLMObject
@property Animal *animal;
@property NSString *name;
@end
@implementation Duck
@end

@interface Frog : RLMObject
@property Animal *animal;
@property NSDate *dateProp;
@end
@implementation Frog
@end

// 用法
Duck *duck =  [[Duck alloc] initWithValue:@{@"animal" : @{@"age" : @(3)}, @"name" : @"Gustav" }];
集合

Realm 拥有一系列能够帮助表示一组对象的类型,我们称之为「Realm 集合」:

1.RLMResults类,表示从检索 中所返回的对象集合。

2.RLMArray类,表示模型中的对多关系。

3.RLMLinkingObjects类,表示模型中的反向关系。

4.RLMCollection 协议,定义了所有 Realm 集合所需要遵守的常用接口。

Realm 集合实现了 RLMCollection 协议,这确保它们能够保持一致。这个协议继承自 NSFastEnumeration,因此它应当与其他 Foundation 当中的集合用法一致。 其他常用的 Realm 集合 API 也在这个协议当中进行了声明,例如其中包括检索、排序以及聚合操作。 RLMArray拥有额外的修改操作,这些操作不在协议接口当中有定义,例如添加和删除对象。

使用 RLMCollection 协议,您可以编写能够操作任意 Realm 集合的泛型代码:

@implementation MyObject
- (void)operateOnCollection:(id<RLMCollection>)collection {
  // collection 既可以是 RLMResults,也可以是 RLMArray
  NSLog(@"对集合 %@s 进行操作", collection.objectClassName);
}
@end

二、开始(增删查改)

1.增

我是采用基类的形式,先基类RLMObject。


先看
ETBaseDataModel.h

#import <Foundation/Foundation.h>
#import <Realm/Realm.h>

@interface ETBaseDataModel : RLMObject

@end

implementation文件暂时是空的,这个方便以后做点什么工作,毕竟模型不少,如果每个都集成一次RLMObject,如果业务逻辑有什么修改那就够忙了。

1.1数据模型

接下来看看我的数据模型

ETUser.h

//
//  ETUser.h
//  Eitty_OA
//
//  Created by HE WEIMING on 2017/2/13.
//  Copyright © 2017年 Eitty. All rights reserved.
//

#import "ETBaseDataModel.h"
#import "ETUserDetail.h"
#import "ETUserSetting.h"
#import "ETUserChatSetting.h"

@interface ETUser : ETBaseDataModel

// 用户ID
@property (nonatomic, strong) NSString *userID;

// 用户名
@property (nonatomic, strong) NSString *username;

// 昵称
@property (nonatomic, strong) NSString *nikeName;

// 头像URL
@property (nonatomic, strong) NSString *avatarURL;

// 头像Path
@property (nonatomic, strong) NSString *avatarPath;

// 备注名
@property (nonatomic, strong) NSString *remarkName;

// 界面显示名称
@property (nonatomic, strong, readonly) NSString *showName;

#pragma mark - 其他
@property (nonatomic, strong) ETUserDetail *detailInfo;

@property (nonatomic, strong) ETUserSetting *userSetting;

@property (nonatomic, strong) ETUserChatSetting *chatSetting;

#pragma mark - 列表用
/**
 *  拼音
 *
 *  来源:备注 > 昵称 > 用户名
 */
@property (nonatomic, strong) NSString *pinyin;

@property (nonatomic, strong) NSString *pinyinInitial;

@end

RLM_ARRAY_TYPE(ETUser)

可以看到

ETUserDetail.h

ETUserSetting.h

ETUserChatSetting.h

也是模型 我顺便在这个类里面进行一对一的关系
ETUser.m

//
//  ETUser.m
//  Eitty_OA
//
//  Created by HE WEIMING on 2017/2/13.
//  Copyright © 2017年 Eitty. All rights reserved.
//

#import "ETUser.h"
#import "NSString+ETPinYin.h"
#import <MJExtension/MJExtension.h>

@implementation ETUser

- (id)init
{
    if (self = [super init]) {
        [ETUser mj_setupObjectClassInArray:^NSDictionary *{
            return @{ @"detailInfo" : @"ETUserDetail",
                      @"userSetting" : @"ETUserSetting",
                      @"chatSetting" : @"ETUserChatSetting",};
        }];
    }
    return self;
}

- (void)setUsername:(NSString *)username
{
    if ([username isEqualToString:_username]) {
        return;
    }
    _username = username;
    if (self.remarkName.length == 0 && self.nikeName.length == 0 && self.username.length > 0) {
        self.pinyin = username.pinyin;
        self.pinyinInitial = username.pinyinInitial;
    }
}

- (void)setNikeName:(NSString *)nikeName
{
    if ([nikeName isEqualToString:_nikeName]) {
        return;
    }
    _nikeName = nikeName;
    if (self.remarkName.length == 0 && self.nikeName.length > 0) {
        self.pinyin = nikeName.pinyin;
        self.pinyinInitial = nikeName.pinyinInitial;
    }
}

- (void)setRemarkName:(NSString *)remarkName
{
    if ([remarkName isEqualToString:_remarkName]) {
        return;
    }
    _remarkName = remarkName;
    if (_remarkName.length > 0) {
        self.pinyin = remarkName.pinyin;
        self.pinyinInitial = remarkName.pinyinInitial;
    }
}

#pragma mark - Getter
- (NSString *)showName
{
    return self.remarkName.length > 0 ? self.remarkName : (self.nikeName.length > 0 ? self.nikeName : self.username);
}

- (ETUserDetail *)detailInfo
{
    if (_detailInfo == nil) {
        _detailInfo = [[ETUserDetail alloc] init];
    }
    return _detailInfo;
}

@end

未完待续

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

4条评论
  • heweiming

    2017年4月10日 上午12:00

    由于工作比较忙,有很多想法,只能慢慢更新上去了

  • remove

    2017年4月12日 下午1:06

    Please let me know if you’re looking for a article author for your
    weblog. You have some really good posts and I believe I would be a good asset.

    If you ever want to take some of the load off, I’d
    love to write some articles for your blog in exchange for a link back
    to mine. Please send me an email if interested.
    Thanks!

  • internees

    2017年4月12日 下午1:09

    After study some of the blog posts in your site now, and i genuinely such
    as your technique for blogging. I bookmarked it to my bookmark site list and
    are checking back soon. Pls look into my web site likewise and make me
    aware what you consider.

  • how to catch largemouth Bass

    2017年5月3日 上午12:49

    What’s Taking place i’m new to this, I stgumbled upon this I have discovered It
    absolutely helpful and it has helped mee out loads. I am hoping to give a contributionn & assist other customers like its aidsed me.
    Good job.

发表评论

电子邮件地址不会被公开。 必填项已用*标注

标签云