Realm Objective‑C 2.4.3 官方文档的翻译

2024-01-28 19:50

本文主要是介绍Realm Objective‑C 2.4.3 官方文档的翻译,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

原文地址https://realm.io/docs/objc/latest/

开始

Realm Objective-C使能够以安全,持久和快速的方式有效地编写应用程序的模型层,例子如下:

// Define your models like regular Objective‑C classes
@interface Dog : RLMObject
@property NSString *name;
@property NSData   *picture;
@property NSInteger age;
@end
@implementation Dog
@end
RLM_ARRAY_TYPE(Dog)
@interface Person : RLMObject
@property NSString             *name;
@property RLMArray<Dog *><Dog> *dogs;
@end
@implementation Person
@end// Use them like regular Objective‑C objects
Dog *mydog = [[Dog alloc] init];
mydog.name = @"Rex";
mydog.age = 1;
mydog.picture = nil; // properties are nullable
NSLog(@"Name of dog: %@", mydog.name);// Query Realm for all dogs less than 2 years old
RLMResults<Dog *> *puppies = [Dog objectsWhere:@"age < 2"];
puppies.count; // => 0 because no dogs have been added to the Realm yet// Persist your data easily
RLMRealm *realm = [RLMRealm defaultRealm];
[realm transactionWithBlock:^{[realm addObject:mydog];
}];// Queries are updated in realtime
puppies.count; // => 1// Query and update the result in another thread
dispatch_async(dispatch_queue_create("background", 0), ^{Dog *theDog = [[Dog objectsWhere:@"age == 1"] firstObject];RLMRealm *realm = [RLMRealm defaultRealm];[realm beginWriteTransaction];theDog.age = 3;[realm commitWriteTransaction];
});
If you have an app that is presently using Core Data and have been considering switching to Realm, we recently published an article discussing how to go about doing this. Go check it out!

如果你打算使用realm替换Core Data,我们(官方)最近将出一片文章讲述如何替换。

环境要求

  • iOS7 or later,macOS 10.9 或者以后版本,tvOS 和watchOS的所有版本。
  • 要求Xcode 8.0及其以后版本。支持Swift2.x和Xcode 7.3最后一个版本是Realm OC 2.3.0

安装

以OC及frameworks的情况说明
1. 下载最新的release版本的Realm 并且解压
2. 在Xcode工程中找到“General”设置项,把Realm.framework 从 ios/dynamic/目录中拖到“Embedded Binaries”选项中,确保在拖拽过程中选中“Copy items if needed ”(如果在多平台中使用realm时除外),点击“Finish”就可以了

导入Realm Framework

在OC源文件的最顶部,使用#import <Realm/Realm.h> 导入Realm OC 然后便可以使用Realm的相关特性

RLMArray属性

在OC中我们依赖协议一致性使Realm知道RLMArray一对多的关系中包含的对象的类型。在Swift中是不可能的,你可以使用以下语法代替:

class Person: RLMObject {dynamic var dogs = RLMArray(objectClassName: Dog.className())
}

其结果等同于

@interface Person : RLMObject
@property RLMArray<Dog *><Dog> *dogs;
@end

Realm Browser

官方提供一个独立的Mac app来查看和编辑realm databases
这里写图片描述
你可以使用菜单项*Tools > Generate demo database,用一些简单的数据生成一个测试的数据库。
如果在寻找app中寻找Realm file,你可以参阅StackOverflow answer 这篇文章。你可以在appstore中下载到该应用。

Xcode Plugin

