git地址:https://github.com/realm/realm-cocoa
官网地址:https://realm.io/
xcode工具包:https://github.com/realm/realm-cocoa
realm studio下载地址:https://github.com/realm/realm-studio
配置开发环境:pod比较简单
如果单元测试中要使用要记得在单元测试target中同样引入库
# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'
target 'TestRealm' do
# Comment the next line if you don't want to use dynamic frameworks
use_frameworks!
pod 'Realm'
# Pods for TestRealm
target 'TestRealmTests' do
inherit! :search_paths
pod 'Realm'
# Pods for testing
end
target 'TestRealmUITests' do
# Pods for testing
end
end
安装数据库管理工具:Real studio(https://github.com/realm/realm-studio)
安装xcode插件包:(官网就有)
#import
模型类中引入属性要注意写法
#import
@interface Student : RLMObject
@property int student_number;
@property NSString *name;
@end
// This protocol enables typed collections. i.e.:
// RLMArray
RLM_ARRAY_TYPE(Student)
.m文件中设置通过复写primaryKey方法设置主键
+ (NSString *)primaryKey{
return "student_number";
}
// 可以用数组,也可以用字典,(如果用数组要保证和模型一致)
// Student *student = [[Student alloc]initWithValue:@{@"student_number":@1,@"name":@"cy"}];
Student *student = [[Student alloc]initWithValue:@[@1,@"cy"]];
RLMRealm *realm = [RLMRealm defaultRealm];
//普通写法
// [realm beginWriteTransaction];// 开始写入
// [realm addObject:student];// 存储数据
//[realm comm itWriteTransaction];//提交
// 也可以这样写
[realm transactionWithBlock:^{
[realm addObject:student];
}];
也可以用不用初始化数据模型用以下方法实现
RLMRealm *realm = [RLMRealm defaultRealm];
[realm transactionWithBlock:^{
[Student createInDefaultRealmWithValue:@[@2,@"liutiesong"]];
}];
通过realm studio打开文件查看写入数据
注:
Student *student = [[Student alloc]initWithValue:@[@3,@"test"]];
RLMRealm *realm = [RLMRealm defaultRealm];
[realm transactionWithBlock:^{
[realm addObject:student];
}];
[realm transactionWithBlock:^{
student.name = @"finalTest";
}];
RLMRealm *realm = [RLMRealm defaultRealm];
RLMResults *result = [Student objectsWhere:@"name = 'finalTest'"];
Student *student = result.firstObject;
[realm transactionWithBlock:^{
student.name = @"cy";
}];
注意:
Student *student = [[Student alloc]initWithValue:@[@2,@"test-2"]];
RLMRealm *realm = [RLMRealm defaultRealm];
[realm transactionWithBlock:^{
[realm addOrUpdateObject:student];
}];
RLMRealm *realm = [RLMRealm defaultRealm];
[realm transactionWithBlock:^{
[Student createOrUpdateInRealm:realm withValue:@[@2,@"test2"]];
}];
RLMRealm *realm = [RLMRealm defaultRealm];
RLMResults *result = [Student objectsWhere:@"name = 'test2'"];
Student *student = result.firstObject;
[realm transactionWithBlock:^{
[realm deleteObject:student];
}];
RLMRealm *realm = [RLMRealm defaultRealm];
[realm transactionWithBlock:^{
[realm deleteAllObjects];
}];
RLMRealm *realm = [RLMRealm defaultRealm];
RLMResults *results = [Student allObjects];
for (Student *student in results) {
[realm transactionWithBlock:^{
[realm deleteObject:student];
}];
}
Student *student = [Student objectInRealm:realm forPrimaryKey:@2];
[realm transactionWithBlock:^{
[realm deleteObject:student];
}];
RLMResults *studentResult = [Student allObjects];
NSLog(@"%@",studentResult);
RLMResults *result = [Student objectsWhere:@"name = 'test2'"];
RLMResults *studentResult = [Student allObjects];
RLMResults *sortedResult = [studentResult sortedResultsUsingKeyPath:@"name" ascending:YES];
可以支持多条件链式叠加查询
RLMResults *studentResult = [Student objectsWhere:@"student_number > 2"];
RLMResults *secOndStudentResults= [studentResult objectsWhere:@"student_number
RLMResults *allStudents = [Student allObjects];
int limit = 2;
int offset = 1;
for (int i = offset; i
在属性声明时,realm不支持的类型可以在.m文件中复写ignore方法,或者使用readonly声明
@property (readonly)UIImage *image;
@property NSData *imageData;
+ (NSArray *)ignoredProperties
{
return @[@"image"];
}
- (UIImage *)image{
return [UIImage imageWithData:self.imageData];;
}
↑当需要读取UIImage时,可以重写image的set方法来获取图片数据(在数据模型的.m文件中)
数据存储代码:
// 可以用数组,也可以用字典,(如果用数组要保证和模型一致)
RLMRealm *realm = [RLMRealm defaultRealm];
Student *student = [[Student alloc]init];
student.name = @"cy";
student.student_number = 1;
NSString *filePath = [[NSBundle mainBundle]pathForResource:@"1.jpg" ofType:nil];
student.imageData = [NSData dataWithContentsOfFile:filePath];
[realm transactionWithBlock:^{
[realm addOrUpdateObject:student];
}];
#import "StudentDetails.h"
@property RLMArray *details;
创建一个RLMObject类型的模型用来存放数组内数据:
#import
@interface StudentDetails : RLMObject
@property NSString *detailID;
@end
// This protocol enables typed collections. i.e.:
// RLMArray
RLM_ARRAY_TYPE(StudentDetails)
创建两个数据模型Zoo和Cow,Zoo中包含一个Cow对象如下:
#import
#import "Cow.h"
@interface Zoo : RLMObject
@property int zooId;
@property NSString *name;
@property Cow *cow;
@end
RLM_ARRAY_TYPE(Zoo)
#import
@interface Cow : RLMObject
@property int cowId;
@property NSString *name;
@end
RLM_ARRAY_TYPE(Cow)
设置对应的 cowId和zooId为主键
Zoo *zoo = [Zoo new];
zoo.zooId = 1;
zoo.name = @"木有鱼丸";
Cow *cow = [Cow new];
cow.cowId = 1;
cow.name = @"奶牛1号";
zoo.cow = cow;
RLMRealm *realm = [RLMRealm defaultRealm];
[realm transactionWithBlock:^{
[realm addObject:zoo];
}];
#import
#import "Cow.h"
@interface Zoo : RLMObject
@property int zooId;
@property NSString *name;
@property RLMArray *cows;
@end
RLM_ARRAY_TYPE(Zoo)
Zoo *zoo = [Zoo new];
zoo.zooId = 1;
zoo.name = @"木有鱼丸";
Cow *cow = [Cow new];
cow.cowId = 1;
cow.name = @"奶牛1号";
Cow *cow2 = [Cow new];
cow2.cowId = 2;
cow2.name = @"奶牛2号";
[zoo.cows addObject:cow];
[zoo.cows addObject:cow2];
RLMRealm *realm = [RLMRealm defaultRealm];
[realm transactionWithBlock:^{
[realm addObject:zoo];
}];
数据库:
1.使用@class声明避免循环引用,使用RLMLinkingObjects创建zoo属性
#import
@class Zoo;
@interface Cow : RLMObject
@property int cowId;
@property NSString *name;
@property(readonly) RLMLinkingObjects *zoo;
@end
RLM_ARRAY_TYPE(Cow)
2.m文件中通过协议方法构建反向关系
#import "Cow.h"
@implementation Cow
+ (NSString *)primaryKey{
return @"cowId";
}
// 关联方法
+ (NSDictionary *)linkingObjectsProperties{
// 通过属性描述器关联
return @{@"zoo":[RLMPropertyDescriptor descriptorWithClass:NSClassFromString(@"Zoo") propertyName:@"cows"]};
}
@end
测试获取数据
Zoo *zoo = [Zoo allObjects].firstObject;
NSLog(@"打印数据%@",zoo.cows.firstObject.zoo);
2020-09-29 18:47:53.510317+0800 TestRealm[30907:35745028] 打印数据RLMLinkingObjects (
[0] Zoo {
zooId = 1;
name = 木有鱼丸;
cows = RLMArray (
[0] Cow {
cowId = 1;
name = 奶牛1号;
},
[1] Cow {
cowId = 2;
name = 奶牛2号;
}
);
}
)
默认情况下,属性是可空的,如果想要强制要求某个属性必须非空可以如下操作:
+ (NSArray *)requiredProperties{
return @[@"name"];;
}
+ (NSDictionary *)defaultPropertyValues{
return @{@"name":@"数据不存在"};
}
@property(readonly) NSString *name;
+ (NSArray *)ignoredProperties{
return @[@"name"];;
}
@property(nonatomic,strong) RLMNotificationToken *token;
- (void)setUp{
[super setUp];
RLMRealm *realm = [RLMRealm defaultRealm];
self.token = [realm addNotificationBlock:^(RLMNotification _Nonnull notification, RLMRealm * _Nonnull realm) {
NSLog(@"监听到通知");
}];
}
- (void)tearDown{
[self.token invalidate];
[super tearDown];
}
- (void)testOneToOne{
Cow *cow = [[Cow alloc]initWithValue:@{@"cowId":@1,@"name":@"test"}];
RLMRealm *realm = [RLMRealm defaultRealm];
[realm transactionWithBlock:^{
[realm addObject:cow];
}];
}
@property(nonatomic,strong) RLMNotificationToken *token;
- (void)setUp{
[super setUp];
RLMResults *result = [Cow allObjects];
self.token = [result addNotificationBlock:^(RLMResults * _Nullable results, RLMCollectionChange * _Nullable change, NSError * _Nullable error) {
NSLog(@"%@____%@___%@",results,change,error);
}];
}
- (void)tearDown{
[self.token invalidate];//注销监听
[super tearDown];
}
- (void)testOneToOne{
Cow *cow = [[Cow alloc]initWithValue:@{@"cowId":@1,@"name":@"test"}];
RLMRealm *realm = [RLMRealm defaultRealm];
[realm transactionWithBlock:^{
[realm addObject:cow];
}];
}
可以在RLMCollectionChange中获取具体修改的内容
创建数据模型
#import
@interface UserData : RLMObject
@property int userDataId;
@end
RLM_ARRAY_TYPE(UserData)
通过修改尾缀根据用户区分数据库
- (void)testExample {
[self setDefalutRealmForUser:@"test1"];
RLMRealm *realm = [RLMRealm defaultRealm];
UserData *data = [UserData new];
data.userDataId = 1;
[realm transactionWithBlock:^{
[realm addObject:data];
}];
[self setDefalutRealmForUser:@"test2"];
RLMRealm *realm2 = [RLMRealm defaultRealm];
UserData *data2 = [UserData new];
data2.userDataId = 1;
[realm2 transactionWithBlock:^{
[realm2 addObject:data2];
}];
}
- (void)setDefalutRealmForUser:(NSString*)userId{
RLMRealmConfiguration *cOnfig= [RLMRealmConfiguration defaultConfiguration];
config.fileURL = [[[config.fileURL URLByDeletingLastPathComponent]URLByAppendingPathComponent:userId] URLByAppendingPathExtension:@"realm"];
[RLMRealmConfiguration setDefaultConfiguration:config];
}
将config中的readObly参数设置为YES
- (void)testReadOnly{
RLMRealmConfiguration *cOnfig= [RLMRealmConfiguration defaultConfiguration];
config.readOnly= YES;
RLMRealm *realm = [RLMRealm realmWithConfiguration:config error:nil];
UserData *data = [UserData new];
data.userDataId = 100;
[realm transactionWithBlock:^{
[realm addObject:data];
}];
}
- (void)testDeleteDataBase{
[self setDefalutRealmForUser:@"test1"];
NSFileManager *manager = [NSFileManager defaultManager];
RLMRealmConfiguration *cOnfig= [RLMRealmConfiguration defaultConfiguration];
NSArray *realmFileURLS = @[
config.fileURL,
[config.fileURL URLByAppendingPathExtension:@"lock"],
[config.fileURL URLByAppendingPathExtension:@"log_a"],
[config.fileURL URLByAppendingPathExtension:@"log_b"],
[config.fileURL URLByAppendingPathExtension:@"note"]
];
for (NSURL *url in realmFileURLS) {
NSError *error = nil;
[manager removeItemAtURL:url error:&error];
if (error) {
//容错处理
}
}
}
#import
@interface UserData : RLMObject
@property int userDataId;
@end
RLM_ARRAY_TYPE(UserData)
#import
@interface UserData : RLMObject
@property int userDataId;
@property NSString *userName;
@end
RLM_ARRAY_TYPE(UserData)
- (void)setUp{
[super setUp];
RLMRealmConfiguration *cOnfig= [RLMRealmConfiguration defaultConfiguration];
// 叠加版本号(每次更新版本号要比上一次高)
int newVersion = 1;
config.schemaVersion = newVersion;
// 数据迁移
[config setMigrationBlock:^(RLMMigration * _Nonnull migration, uint64_t oldSchemaVersion) {
if (oldSchemaVersion
- (void)testMigration{
UserData *user = [UserData new];
user.userDataId = 1;
user.userName = @"cy";
RLMRealm *realm = [RLMRealm defaultRealm];
[realm transactionWithBlock:^{
[realm addObject:user];
}];
}
合并或保留旧数据:
原数据库数据:
迁移后数据:
** 代码 **
模型层修改
#import
@interface UserData : RLMObject
@property int userDataId;
//@property NSString *firstName;
//@property NSString *lastName;
@property NSString *name;
@end
RLM_ARRAY_TYPE(UserData)
数据库迁移操作
- (void)setUp{
[super setUp];
RLMRealmConfiguration *cOnfig= [RLMRealmConfiguration defaultConfiguration];
// 叠加版本号(每次更新版本号要比上一次高)
int newVersion = 5;
config.schemaVersion = newVersion;
// 数据迁移
[config setMigrationBlock:^(RLMMigration * _Nonnull migration, uint64_t oldSchemaVersion) {
if (oldSchemaVersion
#import
@interface UserData : RLMObject
@property int userDataId;
//@property NSString *firstName;
//@property NSString *lastName;
//@property NSString *name;
@property NSString *fullName;
@end
RLM_ARRAY_TYPE(UserData)
- (void)setUp{
[super setUp];
RLMRealmConfiguration *cOnfig= [RLMRealmConfiguration defaultConfiguration];
// 叠加版本号(每次更新版本号要比上一次高)
int newVersion = 4;
config.schemaVersion = newVersion;
// 数据迁移
[config setMigrationBlock:^(RLMMigration * _Nonnull migration, uint64_t oldSchemaVersion) {
if (oldSchemaVersion