Documentation

COObject class documentation

COObject : NSObject <COObjectMatching>

A mutable in-memory representation of an inner object in an object graph context (a counterpart to COItem, whose relationships are represented as Objective-C pointers instead of UUIDs).

AuthorsGenerated by qmathe
Declared inCOObject.h

Overview

A COObject instance is a generic model object described by a metamodel (see -entityDescription), and its lifecycle is managed by a COObjectGraphContext.

For a persistent object, a -branch owns the -objectGraphContext .

For a transient object, the -objectGraphContext is standalone, -branch and -persistentRoot return nil.

From COEditingContext to COObject, there is a owner chain where each element owns the one just below in the list:

  • COEditingContext
  • COPersistentRoot
  • COBranch
  • COObjectGraphContext
  • COObject

Object Equality

COObject inherits NSObject's -hash and -isEqual: methods, so equality is based on pointer comparison.

You must never override -hash or -isEqual:. This is a consequence of the fact that we promise it is safe to put a COObject instance in an NSSet and then mutate the COObject.

Use -isTemporallyEqual: to check both UUID and revision match. For example, when the same object is in use in multiple editing contexts simultaneously.

Common Use Cases

For an existing persistent root or transient object graph context, -initWithObjectGraphContext: is used to create additional inner objects.

To navigate the object graph, access or change the state of these objects, -valueForProperty: and -setValue:forProperty: are available. For instances of COObject subclasses that declare synthesized properties, you should use these accessors rather than those Property-Value Coding methods.

Creation

A persistent or transient object can be instantiated by using -initWithObjectGraphContext: or some other initializer (-init is not supported). The resulting object is a inner object that belongs to the object graph context.

For a transient object graph context, you can later use -[COEditingContext insertNewPersistentRootWithRootObject:] to turn an existing inner object into a root object (the object graph context becoming persistent).

You can instantiate also a new persistent root and retrieve its root object by using -[COEditingContext insertNewPersistentRootWithEntityName:] or similar COEditingContext methods.

When writing a COObject subclass, -initWithObjectGraphContext: can be overriden to initialize the the subclass properties.

The designated initializer rule remains valid in the COObject class hierarchy, but -initWithObjectGraphContext: must work correctly too (it must never return nil or a wrongly initialized instance), usually you have to override it to call the designated initializer. All secondary initializers (inherited or not) must return valid instances or nil. The easiest way to comply is described below:

  • For additional initializers, call the designated initializer
  • For each new designated initializer, override -initWithObjectGraphContext: to call it

Don't create singletons for COObject subclass in +initialize , because -[COObject entityDescription] would return nil.

For the property initialization rules, see Properties section.

Deletion

An inner object is deleted, when it becomes unreachable from the root object in the -objectGraphContext .

It is never explicitly deleted, instead this object must be removed in a collection or a relationship, and once this object doesn't belong to any collection or relationship that can be accessed from the root object, it is declared as unreachable, and will be deleted by the COObjectGraphContext garbage collection (usually on a future commit).

Properties

By default, COObject stores its properties in a variable storage, similar to a dictionary. In the rare cases, where the variable storage is too slow, properties can be stored in instance variables.

In a COObject subclass implementation, the variable storage can be accessed with -valueForVariableStorageKey: and -setValue:forVariableStorageKey: . You must not access the properties with these methods from other objects, this is the same than a direct instance variable access. For reading and writing properties, you must use accessors (synthesized or hand-written ones), or -valueForProperty: and -setValue:forProperty: (known as Property-Value Coding).

For multivalued properties stored in instance variables, you are responsible to allocate the collections in each COObject subclass designed initializer, and to release them in -dealloc (or use ARC). If a multivalued property is stored in the variable storage, COObject allocates the collections at initialization time and releases them at deallocation time (you can access these collections using -valueForVariableStorageKey: in your subclass initializers).

For explanations about accessors, see Writing Accessors section.

Writing Accessors

You can use Property-Value Coding to read and write properties. However implementing accessors can improve readability, type checking etc. For most attributes, we have a basic accessor pattern. For Multivalued properties (relationships or collection-based attributes), the basic accessor pattern won't work correctly.