官方提供的Xcode插件可以很容易的生成新的Realm对象。这里写图片描述
通过Alcatraz 找到“RealmPlugin”去安装Realm plugin插件。
你也可以通过打开[release.zip]中的(https://static.realm.io/downloads/objc/realm-objc-2.4.3.zip)plugin/RealmPlugin.xcodeproj手动的去添加,并且点击build,你需要关闭和重启Xcode。

例子

你可以在官方发布的release.zip 中的examples /下找到iOS和OS X的示例应用程序,演示如何使用Realm的许多功能,如迁移,如何使用UITableViewControllers,加密,命令行工具等

Models

Realm 数据模型使用普通的带属性的类来定义。简单的继承RLMObject对象或者现有的模型去创建Realm data模型对象。Realm和其他的OC对象一样,你可以添加属性和协议并使用它们。主要的限制是你只能在创建它的线程上使用一个对象,你不能直接访问它的任何持久化属性的ivar。
如果你已经安装了官方的Xcode插件,将会有一个很好的模板,在RLMArray对话框中创建接口和实现文件。
关系和嵌套的数据结构和模型可以简单的通过目标类型的属性或对象的类型列表的RLMArrays简单建模

#import <Realm/Realm.h>
@class Person;
// Dog model
@interface Dog : RLMObject
@property NSString *name;
@property Person   *owner;
@end
RLM_ARRAY_TYPE(Dog) // define RLMArray<Dog>// Person model
@interface Person : RLMObject
@property NSString             *name;
@property NSDate               *birthdate;
@property RLMArray<Dog *><Dog> *dogs;
@end
RLM_ARRAY_TYPE(Person) // define RLMArray<Person>
// Implementations
@implementation Dog
@end // none needed
@implementation Person
@end // none needed

See RLMObject for more details.

Supported Types

Realm支持以下属性类型:BOOLboolintNSIntegerlonglong longfloatdoubleNSStringNSDateNSData和用特定类型标记的NSNumber
不建议使用CGFloat属性,因为类型不是平台独立的。
可以使用RLMArray <Object *> <Object>RLMObject子类来建模关系,例如to-many和to-one。
RLMArrays支持编译时Objective-C泛型(如果可用)(Xcode 7或更高版本)。下面是属性定义的不同组件的含义,以及它们为什么有用:

  • RLMArray:属性类型.
  • <Object *>:泛型特化.这有助于防止在编译时使用错误对象类型的数组.
  • <Object>RLMArray遵循的协议。这使得Realm知道如何在运行时专门化此模型的模式

Relationships

RLMObject可以通过使用RLMObjectRLMArray属性彼此链接。 RLMArray具有非常类似于NSArray的接口,并且可以使用索引下标来访问包含在RLMArray中的对象。与NSArrays不同,RLMArrays是类型化的,并且只保存单个子类类型的RLMObject。有关更多详细信息,请参阅RLMArray。
假设你的Person类已经定义(见上文),让我们创建另一个类Dog:

// Dog.h
@interface Dog : RLMObject
@property NSString *name;
@end

To-One Relationships

对于多对一或一对一关系,只需使用RLMObject子类的类型声明一个属性:

// Dog.h
@interface Dog : RLMObject
// ... other property declarations
@property Person *owner;
@end

你可以像使用任何其他属性一样使用此属性:

Person *jim = [[Person alloc] init];
Dog    *rex = [[Dog alloc] init];
rex.owner = jim;

使用RLMObject属性时,可以使用正常属性语法访问嵌套属性。例如rex.owner?.address.country将遍历对象图并根据需要自动从Realm中获取每个对象。

To-Many Relationships

你可以使用RLMArray属性定义一对多关系。 RLMArrays包含单个类型的其他RLMObject,并且具有非常类似于NSMutableArray的接口。
RLMArray可能包含对同一个Realm对象的多个引用,包括具有主键的对象。例如,你可以创建一个空的RLMArray并将相同的对象插入它三次;如果访问索引0,1和2中的任一个处的元素,则RLMArray将返回该对象。
要在链接到多个dog的Person模型上添加“dogs”属性,我们必须首先定义一个RLMArray <Dog>类型。这通过在相应模型接口底部的宏来完成:

// Dog.h
@interface Dog : RLMObject
// ... property declarations
@end
RLM_ARRAY_TYPE(Dog) // Defines an RLMArray<Dog> type

RLM_ARRAY_TYPE宏创建一个协议,以使用RLMArray <Dog>语法。如果宏未放置在模型接口的底部,则可能必须前置声明模型类。
然后可以声明RLMArray <Dog>类型的属性:

// Person.h
@interface Person : RLMObject
// ... other property declarations
@property RLMArray<Dog *><Dog> *dogs;
@end

你可以照常访问和赋值RLMArray属性

// Jim is owner of Rex and all dogs named "Fido"
RLMResults<Dog *> *someDogs = [Dog objectsWhere:@"name contains 'Fido'"];
[jim.dogs addObjects:someDogs];
[jim.dogs addObject:rex];

请注意,虽然可以为RLMArray属性指定nil,但这只能“清空”数组,而不是删除数组。这意味着可以始终将对象添加到RLMArray属性,即使将其设置为nil。
RLMArray属性保证保留它们的插入顺序。

Inverse Relationships

链接是单向的。因此,如果一个to-many属性Person.dogs链接到一个Dog实例,并且一个属性Dog.owner链接到Person,这些链接是彼此独立的。将Dog附加到Person实例的dogs属性不会自动将dogowner属性设置为此Person。因为手动同步的关系对容易出错,复杂和重复信息,Realm提供链接对象属性来表示这些逆关系。
使用链接对象属性,你可以从特定属性获取链接到给定对象的所有对象。例如,Dog对象可以具有名为owner的属性,其中包含在其dogs属性中具有此确切Dog对象的所有Person对象。这通过使属性类型为RLMLinkingObjects,然后覆盖+ [RLMObject linkingObjectsProperties]来指示所有者与Person模型对象的关系来实现。(太TM的绕了,搞了半个小时才弄清楚)

@interface Dog : RLMObject
@property NSString *name;
@property NSInteger age;
@property (readonly) RLMLinkingObjects *owners;
@end
@implementation Dog
+ (NSDictionary *)linkingObjectsProperties {return @{@"owners": [RLMPropertyDescriptor descriptorWithClass:Person.class propertyName:@"dogs"],};
}
@end

Optional Properties

默认情况下,NSString *NSData *NSDate *属性允许将它们设置为nil。如果要求一个值存在,可以覆盖RLMObject子类上的+ requiredProperties方法。例如,使用以下模型定义,尝试将人员的名称设置为nil将抛出异常,但允许将其生日设置为nil

@interface Person : RLMObject
@property NSString *name;
@property NSDate *birthday;
@end@implementation Person
+ (NSArray *)requiredProperties {return @[@"name"];
}
@end

使用NSNumber *属性存储可选数字。因为Realm对不同类型的数字使用不同的存储格式,所以必须使用RLMIntRLMFloatRLMDoubleRLMBool之一来标记该属性。分配给该属性的所有值都将转换为指定的类型。
请注意,NSDecimalNumber值只能分配给RLMDouble Realm属性,Realm将存储该值的双精度浮点近似值,而不是底层十进制值。
例如,如果我们想要存储该人的年龄而不是他们的生日,而当你不知道该人的年龄时仍然允许nil

@interface Person : RLMObject
@property NSString *name;
@property NSNumber<RLMInt> *age;
@end@implementation Person
+ (NSArray *)requiredProperties {return @[@"name"];
}
@end

RLMObject子类属性总是可以为nil,因此不能包含在requiredProperties中,而RLMArray不支持存储nil

Cheatsheet

此表提供了声明模型属性的方便参考。

TypeNon-optionalOptional
Bool@property BOOL value;@property NSNumber<RLMBool> *value;
Int@property int value;@property NSNumber<RLMInt> *value;
Float@property float value;@property NSNumber<RLMFloat> *value;
Double@property double value;@property NSNumber<RLMDouble> *value;
String@property String *value;@property NSString *value;
Data@property NSData *value;@property NSData *value;
Date@property NSDate *value;@property NSDate *value;
Objectn/a: must be optional@property Object *value;
List@property RLMArray<Object *><Object> *value;n/a: must be non-optional
LinkingObjects@property (readonly) RLMLinkingObjects<Object *> *value;n/a: must be non-optional

1)Objective-C引用类型的必需属性必须与以下语句结合声明:

