1 ////////////////////////////////////////////////////////////////////////////
3 // Copyright 2014 Realm Inc.
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
9 // http://www.apache.org/licenses/LICENSE-2.0
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
17 ////////////////////////////////////////////////////////////////////////////
19 #import <Foundation/Foundation.h>
21 #import <Realm/RLMObjectBase.h>
22 #import <Realm/RLMThreadSafeReference.h>
24 NS_ASSUME_NONNULL_BEGIN
26 @class RLMNotificationToken;
27 @class RLMObjectSchema;
28 @class RLMPropertyChange;
29 @class RLMPropertyDescriptor;
31 @class RLMResults<RLMObjectType>;
34 `RLMObject` is a base class for model objects representing data stored in Realms.
36 Define your model classes by subclassing `RLMObject` and adding properties to be managed.
37 Then instantiate and use your custom subclasses instead of using the `RLMObject` class directly.
40 @interface Dog : RLMObject
41 @property NSString *name;
42 @property BOOL adopted;
49 ### Supported property types
52 - `NSInteger`, `int`, `long`, `float`, and `double`
56 - `NSNumber<X>`, where `X` is one of `RLMInt`, `RLMFloat`, `RLMDouble` or `RLMBool`, for optional number properties
57 - `RLMObject` subclasses, to model many-to-one relationships.
58 - `RLMArray<X>`, where `X` is an `RLMObject` subclass, to model many-to-many relationships.
62 You can initiate queries directly via the class methods: `allObjects`, `objectsWhere:`, and `objectsWithPredicate:`.
63 These methods allow you to easily query a custom subclass for instances of that class in the default Realm.
65 To search in a Realm other than the default Realm, use the `allObjectsInRealm:`, `objectsInRealm:where:`,
66 and `objectsInRealm:withPredicate:` class methods.
72 See our [Cocoa guide](https://realm.io/docs/objc/latest#relationships) for more details.
74 ### Key-Value Observing
76 All `RLMObject` properties (including properties you create in subclasses) are
77 [Key-Value Observing compliant](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/KeyValueObserving/KeyValueObserving.html),
78 except for `realm` and `objectSchema`.
80 Keep the following tips in mind when observing Realm objects:
82 1. Unlike `NSMutableArray` properties, `RLMArray` properties do not require
83 using the proxy object returned from `-mutableArrayValueForKey:`, or defining
84 KVC mutation methods on the containing class. You can simply call methods on
85 the `RLMArray` directly; any changes will be automatically observed by the containing
87 2. Unmanaged `RLMObject` instances cannot be added to a Realm while they have any
89 3. Modifying managed `RLMObject`s within `-observeValueForKeyPath:ofObject:change:context:`
90 is not recommended. Properties may change even when the Realm is not in a write
91 transaction (for example, when `-[RLMRealm refresh]` is called after changes
92 are made on a different thread), and notifications sent prior to the change
93 being applied (when `NSKeyValueObservingOptionPrior` is used) may be sent at
94 times when you *cannot* begin a write transaction.
97 @interface RLMObject : RLMObjectBase <RLMThreadConfined>
99 #pragma mark - Creating & Initializing Objects
102 Creates an unmanaged instance of a Realm object.
104 Call `addObject:` on an `RLMRealm` instance to add an unmanaged object into that Realm.
106 @see `[RLMRealm addObject:]`
108 - (instancetype)init NS_DESIGNATED_INITIALIZER;
112 Creates an unmanaged instance of a Realm object.
114 Pass in an `NSArray` or `NSDictionary` instance to set the values of the object's properties.
116 Call `addObject:` on an `RLMRealm` instance to add an unmanaged object into that Realm.
118 @see `[RLMRealm addObject:]`
120 - (instancetype)initWithValue:(id)value NS_DESIGNATED_INITIALIZER;
124 Returns the class name for a Realm object subclass.
126 @warning Do not override. Realm relies on this method returning the exact class
129 @return The class name for the model class.
131 + (NSString *)className;
134 Creates an instance of a Realm object with a given value, and adds it to the default Realm.
136 If nested objects are included in the argument, `createInDefaultRealmWithValue:` will be recursively called
139 The `value` argument can be a key-value coding compliant object, an array or dictionary returned from the methods in
140 `NSJSONSerialization`, or an array containing one element for each managed property.
142 An exception will be thrown if any required properties are not present and those properties
143 were not defined with default values.
145 If the `value` argument is an array, all properties must be present, valid and in the same
146 order as the properties defined in the model.
148 @param value The value used to populate the object.
150 @see `defaultPropertyValues`
152 + (instancetype)createInDefaultRealmWithValue:(id)value;
155 Creates an instance of a Realm object with a given value, and adds it to the specified Realm.
157 If nested objects are included in the argument, `createInRealm:withValue:` will be recursively called
160 The `value` argument can be a key-value coding compliant object, an array or dictionary returned from the methods in
161 `NSJSONSerialization`, or an array containing one element for each managed property.
163 An exception will be thrown if any required properties are not present and those properties
164 were not defined with default values.
166 If the `value` argument is an array, all properties must be present, valid and in the same
167 order as the properties defined in the model.
169 @param realm The Realm which should manage the newly-created object.
170 @param value The value used to populate the object.
172 @see `defaultPropertyValues`
174 + (instancetype)createInRealm:(RLMRealm *)realm withValue:(id)value;
177 Creates or updates a Realm object within the default Realm.
179 This method may only be called on Realm object types with a primary key defined. If there is already
180 an object with the same primary key value in the default Realm, its values are updated and the object
181 is returned. Otherwise, this method creates and populates a new instance of the object in the default Realm.
183 If nested objects are included in the argument, `createOrUpdateInDefaultRealmWithValue:` will be
184 recursively called on them if they have primary keys, `createInDefaultRealmWithValue:` if they do not.
186 The `value` argument is used to populate the object. It can be a Realm object, a key-value coding
187 compliant object, an array or dictionary returned from the methods in `NSJSONSerialization`, or an
188 array containing one element for each managed property.
190 If the object is being created, an exception will be thrown if any required properties
191 are not present and those properties were not defined with default values.
193 If the `value` argument is a Realm object already managed by the default Realm, the
194 argument's type is the same as the receiver, and the objects have identical values for
195 their managed properties, this method does nothing.
197 If the object is being updated, all properties defined in its schema will be set by copying from
198 `value` using key-value coding. If the `value` argument does not respond to `valueForKey:` for a
199 given property name (or getter name, if defined), that value will remain untouched.
200 Nullable properties on the object can be set to nil by using `NSNull` as the updated value.
202 If the `value` argument is an array, all properties must be present, valid and in the same
203 order as the properties defined in the model.
205 @param value The value used to populate the object.
207 @see `defaultPropertyValues`, `primaryKey`
209 + (instancetype)createOrUpdateInDefaultRealmWithValue:(id)value;
212 Creates or updates an Realm object within a specified Realm.
214 This method may only be called on Realm object types with a primary key defined. If there is already
215 an object with the same primary key value in the given Realm, its values are updated and the object
216 is returned. Otherwise this method creates and populates a new instance of this object in the given Realm.
218 If nested objects are included in the argument, `createOrUpdateInRealm:withValue:` will be
219 recursively called on them if they have primary keys, `createInRealm:withValue:` if they do not.
221 The `value` argument is used to populate the object. It can be a Realm object, a key-value coding
222 compliant object, an array or dictionary returned from the methods in `NSJSONSerialization`, or an
223 array containing one element for each managed property.
225 If the object is being created, an exception will be thrown if any required properties
226 are not present and those properties were not defined with default values.
228 If the `value` argument is a Realm object already managed by the given Realm, the
229 argument's type is the same as the receiver, and the objects have identical values for
230 their managed properties, this method does nothing.
232 If the object is being updated, all properties defined in its schema will be set by copying from
233 `value` using key-value coding. If the `value` argument does not respond to `valueForKey:` for a
234 given property name (or getter name, if defined), that value will remain untouched.
235 Nullable properties on the object can be set to nil by using `NSNull` as the updated value.
237 If the `value` argument is an array, all properties must be present, valid and in the same
238 order as the properties defined in the model.
240 @param realm The Realm which should own the object.
241 @param value The value used to populate the object.
243 @see `defaultPropertyValues`, `primaryKey`
245 + (instancetype)createOrUpdateInRealm:(RLMRealm *)realm withValue:(id)value;
247 #pragma mark - Properties
250 The Realm which manages the object, or `nil` if the object is unmanaged.
252 @property (nonatomic, readonly, nullable) RLMRealm *realm;
255 The object schema which lists the managed properties for the object.
257 @property (nonatomic, readonly) RLMObjectSchema *objectSchema;
260 Indicates if the object can no longer be accessed because it is now invalid.
262 An object can no longer be accessed if the object has been deleted from the Realm that manages it, or
263 if `invalidate` is called on that Realm.
265 @property (nonatomic, readonly, getter = isInvalidated) BOOL invalidated;
268 #pragma mark - Customizing your Objects
271 Returns an array of property names for properties which should be indexed.
273 Only string, integer, boolean, and `NSDate` properties are supported.
275 @return An array of property names.
277 + (NSArray<NSString *> *)indexedProperties;
280 Override this method to specify the default values to be used for each property.
282 @return A dictionary mapping property names to their default values.
284 + (nullable NSDictionary *)defaultPropertyValues;
287 Override this method to specify the name of a property to be used as the primary key.
289 Only properties of types `RLMPropertyTypeString` and `RLMPropertyTypeInt` can be designated as the primary key.
290 Primary key properties enforce uniqueness for each value whenever the property is set, which incurs minor overhead.
291 Indexes are created automatically for primary key properties.
293 @return The name of the property designated as the primary key.
295 + (nullable NSString *)primaryKey;
298 Override this method to specify the names of properties to ignore. These properties will not be managed by the Realm
299 that manages the object.
301 @return An array of property names to ignore.
303 + (nullable NSArray<NSString *> *)ignoredProperties;
306 Override this method to specify the names of properties that are non-optional (i.e. cannot be assigned a `nil` value).
308 By default, all properties of a type whose values can be set to `nil` are considered optional properties.
309 To require that an object in a Realm always store a non-`nil` value for a property,
310 add the name of the property to the array returned from this method.
312 Properties of `RLMObject` type cannot be non-optional. Array and `NSNumber` properties
313 can be non-optional, but there is no reason to do so: arrays do not support storing nil, and
314 if you want a non-optional number you should instead use the primitive type.
316 @return An array of property names that are required.
318 + (NSArray<NSString *> *)requiredProperties;
321 Override this method to provide information related to properties containing linking objects.
323 Each property of type `RLMLinkingObjects` must have a key in the dictionary returned by this method consisting
324 of the property name. The corresponding value must be an instance of `RLMPropertyDescriptor` that describes the class
325 and property that the property is linked to.
327 return @{ @"owners": [RLMPropertyDescriptor descriptorWithClass:Owner.class propertyName:@"dogs"] };
329 @return A dictionary mapping property names to `RLMPropertyDescriptor` instances.
331 + (NSDictionary<NSString *, RLMPropertyDescriptor *> *)linkingObjectsProperties;
334 #pragma mark - Getting & Querying Objects from the Default Realm
337 Returns all objects of this object type from the default Realm.
339 @return An `RLMResults` containing all objects of this type in the default Realm.
341 + (RLMResults *)allObjects;
344 Returns all objects of this object type matching the given predicate from the default Realm.
346 @param predicateFormat A predicate format string, optionally followed by a variable number of arguments.
348 @return An `RLMResults` containing all objects of this type in the default Realm that match the given predicate.
350 + (RLMResults *)objectsWhere:(NSString *)predicateFormat, ...;
353 + (RLMResults<__kindof RLMObject *> *)objectsWhere:(NSString *)predicateFormat args:(va_list)args;
357 Returns all objects of this object type matching the given predicate from the default Realm.
359 @param predicate The predicate with which to filter the objects.
361 @return An `RLMResults` containing all objects of this type in the default Realm that match the given predicate.
363 + (RLMResults *)objectsWithPredicate:(nullable NSPredicate *)predicate;
366 Retrieves the single instance of this object type with the given primary key from the default Realm.
368 Returns the object from the default Realm which has the given primary key, or
369 `nil` if the object does not exist. This is slightly faster than the otherwise
370 equivalent `[[SubclassName objectsWhere:@"primaryKeyPropertyName = %@", key] firstObject]`.
372 This method requires that `primaryKey` be overridden on the receiving subclass.
374 @return An object of this object type, or `nil` if an object with the given primary key does not exist.
377 + (nullable instancetype)objectForPrimaryKey:(nullable id)primaryKey;
380 #pragma mark - Querying Specific Realms
383 Returns all objects of this object type from the specified Realm.
385 @param realm The Realm to query.
387 @return An `RLMResults` containing all objects of this type in the specified Realm.
389 + (RLMResults *)allObjectsInRealm:(RLMRealm *)realm;
392 Returns all objects of this object type matching the given predicate from the specified Realm.
394 @param predicateFormat A predicate format string, optionally followed by a variable number of arguments.
395 @param realm The Realm to query.
397 @return An `RLMResults` containing all objects of this type in the specified Realm that match the given predicate.
399 + (RLMResults *)objectsInRealm:(RLMRealm *)realm where:(NSString *)predicateFormat, ...;
402 + (RLMResults<__kindof RLMObject *> *)objectsInRealm:(RLMRealm *)realm where:(NSString *)predicateFormat args:(va_list)args;
405 Returns all objects of this object type matching the given predicate from the specified Realm.
407 @param predicate A predicate to use to filter the elements.
408 @param realm The Realm to query.
410 @return An `RLMResults` containing all objects of this type in the specified Realm that match the given predicate.
412 + (RLMResults *)objectsInRealm:(RLMRealm *)realm withPredicate:(nullable NSPredicate *)predicate;
415 Retrieves the single instance of this object type with the given primary key from the specified Realm.
417 Returns the object from the specified Realm which has the given primary key, or
418 `nil` if the object does not exist. This is slightly faster than the otherwise
419 equivalent `[[SubclassName objectsInRealm:realm where:@"primaryKeyPropertyName = %@", key] firstObject]`.
421 This method requires that `primaryKey` be overridden on the receiving subclass.
423 @return An object of this object type, or `nil` if an object with the given primary key does not exist.
426 + (nullable instancetype)objectInRealm:(RLMRealm *)realm forPrimaryKey:(nullable id)primaryKey;
428 #pragma mark - Notifications
431 A callback block for `RLMObject` notifications.
433 If the object is deleted from the managing Realm, the block is called with
434 `deleted` set to `YES` and the other two arguments are `nil`. The block will
435 never be called again after this.
437 If the object is modified, the block will be called with `deleted` set to
438 `NO`, a `nil` error, and an array of `RLMPropertyChange` objects which
439 indicate which properties of the objects were modified.
441 If an error occurs, `deleted` will be `NO`, `changes` will be `nil`, and
442 `error` will include information about the error. The block will never be
443 called again after an error occurs.
445 typedef void (^RLMObjectChangeBlock)(BOOL deleted,
446 NSArray<RLMPropertyChange *> *_Nullable changes,
447 NSError *_Nullable error);
450 Registers a block to be called each time the object changes.
452 The block will be asynchronously called after each write transaction which
453 deletes the object or modifies any of the managed properties of the object,
454 including self-assignments that set a property to its existing value.
456 For write transactions performed on different threads or in differen
457 processes, the block will be called when the managing Realm is
458 (auto)refreshed to a version including the changes, while for local write
459 transactions it will be called at some point in the future after the write
460 transaction is committed.
462 Notifications are delivered via the standard run loop, and so can't be
463 delivered while the run loop is blocked by other activity. When notifications
464 can't be delivered instantly, multiple notifications may be coalesced into a
467 Unlike with `RLMArray` and `RLMResults`, there is no "initial" callback made
468 after you add a new notification block.
470 Only objects which are managed by a Realm can be observed in this way. You
471 must retain the returned token for as long as you want updates to be sent to
472 the block. To stop receiving updates, call `-invalidate` on the token.
474 It is safe to capture a strong reference to the observed object within the
475 callback block. There is no retain cycle due to that the callback is retained
476 by the returned token and not by the object itself.
478 @warning This method cannot be called during a write transaction, when the
479 containing Realm is read-only, or on an unmanaged object.
481 @param block The block to be called whenever a change occurs.
482 @return A token which must be held for as long as you want updates to be delivered.
484 - (RLMNotificationToken *)addNotificationBlock:(RLMObjectChangeBlock)block;
486 #pragma mark - Other Instance Methods
489 Returns YES if another Realm object instance points to the same object as the receiver in the Realm managing
492 For object types with a primary, key, `isEqual:` is overridden to use the same logic as this
493 method (along with a corresponding implementation for `hash`).
495 @param object The object to compare the receiver to.
497 @return Whether the object represents the same object as the receiver.
499 - (BOOL)isEqualToObject:(RLMObject *)object;
501 #pragma mark - Dynamic Accessors
504 - (nullable id)objectForKeyedSubscript:(NSString *)key;
507 - (void)setObject:(nullable id)obj forKeyedSubscript:(NSString *)key;
512 Information about a specific property which changed in an `RLMObject` change notification.
514 @interface RLMPropertyChange : NSObject
517 The name of the property which changed.
519 @property (nonatomic, readonly, strong) NSString *name;
522 The value of the property before the change occurred. This will always be `nil`
523 if the change happened on the same thread as the notification and for `RLMArray`
526 For object properties this will give the object which was previously linked to,
527 but that object will have its new values and not the values it had before the
528 changes. This means that `previousValue` may be a deleted object, and you will
529 need to check `invalidated` before accessing any of its properties.
531 @property (nonatomic, readonly, strong, nullable) id previousValue;
534 The value of the property after the change occurred. This will always be `nil`
535 for `RLMArray` properties.
537 @property (nonatomic, readonly, strong, nullable) id value;
540 #pragma mark - RLMArray Property Declaration
543 Properties on `RLMObject`s of type `RLMArray` must have an associated type. A type is associated
544 with an `RLMArray` property by defining a protocol for the object type that the array should contain.
545 To define the protocol for an object, you can use the macro RLM_ARRAY_TYPE:
547 RLM_ARRAY_TYPE(ObjectType)
549 @property RLMArray<ObjectType *><ObjectType> *arrayOfObjectTypes;
551 #define RLM_ARRAY_TYPE(RLM_OBJECT_SUBCLASS)\
552 @protocol RLM_OBJECT_SUBCLASS <NSObject> \
555 NS_ASSUME_NONNULL_END