For a COObject subclass, CoreObject will synthesize attribute accessors at run-time, if the property is declared @dynamic on the implementation side. For now, CoreObject doesn't synthesize collection-compliant accessors (such as Key-Value Coding collection accessors) beside set and get, all collection mutation methods must be hand-written based on the Multivalued Accessor Pattern.

Note: For a COObject subclass such as COCollection that holds a single collection, the subclass can conform to ETCollection and ETCollectionMutation protocols, and adopt their related traits, in this way no dedicated accessors need to be implemented.

Basic Accessor Pattern

 - (void)name
 {
     // When no ivar is provided, you can use the variable storage as below
     // return [self valueForVariableStorageKey: @"name"];
     return name;
 }

 - (void)setName: (NSString *)aName
 {
     [self willChangeValueForProperty: @"name"];
     // When no ivar is provided, you can use the variable storage as below
     // [self setValue: aName: forVariableStorageKey: @"name"];
     name =  aName;
     [self didChangeValueForProperty: @"name"];
 }
 

Multivalued Accessor Pattern

The example below is based on a COObject subclass using a names instance variable. If the value is stored in the variable storage, the example must be adjusted to use -valueForVariableStorageKey: and -setValue:forVariableStorageKey: .

 - (void)names
 {
     // The synthesized accessor would just do the same.
     return [names copy];
 }

 - (void)addName: (NSString *)aName
 {
     NSArray *insertedObjects = A(aName);
     NSIndexSet *insertionIndexes = [NSIndexSet indexSet];

     [self willChangeValueForProperty: key
	                          atIndexes: insertionIndexes
                          withObjects: insertedObjects
                         mutationKind: ETCollectionMutationKindInsertion];

     // You can update the collection in whatever you want, the synthesized 
     // accessors would just use ETCollectionMutation methods.
     [names addObject: aName];

     [self didChangeValueForProperty: key
                           atIndexes: insertionIndexes
                         withObjects: insertedObjects
                        mutationKind: ETCollectionMutationKindInsertion];
 }

 - (void)removeName: (NSString *)aName
 {
     NSArray *removedObjects = A(aName);
     NSIndexSet *removalIndexes = [NSIndexSet indexSet];

     [self willChangeValueForProperty: key
	                          atIndexes: removalIndexes
                          withObjects: removedObjects
                         mutationKind: ETCollectionMutationKindRemoval];

     // You can update the collection in whatever you want, the synthesized 
     // accessors would just use ETCollectionMutation methods.
     [names removeObject: aName];

     [self didChangeValueForProperty: key
                           atIndexes: removalIndexes
                         withObjects: removedObjects
                        mutationKind: ETCollectionMutationKindRemoval];
 }

 // Direct setters are rare, but nonetheless it is possible to write one as below...
 - (void)setNames: (id <ETCollection>)newNames
 {
     NSArray *replacementObjects = A(aName);
     // If no indexes are provided, the entire collection is replaced or set.
     NSIndexSet *replacementIndexes = [NSIndexSet indexSet];

     [self willChangeValueForProperty: key
	                          atIndexes: replacementIndexes
                          withObjects: replacementObjects
                         mutationKind: ETCollectionMutationKindReplacement];

     // You can update the collection in whatever you want, the synthesized 
     // accessor would just do the same or allocate a custom CoreObject
     // primitive collections.
     names = [newNames mutableCopy];

     [self didChangeValueForProperty: key
                           atIndexes: replacementIndexes
                         withObjects: replacementObjects
                        mutationKind: ETCollectionMutationKindReplacement];
 }
 

To implement a getter that returns an incoming relationships e.g. parent(s), just use -valueForVariableStorageKey: (see the -name getter example above).

You must never implement incoming relationship setters.

To access incoming relationships when no accessors are available, just use -valueForProperty: as you would do it for other properties.

Serialization and Metamodel

At commit time, all the inner objects in a COObjectGraphContext are serialized into an intermediate COItem representation with COItemGraph protocol.