@implementation MyModel
+ (NSArray *)requiredProperties {return @[@"value"];
}
@end

2)链接对象属性必须与+ linkingObjectsProperties方法组合声明

@implementation MyModel
+ (NSDictionary *)linkingObjectsProperties {return @{ @"property": [RLMPropertyDescriptor descriptorWithClass:Class.class propertyName:@"link"] };
}
@end

Property Attributes

注意,Realm忽略ObjectiveC属性修饰符,如非原子,原子,强,复制,弱等等。这是因为Realm有自己的优化存储语义。所以为了避免误导,我们建议编写没有任何属性修饰符的模型。但是,如果设置属性修饰符,它们将一直使用,直到将RLMObject添加到Realm潜台词就是一旦添加到Realm这些修饰符就不一定好用了)。 getter和setter的自定义名称正常工作,而不管RLMObject是否由Realm管理。如果使用Realm Objective-C和Swift,模型属性需要动态var属性,以便这些属性成为底层数据库数据的访问器。(其实就是告诉不要添加任何属性修饰符)

Indexed Properties

覆盖+ indexedProperties以设置模型中应该索引哪些属性:

@interface Book : RLMObject
@property float price;
@property NSString *title;
@end@implementation Book
+ (NSArray *)indexedProperties {return @[@"title"];
}
@end

Realm支持对字符串,整数,布尔和NSDate属性的索引。
索引属性将大大加快查询的速度,其中的属性被比较相等(即=和IN运算符),代价是较慢的插入

Default Property Values

重写 + defaultPropertyValues在每次创建对象时提供默认值

@interface Book : RLMObject
@property float price;
@property NSString *title;
@end@implementation Book
+ (NSDictionary *)defaultPropertyValues {return @{@"price" : @0, @"title": @""};
}
@end

Auto-Updating Objects

RLMObject实例是实时的,自动更新视图到底层数据,这意味着对象不必被刷新。修改对象的属性将立即反映在引用同一对象的任何其他实例中

Dog *myDog = [[Dog alloc] init];
myDog.name = @"Fido";
myDog.age = 1;[realm transactionWithBlock:^{[realm addObject:myDog];
}];Dog *myPuppy = [[Dog objectsWhere:@"age == 1"] firstObject];
[realm transactionWithBlock:^{myPuppy.age = 2;
}];myDog.age; // => 2

