一、环境配置
1.1 安装Realm
- GitHub下载
- CocoaPods
1.2 Xcode插件
下载完打开plugin/RealmPlugin.xcodeproj
并运行,重启Xcode,新建一个RLMObject类,如下:
1.3 Realm Browser(可视化工具 )
在App Store
中下载安装 Realm Browser,帮助更好查看数据的增删改查
二、实践&原理
2.1 模型属性
Post
Post.h
#import <Realm/Realm.h>
@class User; // 避免交叉引用
RLM_ARRAY_TYPE(Post)
@interface Post : RLMObject
@property User *user; // 对一
@property NSString *postID;
@property NSString *title;
@property NSDate *timestamp;
@property NSData *content;
@property NSInteger look; // defaultPropertyValues
@property NSNumber<RLMBool> *isTop; // 常量在Realm数据库里边是不可以为空,所以存储为NSNumber
@property RLMArray <Post *><Post> *comments; // 对多
// 不支持CGFloat,请使用float和double
@end
Post.m
#import "Post.h"
@implementation Post
// 可空属性,决定属性是否可以为nil
+ (NSArray<NSString *> *)requiredProperties {
return @[@"title"];
}
+ (NSDictionary *)defaultPropertyValues {
return @{
@"look": @(0)
};
}
// 忽略属性
+ (NSArray *)ignoredProperties {
return @[];
}
// 索引属性,支持NSString,NSNumber(包括常量),NSDate
+ (NSArray<NSString *> *)indexedProperties {
return @[@"title", @"timestamp"];
}
// 主键(唯一性)
+ (NSString *)primaryKey {
return @"postID";
}
User
User.h
#import <Realm/Realm.h>
@interface User : RLMObject
@property NSString *nickName;
@property NSString *hobby;
@property (readonly) RLMLinkingObjects *posts; // 对多(RLMLinkingObjects继承自RLMResults)
@end
// This protocol enables typed collections. i.e.:
// RLMArray<User *><User>
RLM_ARRAY_TYPE(User)
User.m
+ (NSDictionary<NSString *,RLMPropertyDescriptor *> *)linkingObjectsProperties {
return @{
@"posts": [RLMPropertyDescriptor descriptorWithClass:Post.class propertyName:@"user"]
};
}
Test
Post *post = [[Post alloc] initWithValue:@{@"postID": @"5201314", @"title": @"undefined"}];
User *user = [[User alloc] init];
user.hobby = @"tennis";
post.user = user;
RLMRealm *realm = [RLMRealm defaultRealm];
[realm transactionWithBlock:^{
[realm addObject:post];
[realm addObject:user];
NSLog(@"%@", user.posts);
}];
2.2 数据库操作
增
[realm transactionWithBlock:^{
[realm addObject:post]; // 增
}];
删
[realm transactionWithBlock:^{
[realm deleteObject:post];
[realm deleteAllObjects]; // 删
}];
改
针对某个对象修改&实时性
[realm transactionWithBlock:^{
post.timestamp = [NSDate date]; // 改
}];
通过主键更新
Post *postReset = [[Post alloc] init];
postReset.postID = @"52011314";
postReset.title = @"真香";
postReset.timestamp = [NSDate date];
[realm transactionWithBlock:^{
[realm addOrUpdateObject:postReset];
}];
批量修改(支持KVC)
RLMResults *results = [Post allObjects];
[realm transactionWithBlock:^{
[results setValue:[NSDate date] forKey:@"timestamp"];
}];
查
等于
RLMResults *results = [Post objectsWhere:@"title == %@", @"undefined"];
Post *postBeFound = [results firstObject];
[realm transactionWithBlock:^{
post.title = @"hihihi";
}];
NSLog(@"%@", postBeFound);
大于小于
// AND
RLMResults *results = [Post objectsWhere:@"look < 20 AND look > 0"];
// BETWEEN
RLMResults *results = [Post objectsWhere:@"look BETWEEN {10, 80}"];
包含
// [c]不区分大小写
RLMResults *results = [Post objectsWhere:@"title CONTAINS[c] 'hi'"];
链式检索
RLMResults *results = [Post objectsWhere:@"comments.@count > 0"];
RLMResults *finalResults = [results objectsWhere:@"look > 10"];
NSLog(@"%@", finalResults);
排序
// 不影响数据库中的排序
RLMResults *results = [Post allObjects];
RLMResults *sortResult = [results sortedResultsUsingKeyPath:@"look" ascending:YES];
NSLog(@"%@", sortResult);
分页
没有分页功能,通过惰性加载
2.3 数据库基本配置
查看路径及相关配置:
RLMRealmConfiguration *defaultRealm = [RLMRealmConfiguration defaultConfiguration];
NSLog(@"%@", defaultRealm);
打印:
其中几个参数:
参数 | 意义 |
---|---|
inMemoryIdentifier | |
encryptionKey | |
readOnly | |
schemaVersion | |
deleteRealmIfMigrationNeeded | |
shouldCompactOnLaunch | |
dynamic | |
customSchema |
RLMRealmConfiguration *defaultRealm = [RLMRealmConfiguration defaultConfiguration];
defaultRealm.fileURL = [[NSBundle mainBundle] URLForResource:@"default" withExtension:@"realm"];
defaultRealm.readOnly = YES;
RLMRealm *realm = [RLMRealm realmWithConfiguration:defaultRealm error:nil];
// 内存数据库
RLMRealmConfiguration *memoryRealm = [RLMRealmConfiguration defaultConfiguration];
memoryRealm.inMemoryIdentifier = @"memoryDB";
RLMRealm *realmMem = [RLMRealm realmWithConfiguration:memoryRealm error:nil];
// 数据库写入通知
2.4 数据库版本迁移
RLMRealmConfiguration *realmConf = [RLMRealmConfiguration defaultConfiguration];
uint64_t currentVersion = 3;
realmConf.schemaVersion = currentVersion;
[realmConf setMigrationBlock:^(RLMMigration * _Nonnull migration, uint64_t oldSchemaVersion) {
if(oldSchemaVersion < currentVersion) {
[migration enumerateObjects:NSStringFromClass([Post class]) block:^(RLMObject * _Nullable oldObject, RLMObject * _Nullable newObject) {
newObject[@"hot"] = @([oldObject[@"look"] integerValue]);
}];
// 属性重命名
[migration renamePropertyForClass:NSStringFromClass([Post class]) oldName:@"title" newName:@"postTitle"];
}
}];
RLMRealm *realm = [RLMRealm realmWithConfiguration:realmConf error:nil];
常量在RLM数据库中不能为空
三、比较
RLMObject 与 NSManagerObject
不可重写setter和getter
RLMObject:支持ignore属性;NSManagerObject需要@dynamic属性
【参考】
1、官方文档