At serialization time, each object is turned into a COItem with -[COObject storeItem]. At deserialization, a COItem is passed to -[COObject setStoreItem:] to recreate the object state.

All properties declared as persistent (see -[ETPropertyDescription isPersistent]) in the metamodel are serialized, transient properties are skipped. For transient properties, COObject don't manage them in any way, but just ensure their values respect the metamodel constraints (in -didChangeValueForProperty:).

For persistent properties, COObject supports both relationships to other inner objects, and attributes that contain primitive objects such as NSString or NSDate.

Both attributes and relationships can be either univalued or multivalued (to-one or to-many), see -[ETPropertyDescription isMultivalued] in the metamodel.

Relationships can be either undirectional or bidirectional (one-way or two-way). To create a bidirectional relationships, -[ETPropertyDescription opposite] must be set on one side. The other side or opposite is the inverse relationship. For a bidirectional relationship, a single side can be marked as persistent, the other side must be transient. The persistent side is known as an outgoing relationship, and the transient side as an incoming relationship. CoreObject doesn't load incoming relationships into each COObject, but load them in the relationship cache. This rule doesn't apply to transient relationships.

With metamodel constraints, CoreObject supports several multivalued relationship variations:

Keyed Relationship
hold in a NSDictionary – -[ETPropertyDescription isKeyed] == YES in the metamodel
Ordered Relationship
hold in a NSArray – -[ETPropertyDescription isOrdered] == YES in the metamodel
Unordered Relationship
hold in a NSSet – -[ETPropertyDescription isOrdered] == NO in the metamodel
Unidirectional Relationship
a one-way relationship – -[ETPropertyDescription opposite] == nil in the metamodel
Bidirectional Relationship
a two-way relationship – -[ETPropertyDescription opposite != nil in the metamodel
Composite Relationship
a parent/child relationship – -[[ETPropertyDescription multivalued] is not the same on both side

A persistent keyed relationship is undirectional, -[ETPropertyDescription opposite] must be nil.

A composite relationsip is just a bidirectional relationship subcase, it models a tree structure inside the object graph, and in this way, a composite determines how the object graph is copied. A composite object (or child object) is copied rather than aliased when the tree structure it belongs to is copied.

With metamodel constraints, CoreObject supports several variations over attribute collections:

Keyed Collection
hold in a NSDictionary – -[ETPropertyDescription isKeyed] == YES in the metamodel
Ordered Collection
hold in a NSArray – -[ETPropertyDescription isOrdered] == YES in the metamodel
Unordered Collection
hold in a NSSet – -[ETPropertyDescription isOrdered] == NO in the metamodel

For relationships or attribute collections, both ordered and unordered, duplicates are not allowed, and if the same object is inserted twice in a collection, CoreObject will remove the previous reference to this object in the collection.

A keyed relationship or attribute collection is unordered, -[ETPropertyDescription isOrdered] must be NO. This restriction applies to transient properties too currently.

Note: If a collection is a relationship or an attribute collection is controlled by -[ETPropertyDescription type], and whether this entity description return YES to -[ETEntityDescription isPrimitive]. You can override -[ETEntityDescription isPrimitive] in a ETEntityDescription subclass to declare new attribute objects in the metamodel. However CoreObject will treat all COObject instances as relationships internally, since CoreObject serialized format has a fixed set of attribute types (see COType).

Object Graph Loading

When a persistent root's root object is accessed, the entire object graph bound to it is loaded (if the root object is not present in memory).

When a persistent inner object is loaded, once the attribute values have been deserialized, -awakeFromDeserialization is sent to the object to let it update its state before being used. You can thus override -awakeFromDeserialization to recreate transient properties, recompute correct property values based on the deserialized values, etc. But you must not access or update persistent relationships in -awakeFromDeserialization directly.

You can override -didLoadObjectGraph to manipulate persistent relationships in a such way. Loading a persistent object usually result in the other inner objects being loaded, and -didLoadObjectGraph is sent to all the inner objects once all these objects have been loaded.

Although you should avoid to override -didLoadObjectGraph , in some cases it cannot be avoided. For example, an accessor can depend on or alter the state of a relationship (e.g. a parent object in a tree structure). To give a more concrete example, in EtoileUI -[ETLayoutItem setView:] uses -[ETLayoutItemGroup handleAttacheViewOfItem:] to adjust the parent view, so -[ETLayoutItem setView:] cannot be used until the parent item is loaded.

Model Validation

At commit time, all the changed objects are validated with -validate . You can override this method to implement some custom validation logic per COObject subclass. By default, the object will be validated with the model validation logic packaged with the metamodel, -validateAllValues will check each property value with the validation rules provided by -[ETPropertyDescription role] and -[ETRoleDescription validateValue:forKey:].

Note: -validateAllValues currently doesn't check that the property values respect the constraints set on their related property descriptions. For now, CoreObject enforces these metamodel constraints in -didChangeValueForProperty: .


Initialization

- (id) initWithObjectGraphContext: (COObjectGraphContext *)aContext

Initializes and returns object that is owned and managed by the given object graph context. During the initialization, the receiver is automatically inserted into the object graph context. As a result, the receiver appears in -[COObjectGraphContext insertedObjectUUIDs] on return.

If the object graph context is transient (not owned by any branch), the returned object is transient, otherwise it is persistent.

It is possible to turn a transient object into a persistent one, by making the object graph context persistent with -[COEditingContext insertPersistentRootWithRootObject:] . For example:

 COObjectGraphContext *graphContext = [COObjectGraphContext new];
 COObject *object = [[COObject alloc] initWithObjectGraphContext: graphContext];

 [editingContext insertPersistentRootWithRootObject: [graphContext rootObject]];
 

You cannot use -init to create a COObject instance.

For a nil context, raises an NSInvalidArgumentException.

    - (id) initWithEntityDescription: (ETEntityDescription *)anEntityDesc objectGraphContext: (COObjectGraphContext *)aContext

    Initializes and returns an object that uses a custom entity description.

    For initialization, you should usually just use -initWithObjectGraphContext: .

    If you have subclassed COObject, in most cases, you want to instantiate your subclass using the identically named entity description, and -initWithObjectGraphContext: does just that.

    For some use cases (e.g. custom object representation or partial object loading), you might want to use a subentity or parent entity description rather than the entity description registered for the receiver class in -[COObjectGraphContext modelDescriptionRepository] , and this initializer is the only way to do that.

    For a subclass, this method results in the subclass designated initializer being called.

      Persistency Attributes

      - (ETUUID *) UUID

      Returns the UUID that uniquely identifies the persistent object that corresponds to the receiver.

      A persistent object has a single instance per editing context.

        - (ETEntityDescription *) entityDescription

        Returns the metamodel that declares all the object properties (persistent and transient).

        See also -propertyNames and -persistentPropertyNames .

          - (COBranch *) branch

          Returns the branch when the receiver is persistent, otherwise returns nil.

            - (COPersistentRoot *) persistentRoot

            Returns the persistent root when the receiver is persistent, otherwise returns nil.

              - (COEditingContext *) editingContext

              Returns the editing context when the receiver is persistent, otherwise returns nil.

                - (COObjectGraphContext *) objectGraphContext

                Returns the object graph context owning the receiver.

                  - (id) rootObject

                  Returns the root object when the receiver is persistent, otherwise returns nil.

                  When the receiver is persistent, returns either self or the root object that encloses the receiver as an inner object.

                  See also -isRoot .

                    - (BOOL) isPersistent

                    Returns whether the receiver is owned by a persistent root.

                    This doesn't mean the object has been saved to the disk yet.

                    When persistent, the receiver has a valid root object and its object graph context is owned by a branch.

                    See also -persistentRoot .

                      - (BOOL) isRoot

                      Returns whether the receiver is a root object that provides access to other inner objects (in the object graph context).

                      Inner or non-persistent objects returns NO.

                      See also -rootObject .

                        - (BOOL) isShared

                        Whether it is permissible to make an alias to the receiver when copying an object graph. Default is YES.

                          History Attributes

                          - (CORevision *) revision

                          Return the revision object corresponding to the most recent commit of the branch owning the object graph context.

                          See also -[COBranch currentRevision] .

                            Basic Properties

                            - (NSString *) name

                            The object name.

                              - (void) setName: (NSString *)name

                              The object name.

                                - (NSString *) identifier

                                Returns the object identifier.

                                By default, returns -name which can be nil and might not be unique even within a COCollection content.

                                Can be overriden to return a custom string. See -[COCollection objectForIdentifier:] .

                                  - (NSString *) displayName

                                  Returns -name .

                                    - (NSSet *) tags

                                    Returns the tags attached to the receiver.

                                    The returned collection contains COTag objects.

                                      Property-Value Coding

                                      - (NSArray *) propertyNames

                                      Returns the properties declared in the receiver entity description.

                                      See also -entityDescription and -persistentPropertyNames .

                                        - (NSArray *) persistentPropertyNames

                                        Returns the persistent properties declared in the receiver entity description.

                                        The returned array contains the property descriptions which replies YES to -[ETPropertyDescription isPersistent] .

                                        See also -entityDescription and -propertyNames .

                                          - (id) valueForProperty: (NSString *)key

                                          Returns the property value.

                                          When the property is not declared in the entity description, raises an NSInvalidArgumentException.

                                          See also -setValue:forProperty: .

                                            - (BOOL) setValue: (id)value forProperty: (NSString *)key

                                            Sets the property value.

                                            When the property is not declared in the entity description, raises an NSInvalidArgumentException.

                                            See also -valueForProperty: .

                                              Validation

                                              - (NSArray *) validateAllValues

                                              Validates every persistent property, then returns a validation result array.

                                              Valid results are not included in the returned array.

                                              When the entity description includes persistent properties, transient objects are validatable too.

                                              See -validateValue:forProperty: and ETValidationResult.

                                                - (NSArray *) validateValue: (id)value forProperty: (NSString *)key

                                                Validates the proposed value against the property, then returns a validation result array.

                                                Valid results are not included in the returned array. On success, returns an empty array.

                                                The validation is divided in two steps that occurs in the order below:

                                                • Metamodel Validation using -[ETPropertyDescription validateValue:forKey:] , (for relationships, the opposite property is validated too)
                                                • Model Validation, when a method -validate PropertyName : is implemented (e.g. the method signature must be match -(ETValidationResult *)validateName ).

                                                The Model validation scheme doesn't support Key-Value Coding custom validation methods (e.g. -validateName:error:).

                                                See -validateValue:forProperty: and ETValidationResult.

                                                  - (NSArray *) validate

                                                  Validates the receiver when it belongs to the inserted or updated objects in the commit under way, then returns an error array.

                                                  By default, returns -validateAllValues result (as an error array).

                                                  This method must return an empty array on validation success, otherwise it must return an error array. Each error (usually a COError object) can wrap a validation result in -[NSError userInfo] under the key kCOValidationResultKey. For wrapping validation result, you should use -[COError errorWithValidationResult:] .

                                                  The superclass implementation must be called, then the returned array is either returned directly, or when validation doesn't succeed locally combined with the new array through -[NSArray arrayByAddingObjectsFromArray:] .

                                                   NSArray *errors = [COError errorsWithValidationResults: results];
                                                   
                                                   // additionalErrors would contain errors that don't wrap a validation result 
                                                   // (without a kCOValidationResultKey in their user info)
                                                   errors = [errors arrayByAddingObjectsFromArray: additionalErrors];
                                                  
                                                   return [[super validate] arrayByAddingObjectsFromArray: errors];
                                                   

                                                  To know if the receiver is validated for an insertion or an update, pass the receiver to -[COObjectGraphContext isUpdatedObject:].

                                                  For objects collected during a GC phase by COObjectGraphContext, no special validation occurs. You cannot override -validate to cancel a receiver deletion (you can override -dealloc to react to it though).

                                                  For cancelling deletions, override -validate to detect invalid object removals in outgoing relationships (e.g. the receiver is a parent). For a removed object, if no incoming relationships retains it, the object is going to be deleted (collected in the next GC phase).

                                                  See also COError, -[COObjectGraphContext insertedObjectUUIDs], -[COObjectGraphContext updatedObjectUUIDs] and -[COObjectGraphContext changedObjectUUIDs].

                                                    - (BOOL) validateValue: (id*)aValue forKey: (NSString *)key error: (NSError **)anError

                                                    Calls -validateValue:forProperty: to validate the value, and returns the validation result through aValue and anError.

                                                    This method exists to integrate CoreObject validation with existing Cocoa or GNUstep programs.

                                                    For Etoile programs or new projects, you should use -validateValue:forProperty: .

                                                      Direct Access to the Variable Storage

                                                      - (id) valueForVariableStorageKey: (NSString *)key

                                                      Returns a value from the variable storage.

                                                      Can be used to read a property with no instance variable.

                                                      This is a low-level method whose use should be restricted to serialization code and accessors that expose properties with no related instance variable.

                                                        - (void) setValue: (id)value forVariableStorageKey: (NSString *)key

                                                        Sets a value in the variable storage.

                                                        Can be used to write a property with no instance variable.

                                                        This is a low-level method whose use should be restricted to serialization code and accessors that expose properties with no related instance variable.

                                                        This method involves no integrity check or relationship consistency update. It won't invoke -willChangeValueForProperty: and -didChangeValueForProperty: (or -willChangeValueForKey: and -didChangeValueForKey:).

                                                          Notifications to be called by Accessors

                                                          - (void) willChangeValueForProperty: (NSString *)key

                                                          Tells the receiver that the value of the property (transient or persistent) is about to change.

                                                          By default, limited to calling -willChangeValueForKey: .

                                                          Can be overriden, but the superclass implementation must be called.

                                                            - (void) didChangeValueForProperty: (NSString *)key

                                                            Tells the receiver that the value of the property (transient or persistent) has changed.

                                                            By default, notifies the editing context about the receiver change and triggers Key-Value Observing notifications by calling -didChangeValueForKey: .

                                                            Can be overriden, but the superclass implementation must be called.

                                                              - (void) willChangeValueForProperty: (NSString *)property atIndexes: (NSIndexSet *)indexes withObjects: (NSArray *)objects mutationKind: (ETCollectionMutationKind)mutationKind

                                                              Tells the receiver that the value of the multivalued property (transient or persistent) is about to change.

                                                              By default, limited to calling -willchangevalueforkey:atindexes:withObjects:mutationkind:.

                                                              To know more about the arguments, see -willchangevalueforkey:atindexes:withObjects:mutationkind:.

                                                              Can be overriden, but the superclass implementation must be called.

                                                                - (void) didChangeValueForProperty: (NSString *)property atIndexes: (NSIndexSet *)indexes withObjects: (NSArray *)objects mutationKind: (ETCollectionMutationKind)mutationKind

                                                                Tells the receiver that the value of the multivalued property (transient or persistent) has changed.

                                                                By default, notifies the editing context about the receiver change and triggers Key-Value Observing notifications by calling -didChangeValueForKey:atIndexes:withObjects:mutationKind:.

                                                                To know more about the arguments, see -didChangeValueForKey:atIndexes:withObjects:mutationKind:.

                                                                Can be overriden, but the superclass implementation must be called.

                                                                  Overridable Loading Notifications

                                                                  - (void) awakeFromDeserialization

                                                                  For an object graph context loading (or reloading), tells the receiver that the receiver was just deserialized, and it can recreate additional transient state.

                                                                  During the loading, each concerned inner object is deserialized and receives -awakeFromDeserialization in turn (just before deserializing the next object). The order in which inner objects are deserialized is random. So you should never access other COObject instances or manipulate persistent relationships in an overriden implementation.

                                                                  For recreating transient state related to persistent relationships or react to the object graph loading, you must override -didLoadObjectGraph .

                                                                  The object graph context reuse existing objects (based on their UUID idendity) accross reloads, so be cautious to reset all transient state in -awakeFromDeserialization (or adjust it to match the last deserialized state).

                                                                  This method is also called for object graph copies inside the current object graph context (see COCopier).

                                                                  If you override this method, the superclass implementation must be called first.

                                                                    - (void) didLoadObjectGraph

                                                                    For an object graph context loading (or reloading), tells the receiver that all the inner objects, which were not yet loaded or for which a new state was needed, have been deserialized.

                                                                    You can override this method, to recreate transient state related to persistent relationships, or react to a partial or entire object graph loading.

                                                                    Each inner object that has received -awakeFromDeserialization , receives -didLoadObjectGraph . The root object is always the last to receive -didLoadObjectGraph (if the root object was loaded or reloaded).

                                                                    Don't forget that you shouldn't expect all inner objects to receive -awakeFromDeserialization and -didLoadObjectGraph during a loading. For a reloading, the object graph context doesn't discard the existing objects but reuse them (based on their UUID idendity).

                                                                    For an object graph copy (see COCopier), the object copies receive -awakeFromDeserialization and -didLoadObjectGraph , but all other inner objects don't.

                                                                    If you override this method, the superclass implementation must be called first.

                                                                      Object Equality

                                                                      - (BOOL) isTemporallyEqual: (id)anObject

                                                                      Returns whether anObject saved state is equal the receiver saved state.

                                                                      Two persistent objects are temporally equal if they share the same UUID and revision.

                                                                      See also -isEqual: .

                                                                        Object Matching

                                                                        - (NSArray *) objectsMatchingQuery: (COQuery *)aQuery

                                                                        Returns the receiver put in an array when it matches the query, otherwise returns an empty array.

                                                                          Debugging and Description

                                                                          - (NSString *) detailedDescription

                                                                          Returns a description that includes the receiver properties and their values.

                                                                          See -detailedDescriptionWithTraversalKey:, and -[NSObject descriptionWithOptions:] to implement custom detailed descriptions.

                                                                            - (NSString *) detailedDescriptionWithTraversalKey: (NSString *)aProperty

                                                                            Returns a tree description for all the objects encountered while traversing the given relationship (including the receiver).

                                                                            For each relationship object, the output looks the same than - detailedDescription.

                                                                            You can use this method to print an object graph or tree. The max traversal depth is 20 levels.

                                                                            See -[NSObject descriptionWithOptions:] to implement custom detailed descriptions.

                                                                              - (NSString *) description

                                                                              Returns a short description to summarize the receiver.

                                                                              Can be overriden, but must check -isZombie , and if YES, return a basic description (limited to -UUID and -entity description), or just call the superclass description that is expected to comply the present rule.

                                                                                - (NSString *) typeDescription

                                                                                Returns a short and human-readable description of the receiver type.

                                                                                This is used to present the type to the user in the UI.

                                                                                As such, the returned string must be localized.

                                                                                By default, returns the entity localized description, -[ETEntityDescription setLocalizedDescription:] can be used to customize the description. See -entityDescription to access the entity. You can override the method to return a custom description too. For example, a COPhoto subclass could return the UTI description bound to the image it encapsulates: [[[self image] UTI] typeDescription].

                                                                                This method doesn't return the receiver UTI description e.g. Core Object, it is more accurate but not simple enough to be presented to the user.

                                                                                  - (NSString *) revisionDescription

                                                                                  Returns the receiver revision as a string.

                                                                                  This is used to present the revision to the user in the UI.

                                                                                    - (NSString *) tagDescription

                                                                                    Returns the receiver tags in a coma separated list.

                                                                                    This is used to present -tags to the user in the UI.

                                                                                      - (BOOL) isZombie

                                                                                      Returns whether the receiver has been relinquished by the object graph context (during a GC phase). You might encounter this if your app holds a strong Objective-C reference to a COObject that is subsequently deleted from an object graph context.

                                                                                      This property is only provided for debugging, and should never be used in application logic (a correctly written program will never encounter a zombie object.) See COObjectGraphContextWillRelinquishObjectsNotification.

                                                                                      A zombie object is an invalid inner object that must not be used, since messages that access its state can result in an exception. You are just allowed to call -UUID, -entityDescription and -description on it.

                                                                                      See also -objectGraphContext .