RLMObject的这个方面不仅保持Realm的快速和高效,它允许你的代码更简单和更多的反应。例如,如果的UI代码依赖于特定的Realm对象,则不需要担心在触发UI重绘之前刷新或重新获取它。(潜台词就是realm可以快到UI渲染之前肯定能够返回给你数据,作死的不算
可以订阅Realm通知,以了解对象中的Realm数据何时更新,指示应用程序的UI应该何时刷新。或者,可以使用键值观察在更新RLMObject的特定属性时通知。

Primary Keys

重写+ primaryKey以设置模型的主键。声明主键允许有效地查找和更新对象,并强制实现每个值的唯一性。将带有主键的对象添加到域后,无法更改主键

@interface Person : RLMObject
@property NSInteger id;
@property NSString *name;
@end@implementation Person
+ (NSString *)primaryKey {return @"id";
}
@end

Ignored Properties

重写+ ignoredProperties以防止Realm持久化模型属性。 Realm不会干扰这些属性的正常操作:它们将由ivars支持,并且可以自由覆盖其setter和getter。

@interface Person : RLMObject
@property NSInteger tmpID;
@property (readonly) NSString *name; // read-only properties are automatically ignored
@property NSString *firstName;
@property NSString *lastName;
@end@implementation Person
+ (NSArray *)ignoredProperties {return @[@"tmpID"];
}
- (NSString *)name {return [NSString stringWithFormat:@"%@ %@", self.firstName, self.lastName];
}
@end

忽略的属性的行为方式与正常Objective-C或Swift类的正常属性完全相同。它们不支持任何Realm特定的功能。例如,它们不能在查询中使用,如果表示相同Realm对象的另一个实例上的相同属性发生更改,则它们不会自动更新它们的值,并且它们在更改时不会触发通知。然而,他们仍然可以使用KVO观察。

Model Inheritance

Realm允许模型进一步子类化,允许在模型之间进行大量代码重用,但是一些Cocoa特性对运行时丰富的类多态性有所帮助(潜台词尽量简单的使用realm的对象)。以下是可能的:

  • 父类上的类方法,实例方法和属性在其子类中继承
  • 将父类作为参数的方法和函数可以对子类进行操作

以下是不可能的:

  • 在多态类之间转换(即,子类到子类,子类到父类,父类到子类,等等)。
  • 同时查询多个类。
  • 多类容器(RLMArray和RLMResults)。
    我们建议使用以下模式的类组合构建包含其他类的逻辑的子类:
// Base Model
@interface Animal : RLMObject
@property NSInteger age;
@end
@implementation Animal
@end
// Models composed with 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// Usage
Duck *duck =  [[Duck alloc] initWithValue:@{@"animal" : @{@"age" : @(3)}, @"name" : @"Gustav" }];

Collections

Realm有几种类型可以帮助表示对象组,我们称之为“Realm集合”

  1. RLMResults一个表示查询返回对象的集合类。
  2. RLMArray一个在模型中表示一对多关系集合类。
  3. RLMLinkingObjects一个表示反向指向关系集合类
  4. RLMCollection一个定义所realm Collections遵循的公共接口协议的类。

Realm集合符合RLMCollection协议,确保它们的行为一致。此协议从NSFastEnumeration继承,以便它可以以与其他Foundation集合相同的方式使用。在此协议中声明了其他公共Realm集合API,例如查询,排序和聚合操作等。 RLMArrays具有扩展超出协议接口的额外的新增操作,例如添加和删除对象。
使用RLMCollection协议,你可以编写可以在任何Realm集合上操作的通用代码

@implementation MyObject
- (void)operateOnCollection:(id<RLMCollection>)collection {// Collection could be either RLMResults or RLMArrayNSLog(@"operating on collection of %@s", collection.objectClassName);
}
@end

Writes

对对象的所有更改(添加,修改和删除)必须在写事务中完成。
Realm对象可以被实例化,并像常规Objective-C对象一样用作非托管对象(即尚未添加到Realm)。要在线程之间共享对象或在应用启动之间重新使用它们,必须将它们添加到同一个Realm中,这是必须在写事务中完成的操作。

由于写事务会产生不可忽略的开销,因此你应该构建的代码以最小化写事务的数量。(尽量少些事务)

因为写事务可能像任何其他磁盘IO操作一样失败,两个 - [RLMRealm transactionWithBlock:]& - [RLMRealm commitWriteTransaction]可选地采用NSError指针参数,因此你可以处理并从诸如磁盘空间不足的故障中恢复。没有其他可恢复的错误。为简洁起见,我们的代码示例不处理这些错误,由使用中在自己的app里处理。

Creating Objects

定义模型后,可以实例化RLMObject子类,并将新实例添加到Realm。参考这个简单的模型:

// Dog model
@interface Dog : RLMObject
@property NSString *name;
@property NSInteger age;
@end// Implementation
@implementation Dog
@end

我们可以通过几种方式创建新对象:

// (1) Create a Dog object and then set its properties
Dog *myDog = [[Dog alloc] init];
myDog.name = @"Rex";
myDog.age = 10;// (2) Create a Dog object from a dictionary
Dog *myOtherDog = [[Dog alloc] initWithValue:@{@"name" : @"Pluto", @"age" : @3}];// (3) Create a Dog object from an array
Dog *myThirdDog = [[Dog alloc] initWithValue:@[@"Pluto", @3]];
  1. 最明显的是使用指定的初始化程序来创建一个对象。请注意,必须先设置所有必需的属性,然后才能将对象添加到Realm。
  2. 还可以使用适当的键和值从字典创建对象。
  3. 最后,可以使用数组实例化RLMObject子类。数组中的值必须与模型中相应的属性具有相同的顺序。

Nested Objects

如果对象的属性为RLMObjectsRLMArrays,则可以使用嵌套数组和/或字典递归设置这些属性。只需用表示其属性的字典或数组替换每个对象.

// Instead of using already existing dogs...
Person *person1 = [[Person alloc] initWithValue:@[@"Jane", @30, @[aDog, anotherDog]]];// ...we can create them inline
Person *person2 = [[Person alloc] initWithValue:@[@"Jane", @30, @[@[@"Buster", @5],@[@"Buddy", @6]]]];

这将适用于嵌套数组和字典的任何组合。请注意,RLMArray只能包含RLMObject,而不是基本类型,如NSString

Adding Objects

如下

// Create object
Person *author = [[Person alloc] init];
author.name    = @"David Foster Wallace";// Get the default Realm
RLMRealm *realm = [RLMRealm defaultRealm];
// You only need to do this once (per thread)// Add to Realm with transaction
[realm beginWriteTransaction];
[realm addObject:author];
[realm commitWriteTransaction];

在将对象添加到Realm之后,可以继续使用它,并且对它所做的所有更改都将保留(并且必须在写事务中完成)。任何更改都可用于提交写入事务时使用相同Realm的其他线程。
请注意,写操作会相互阻塞,如果正在进行多个写操作,它将阻塞它们的线程。这与其他持久性解决方案类似,我们建议对此情况使用通常的最佳做法:将写入操作归到单独的线程。
感谢Realm的MVCC架构,在写事务打开时,读取不会被阻塞。除非需要同时从多个线程同时写入,否则应该倾向于更大的写事务,这些事务在许多细粒度的写事务上做更多的工作。当将写事务提交到Realm时,该Realm的所有其他实例将被通知并自动更新。
有关更多详细信息,请参阅RLMRealmRLMObject

Updating Objects

Realm提供了几种更新对象的方法,所有这些方法都根据情况提供不同的权衡。选择最适合的情况:

Typed Updates

// Update an object with a transaction
[realm beginWriteTransaction];
author.name = @"Thomas Pynchon";
[realm commitWriteTransaction];

Creating and Updating Objects With Primary Keys

如果模型类包含主键,则可以使用 - [RLMRealm addOrUpdateObject:],让Realm根据主键值智能地更新或添加对象。
如果具有主键值为“1”的Book对象已经存在于数据库中,则该对象将被简单地更新。如果它不存在,那么将创建一个全新的Book对象并将其添加到数据库。
还可以通过只传递要更新的值的一部分以及主键来部分更新具有主键的对象:

// Assuming a "Book" with a primary key of `1` already exists.
[realm beginWriteTransaction];
[Book createOrUpdateInRealm:realm withValue:@{@"id": @1, @"price": @9000.0f}];
// the book's `title` property will remain unchanged.
[realm commitWriteTransaction];

在未定义主键的对象上不能调用本章中显示的方法(以OrUpdate结束)。
请注意,在更新对象时,NSNull仍被视为可选属性的有效值。如果提供具有NSNull属性值的字典,那么这些将应用于对象,这些属性将被清空。为确保不会遇到任何意外的数据丢失,请务必在使用此方法时仅提供要更新的属性。(潜台词自己作死造成的问题我们不负责)

Key-Value Coding

RLMObject,RLMResultRLMArray都符合键值编码(KVC)。当需要确定在运行时更新哪个属性时,这可能很有用。
将KVC应用于集合是一种大量更新对象的好方法,无需在为每个项目创建访问器的情况下迭代集合的开销。

RLMResults<Person *> *persons = [Person allObjects];
[[RLMRealm defaultRealm] transactionWithBlock:^{[[persons firstObject] setValue:@YES forKeyPath:@"isFirst"];// set each person's planet property to "Earth"[persons setValue:@"Earth" forKeyPath:@"planet"];
}];

Deleting Objects

将要删除的对象传递给写事务中的 - [RLMRealm deleteObject:]方法

// cheeseBook stored in Realm// Delete an object with a transaction
[realm beginWriteTransaction];
[realm deleteObject:cheeseBook];
[realm commitWriteTransaction];

还可以删除存储在Realm中的所有对象。请注意,Realm文件将保持其在磁盘上的大小,以便有效地将该空间用于未来的对象.

// Delete all objects from the realm
[realm beginWriteTransaction];
[realm deleteAllObjects];
[realm commitWriteTransaction];

Queries

查询返回一个RLMResults实例,它包含一个RLMObjects集合。 RLMResults具有非常类似于NSArray的接口,并且可以使用索引下标访问包含在RLMResults中的对象。与NSArrays不同,RLMResults是类型化的,并且只保留单个子类类型的RLMObject
所有查询(包括查询和属性访问)在Realm中都是延迟的。仅当访问属性时才读取数据。
查询的结果不是数据的副本:修改查询的结果(在写事务中)将直接修改磁盘上的数据。类似地,可以直接从RLMResults中包含的RLMObjects遍历关系图。
执行查询被延迟,直到结果被使用。这意味着链接几个临时RLMResults以排序和过滤的数据不会执行处理中间状态的额外工作。
一旦执行了查询或添加了通知块,RLMResults将保持与Realm中所做的更改一致,并在可能的情况下在后台线程上执行查询。
用于从Realm检索对象的最基本的方法是+ [RLMObject allObjects],它返回从默认领域查询的子类型的所有RLMObject实例的RLMResults

RLMResults<Dog *> *dogs = [Dog allObjects]; // retrieves all Dogs from the default Realm

Filtering

如果你熟悉NSPredicate,那么你已经知道如何在Realm中查询。 RLMObjectsRLMRealmRLMArrayRLMResults都提供了允许通过简单地传递NSPredicate实例,谓词字符串或谓词格式字符串来查询特定RLMObject实例的方法,就像查询NSArray时一样。
例如,以下将通过调用[RLMObject objectsWhere:]来扩展我们前面的示例,以检索默Realm中以“B”开头的color为tan的dog。

// Query using a predicate string
RLMResults<Dog *> *tanDogs = [Dog objectsWhere:@"color = 'tan' AND name BEGINSWITH 'B'"];// Query using an NSPredicate
NSPredicate *pred = [NSPredicate predicateWithFormat:@"color = %@ AND name BEGINSWITH %@",@"tan", @"B"];
tanDogs = [Dog objectsWithPredicate:pred];

有关构建谓词和使用我们的NSPredicate Cheatsheet的更多信息,请参阅Apple’s Predicates编程指南。Realm支持许多常见谓词:

  • 比较操作数可以是属性名称或常量。至少有一个操作数必须是属性名称
  • 支持int,long,long long,float,double和NSDate属性类型的比较运算符==,<=,<,> =,>,!=和BETWEEN。如age == 45
  • 身份比较==,!=,例如[Employee objectsWhere:@“company ==%@”,company]
  • 比较运算符==和!=支持布尔属性
  • 对于NSString和NSData属性,我们支持==,!=,BEGINSWITH,CONTAINS和ENDSWITH运算符,例如name CONTAINS’Ja’
  • 对于NSString属性,LIKE运算符可以用于比较左手属性和右手表达式:?和作为通配符,其中?匹配1个字符,匹配0个或多个字符。例如值LIKE’?bc *’匹配字符串,如“abcde”和“cbc”
  • 字符串的不区分大小写的比较,例如名称CONTAINS [c]’Ja’。注意,只有字符“A-Z”和“a-z”将被忽略
  • Realm支持以下复合运算符:“AND”,“OR”和“NOT”。例如名称BEGINSWITH’J’AND age> = 32
  • 包含操作数IN,例如名称IN {‘Lisa’,’Spike’,’Hachi’}
  • Nil比较==,!=,例如[Company objectsWhere:@"ceo == nil"]。请注意,Realm将nil视为一个特殊值,而不是没有值,因此与SQL nil不同的是它本身。
  • any比较,例如ANY student.age <21
  • RLMArrayRLMResults属性上支持聚合表达式@count,@min,@ max,@ sum和@avg。 [Company objectsWhere:@"employees.@count > 5"]找到所有拥有超过五名员工的公司
    -支持子查询具有以下限制:
    • @count是唯一可以应用于SUBQUERY表达式的运算符。
    • 必须将SUBQUERY(...).@ count表达式与常量进行比较。
    • 尚不支持相关子查询。
      有关更多信息,请参阅[RLMObject objectsWhere:]

Sorting

RLMResults允许基于key路径,属性或一个或多个排序描述符指定排序条件和顺序。例如,以下调用按照名称按字母顺序对从上面的示例返回的dog进行排序:

// Sort tan dogs with names starting with "B" by name
RLMResults<Dog *> *sortedDogs = [[Dog objectsWhere:@"color = 'tan' AND name BEGINSWITH 'B'"]sortedResultsUsingKeyPath:@"name" ascending:YES];

key路径也可以是一对一关系的属性

RLMResults<Person *> *dogOwners = [Person allObjects];
RLMResults<Person *> *ownersByDogAge = [dogOwners sortedResultsUsingKeyPath:@"dog.age" ascending:YES];

注意,sortedResultsUsingKeyPath:sortedResultsUsingProperty:不支持多个属性作为排序条件,并且不能链接(只有最后一次调用sortedResults ...将被使用)。要按多个属性排序,请使用sortedResultsUsingDescriptors:与多个RLMSortDescriptor对象。
更多参考

  • sortedResultsUsingDescriptors:
  • [RLMResults sortedResultsUsingKeyPath:ascending:]

请注意,结果的顺序只能保证在查询排序时保持一致。出于性能原因,不保证保留插入顺序。如果你需要保持插入的顺序,在这里提出一些解决方案。

Chaining

Realm的查询引擎的一个独特属性是链接查询的能力,与传统的数据库相比,只需要为每个连续的查询单独访问数据库服务器,只需很少的事务性开销。
例如,如果我们想要的结果集只是棕褐色的狗和棕褐色的狗的名字也以’B’开头,你可能链接两个查询,像这样:
这里写链接内容

Auto-Updating Results

RLMResults实例是实时的,自动更新视图到底层数据,这意味着结果从来不必重新获取。它们总是在当前线程上反映Realm的当前状态,包括在当前线程上的写事务期间。一个例外是当在枚举中使用for... in时,在枚举开始时,它将始终枚举匹配查询的对象,即使它们中的一些被删除或修改为在枚举期间被过滤器排除。

RLMResults<Dog *> *puppies = [Dog objectsInRealm:realm where:@"age < 2"];
puppies.count; // => 0[realm transactionWithBlock:^{[Dog createInRealm:realm withValue:@{@"name": @"Fido", @"age": @1}];
}];puppies.count; // => 1

这适用于所有RLMResults:所有对象,过滤和链接。
RLMResults的这个属性不仅保持Realm的快速和高效,它允许你的代码更简单和更多的反应。例如,如果的视图控制器依赖于查询的结果,可以将RLMResults存储在属性中并进行访问,而无需在每次访问之前确保刷新其数据。
可以订阅Realm通知,以了解何时更新Realm数据,指示的应用程序的UI应该何时刷新,而无需重新获取RLMResults
由于结果是自动更新,重要的是不要依赖于索引和计数保持不变。唯一一个RLMResults被冻结的时候是快速枚举它.
或者,使用键值编码对RLMResults执行操作
大多数其他数据库技术提供了从查询中分页结果的功能(例如SQLite中的“LIMIT”关键字)。这通常是为了避免从磁盘读取过多,或者将太多的结果一次性拉到内存中。
由于Realm中的查询是延迟的,执行这种分页行为根本不是必需的,因为Realm只有在查询的结果被显式访问时才加载对象。
如果对于UI相关或其他实现原因,需要查询的对象的特定子集,它就像获取RLMResults对象一样简单,并且只读出需要的对象。

/ Loop through the first 5 Dog objects
// restricting the number of objects read from disk
RLMResults<Dog *> *dogs = [Dog allObjects];
for (NSInteger i = 0; i < 5; i++) {Dog *dog = dogs[i];// ...
}
Realms

Realms

The Default Realm

你可能已经注意到,我们已经通过调用[RLMRealm defaultRealm]初始化了对我们的realm变量的访问。该方法返回一个RLMRealm对象,映射到应用程序的文档文件夹(iOS)或应用程序支持文件夹(OS X)下的名为“default.realm”的文件。
Realm API中的许多方法都有接受RLMRealm实例的版本和使用默认领域的便利版本。例如,[RLMObject allObjects]等价于[RLMObject allObjectsInRealm:[RLMRealm defaultRealm]]

请注意,默认的Realm构造函数和默认的Realm方便方法不允许错误处理;你应该只使用它们时,初始化领域不能失败。有关详细信息,请参阅错误处理

Realm Configuration

配置诸如存储Realm文件的位置等操作是通过RLMRealmConfiguration来完成的。每次需要Realm实例时,配置都可以传递到[RLMRealm realmWithConfiguration:config error:&err],或者您可以将[RLMRealmConfiguration setDefaultConfiguration:config]设置为用于默认范围。
例如,假设有一个应用程序,用户必须登录到你的网络后端,并且希望支持在帐户之间快速切换。您可以通过执行以下操作,为每个帐户指定自己的Realm文件,这些文件将用作默认Realm:

@implementation SomeClass
+ (void)setDefaultRealmForUser:(NSString *)username {RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];// Use the default directory, but replace the filename with the usernameconfig.fileURL = [[[config.fileURL URLByDeletingLastPathComponent]URLByAppendingPathComponent:username]URLByAppendingPathExtension:@"realm"];// Set this as the configuration used for the default Realm[RLMRealmConfiguration setDefaultConfiguration:config];
}
@end

Other Realms

有时,有多个Realm在不同位置持久化有用。例如,除了默认realm,你可能需要在Realm文件中将一些数据与应用程序捆绑在一起。可以使用以下代码执行此操作

RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];// Get the URL to the bundled file
config.fileURL = [[NSBundle mainBundle] URLForResource:@"MyBundledData" withExtension:@"realm"];
// Open the file in read-only mode as application bundles are not writeable
config.readOnly = YES;// Open the Realm with the configuration
RLMRealm *realm = [RLMRealm realmWithConfiguration:config error:nil];// Read some data from the bundled Realm
RLMResults<Dog *> *dogs = [Dog objectsInRealm:realm where:@"age > 5"];

In-Memory Realms

通常,Realm持久存储到磁盘,但是也可以通过设置inMemoryIdentifier而不是RLMRealmConfiguration上的fileURL来创建纯粹在内存中操作的领域

RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
config.inMemoryIdentifier = @"MyInMemoryRealm";
RLMRealm *realm = [RLMRealm realmWithConfiguration:config error:nil];

内存Realm不会在应用程序启动时保存数据,但是Realm的所有其他功能都会按预期工作,包括查询,关系和线程安全。如果需要灵活的数据访问,而不需要磁盘持久性的开销,这是一个有用的选项。

内存区域在临时目录中创建几个文件,以协调跨进程通知等事务。没有数据实际写入文件,除非操作系统由于内存压力需要交换到磁盘
注意:当所有具有特定标识符的内存实例实例超出范围而没有引用时,所有数据将为该范围释放。建议您在应用程序的持续时间内保持对任何创建的内存区域的强引用。

Error Handling

与任何磁盘IO操作一样,如果资源受到限制,则创建RLMRealm实例有时可能会失败。实际上,这只能在第一次在给定的线程上创建一个Realm实例时发生。从同一个线程对一个Realm的后续访问将重用一个缓存的实例,并且总是成功。
要在第一次访问指定线程上的Realm时处理错误,请提供一个指向错误参数的NSError指针:

NSError *error = nil;RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
RLMRealm *realm = [RLMRealm realmWithConfiguration:config error:&error];
if (!realm) {// handle error
}

Copying Objects Between Realms

将Realm对象复制到其他领域与将原始对象传递给+ [RLMObject createInRealm:withValue:]一样简单。例如,[MyRLMObjectSubclass createInRealm:otherRealm withValue:originalObjectInstance]。记住,Realm对象只能从它们第一次创建的线程进行访问,所以这个copy过程只能在同一线程上的Realms中使用才有效。
请注意,+ [RLMObject createInRealm:withValue:]不支持处理循环对象图。不要传递包含直接或间接引用回父对象的对象的关系的对象。

Finding a Realm File

如果需要帮助查找您的应用程序的Realm文件,请检查此StackOverflow答案详细说明

Auxiliary Realm Files

除了标准的.realm文件,Realm还为其自己的内部操作生成和维护附加的文件和目录。

  • .realm.lock - 资源锁的锁文件。
  • .realm.management - 进程间锁文件目录。
  • .realm.note - 通知的命名管道。

这些文件对.realm数据库文件没有任何影响,如果删除或替换其父数据库文件,则不会导致任何错误行为。

当报告Realm问题时,请确保将这些辅助文件与主.realm文件一起包含,因为它们包含用于调试目的的有用信息。

Bundling a Realm with an App

Class Subsets

Deleting Realm Files

Realm with Background App Refresh

SB了官网有中文版,还是当前版本还没有中文版
https://realm.io/cn/docs/objc/latest

这篇关于Realm Objective‑C 2.4.3 官方文档的翻译的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/654621

相关文章

基于Java医院药品交易系统详细设计和实现(源码+LW+调试文档+讲解等)

💗博主介绍:✌全网粉丝10W+,CSDN作者、博客专家、全栈领域优质创作者,博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌💗 🌟文末获取源码+数据库🌟 感兴趣的可以先收藏起来,还有大家在毕设选题,项目以及论文编写等相关问题都可以给我留言咨询,希望帮助更多的人  Java精品实战案例《600套》 2023-2025年最值得选择的Java毕业设计选题大全:1000个热

工程文档CAD转换必备!在 Java 中将 DWG 转换为 JPG

Aspose.CAD 是一个独立的类库,以加强Java应用程序处理和渲染CAD图纸,而不需要AutoCAD或任何其他渲染工作流程。该CAD类库允许将DWG, DWT, DWF, DWFX, IFC, PLT, DGN, OBJ, STL, IGES, CFF2文件、布局和图层高质量地转换为PDF和光栅图像格式。 Aspose API支持流行文件格式处理,并允许将各类文档导出或转换为固定布局文件格

关于word文档中目录的switch

有很多的switch,下面这篇文章介绍的比较详细,可以参考:http://word.mvps.org/FAQs/Formatting/TOCSwitches.htm

HTML文档插入JS代码的几种方法

在HTML文档里嵌入客户端JavaScript代码有4中方法: 1.内联,放置在< script>和标签对之间。 2.放置在由< script>标签的src属性指定的外部文件中。 3.放置在HTML事件处理程序中,该事件处理程序由onclick或onmouseover这样的HTML属性值指定。 4.放在一个URL里,这个URL使用特殊的“javascript:”协议。 在JS编程中,主张

9 RestClient客户端操作文档

1. match_all @GetMapping("matchAll")public void matchAll() throws IOException {//1. 准备requestSearchRequest request = new SearchRequest("hotel");//2. 组织DSL参数request.source().query(QueryBuilders.matchA

如何给文档设置密码?电脑文件安全加密的详细操作步骤(10种方法)

在数字化时代,电脑文件的安全和隐私至关重要。通过给电脑的文件或者文件夹设置密码和加密,可以有效保护你的重要文件不被未经授权的人员访问,特别是公司的重要岗位,一些特殊的机密文件,投标文件,资金文件等等,更应该注重文件日常使用安全性。下面将为你介绍10种电脑文件,文件夹加密的详细操作步骤,帮助你更好地保护你的电脑文件安全。 加密方式一、Windows系统内置加密(电脑自带的文件加密) 选中需要

Kimichat使用案例026:AI翻译英语PDF文档的3种方法

文章目录 一、介绍二、腾讯交互翻译TranSmart https://transmart.qq.com/三、沉浸式翻译三、谷歌网页翻译 一、介绍 短的文章,直接丢进kimichat、ChatGPT里面很快就可以翻译完成,而且效果很佳。但是,很长的PDF文档整篇需要翻译,怎么办呢? 二、腾讯交互翻译TranSmart https://transmart.qq.com/ 软件

CloudStack管理员文档 - 服务方案

用户创建一个实例可以又很多个选项来设定该实例的特性和性能。CloudStack提供以下几种方式: 服务方案,由管理员定义,提供了CPU速度,CPU数量,内存大小,根磁盘的标签,以及其他选项磁盘方案,由管理员定义,为主存储提供了磁盘大小和IOPS的选项网络方案,由管理员定义, 计算和磁盘方案 服务方案是CPU,内存,磁盘等虚拟硬件特性的集合。管理员可以创建各种服务方案,终端用户在创建虚拟机的时

如何给MySQL设置远程访问?(官方校正版)

在现代数据驱动的世界中,数据库的灵活性和可访问性变得尤为重要。设置MySQL的远程访问不仅仅是为了方便,还为企业和开发者提供了多种优势。无论是在分布式团队协作、跨地域数据管理,还是在系统集成和实时数据访问方面,远程访问都能显著提升效率和生产力。 目录 1. 修改MySQL配置文件 2. 重启MySQL服务 3. 创建远程访问用户 4. 配置防火墙 a. 使用UFW(适用于Ubun

Creating custom and compound Views in Android - Tutorial(翻译)

Creating custom and compound Views in Android - Tutorial(翻译) 译前的: 之前做了三篇学习笔记,从知乎上面看到了这篇英文的推荐,总的来说可以是一篇导读,没有相关的学习,看这篇,可以作为一个学习脉络导向;有相关的学习底子,可以作为一个基础夯实、思维理清。没想到一翻译就是四个多小时…英语渣,很多词句都不太准确,幸好有之前的学习基础打底…