Class

NSManagedObject

NSManagedObject is a generic class that implements all the basic behavior required of a Core Data model object. It is not possible to use instances of direct subclasses of NSObject (or any other class not inheriting from NSManagedObject) with a managed object context. You may create custom subclasses of NSManagedObject, although this is not always required. If no custom logic is needed, a complete Object graph can be formed with NSManagedObject instances.

Overview

A managed object is associated with an entity description (an instance of NSEntityDescription) that provides metadata about the object (including the name of the entity that the object represents and the names of its attributes and relationships) and with a managed object context that tracks changes to the object graph. It is important that a managed object is properly configured for use with Core Data. If you instantiate a managed object directly, you must call the designated initializer (init(entity:insertInto:)).

Data Storage

In some respects, an NSManagedObject acts like a dictionary—it is a generic container object that efficiently provides storage for the properties defined by its associated NSEntityDescription object. NSManagedObject provides support for a range of common types for attribute values, including string, date, and number (see NSAttributeDescription for full details). There is therefore commonly no need to define instance variables in subclasses. Sometimes, however, you want to use types that are not supported directly, such as colors and C structures. For example, in a graphics application you might want to define a Rectangle entity that has attributes color and bounds that are an instance of NSColor and an NSRect struct respectively. For some types you can use a transformable attribute, for others this may require you to create a subclass of NSManagedObject—see Non-Standard Persistent Attributes.

Faulting

Managed objects typically represent data held in a persistent store. In some situations a managed object may be a “fault”—an object whose property values have not yet been loaded from the external data store—see Faulting and Uniquing for more details. When you access persistent property values, the fault “fires” and the data is retrieved from the store automatically. This can be a comparatively expensive process (potentially requiring a round trip to the persistent store), and you may wish to avoid unnecessarily firing a fault.

You can safely invoke the following methods on a fault without causing it to fire: isEqual:, hash, superclass, class, self, isProxy, isKindOfClass:, isMemberOfClass:, conformsToProtocol:, respondsToSelector:, description, managedObjectContext, entity, objectID, isInserted, isUpdated, isDeleted, faultingState, and isFault. Since isEqual and hash do not cause a fault to fire, managed objects can typically be placed in collections without firing a fault. Note, however, that invoking key-value coding methods on the collection object might in turn result in an invocation of valueForKey: on a managed object, which would fire the fault.

Although the description method does not cause a fault to fire, if you implement a custom description method that accesses the object’s persistent properties, this will cause a fault to fire. You are strongly discouraged from overriding description in this way.

Subclassing Notes

In combination with the entity description in the managed object model, NSManagedObject provides a rich set of default behaviors including support for arbitrary properties and value validation. There are, however, many reasons why you might wish to subclass NSManagedObject to implement custom features; in doing so, though, you must not disrupt Core Data’s behavior.

Methods you Must Not Override

NSManagedObject itself customizes many features of NSObject so that managed objects can be properly integrated into the Core Data infrastructure. Core Data relies on NSManagedObject’s implementation of the following methods, which you therefore absolutely must not override: primitiveValueForKey:, setPrimitiveValue:forKey:, isEqual:, hash, superclass, class, self, isProxy, isKindOfClass:, isMemberOfClass:, conformsToProtocol:, respondsToSelector:, managedObjectContext, entity, objectID, isInserted, isUpdated, isDeleted, and isFault, alloc, allocWithZone:, new, instancesRespondToSelector:, instanceMethodForSelector:, methodForSelector:, methodSignatureForSelector:, instanceMethodSignatureForSelector:, or isSubclassOfClass:.

Methods you Are Discouraged From Overriding

As with any class, you are strongly discouraged from overriding the key-value observing methods such as willChangeValue(forKey:) and didChangeValue(forKey:withSetMutation:using:). You are discouraged from overriding description—if this method fires a fault during a debugging operation, the results may be unpredictable. You are also discouraged from overriding init(entity:insertInto:), or dealloc. Changing values in the init(entity:insertInto:) method will not be noticed by the context and if you are not careful, those changes may not be saved. Most initialization customization should be performed in one of the awake… methods. If you do override init(entity:insertInto:), you must make sure you adhere to the requirements set out in the method description (see init(entity:insertInto:)).

You are discouraged from overriding dealloc because didTurnIntoFault() is usually a better time to clear values—a managed object may not be reclaimed for some time after it has been turned into a fault. Core Data does not guarantee that dealloc will be called in all scenarios (such as when the application quits); therefore you should not include required side effects (like saving or changes to the file system, user preferences, and so on) in these methods.

In summary, for init(entity:insertInto:) and dealloc, it is important to remember that Core Data reserves exclusive control over the life cycle of the managed object (that is, raw memory management). This is so that the framework is able to provide features such as uniquing and by consequence relationship maintenance as well as much better performance than would be otherwise possible.

Methods to Override Considerations

The following methods are intended to be fine grained and not perform large scale operations. You must not fetch or save in these methods. In particular, they should not have side effects on the managed object context:

  • init(entity:insertInto:)

  • didTurnIntoFault()

  • willTurnIntoFault()

  • dealloc

In addition to methods you should not override, there are others that if you do override you should invoke the superclass’s implementation first, including awakeFromInsert, awakeFromFetch, and validation methods. You should not modify relationships in awakeFromFetch()—see the method description for details.

Custom Accessor Methods

Typically, there is no need to write custom accessor methods for properties that are defined in the entity of a managed object’s corresponding managed object model. Should you wish or need to do so, though, there are several implementation patterns you must follow. These are described in Managed Object Accessor Methods in Core Data Programming Guide.

Core Data automatically generates accessor methods (and primitive accessor methods) for you. For attributes and to-one relationships, Core Data generates the standard get and set accessor methods; for to-many relationships, Core Data generates the indexed accessor methods as described in Defining Basic Accessor Methods in Key-Value Coding Programming Guide. You do however need to declare the accessor methods or use Objective-C properties to suppress compiler warnings. For a full discussion, see Managed Object Accessor Methods in Core Data Programming Guide.

Custom Instance Variables

By default, NSManagedObject stores its properties in an internal structure as objects, and in general Core Data is more efficient working with storage under its own control rather using custom instance variables.

NSManagedObject provides support for a range of common types for attribute values, including string, date, and number (see NSAttributeDescription for full details). If you want to use types that are not supported directly, such as colors and C structures, you can either use transformable attributes or create a subclass of NSManagedObject, as described in Non-Standard Persistent Attributes.

Sometimes it may be convenient to represent variables as scalars—in a drawing applications, for example, where variables represent dimensions and x and y coordinates and are frequently used in calculations. To represent attributes as scalars, you declare instance variables as you would in any other class. You also need to implement suitable accessor methods as described in Managed Object Accessor Methods.

If you define custom instance variables, for example, to store derived attributes or other transient properties, you should clean up these variables in didTurnIntoFault() rather than dealloc.

Validation Methods

NSManagedObject provides consistent hooks for validating property and inter-property values. You typically should not override validateValue(_:forKey:), instead you should implement methods of the form validate<Key>:error:, as defined by the NSKeyValueCoding protocol. If you want to validate inter-property values, you can override validateForUpdate() and/or related validation methods.

You should not call validateValue:forKey:error: within custom property validation methods—if you do so you will create an infinite loop when validateValue:forKey:error: is invoked at runtime. If you do implement custom validation methods, you should typically not call them directly. Instead you should call validateValue:forKey:error: with the appropriate key. This ensures that any constraints defined in the managed object model are applied.

If you implement custom inter-property validation methods (such as validateForUpdate()), you should call the superclass’s implementation first. This ensures that individual property validation methods are also invoked. If there are multiple validation failures in one operation, you should collect them in an array and add the array—using the key NSDetailedErrorsKey—to the userInfo dictionary in the NSError object you return. For an example, see Managed Object Validation.

Symbols

Initializing a Managed Object

init(entity: NSEntityDescription, insertInto: NSManagedObjectContext?)

Initializes the receiver and inserts it into the specified managed object context.

Getting a Managed Object’s Identity

var entity: NSEntityDescription

The entity description of the receiver.

var objectID: NSManagedObjectID

The object ID of the receiver.

Getting State Information

var managedObjectContext: NSManagedObjectContext?

The managed object context with which the receiver is registered.

var hasChanges: Bool

A Boolean value that indicates whether the receiver has been inserted, has been deleted, or has unsaved changes.

var isInserted: Bool

A Boolean value that indicates whether the receiver has been inserted in a managed object context.

var isUpdated: Bool

A Boolean value that indicates whether the receiver has unsaved changes.

var isDeleted: Bool

A Boolean value that indicates whether the receiver will be deleted during the next save.

var isFault: Bool

A Boolean value that indicates whether the receiver is a fault.

var faultingState: Int

The faulting state of the receiver.

func hasFault(forRelationshipNamed: String)

Returns a Boolean value that indicates whether the relationship for a given key is a fault.

Managing Life Cycle and Change Events

func awakeFromFetch()

Invoked automatically by the Core Data framework after the receiver has been fetched.

func awakeFromInsert()

Invoked automatically by the Core Data framework when the receiver is first inserted into a managed object context.

func awake(fromSnapshotEvents: NSSnapshotEventType)

Invoked automatically by the Core Data framework when the receiver is reset due to an undo, redo, or other multi-property state change.

func changedValues()

Returns a dictionary containing the keys and (old) values of persistent properties that have been changed since last fetching or saving the receiver.

func changedValuesForCurrentEvent()

Returns a dictionary containing the keys and old values of persistent properties that have changed since the last posting of NSManagedObjectContextObjectsDidChange.

func committedValues(forKeys: [String]?)

Returns a dictionary of the last fetched or saved values of the receiver for the properties specified by the given keys.

func prepareForDeletion()

Invoked automatically by the Core Data framework when the receiver is about to be deleted.

func willSave()

Invoked automatically by the Core Data framework when the receiver’s managed object context is saved.

func didSave()

Invoked automatically by the Core Data framework after the receiver’s managed object context completes a save operation.

func willTurnIntoFault()

Invoked automatically by the Core Data framework before receiver is converted to a fault.

func didTurnIntoFault()

Invoked automatically by the Core Data framework when the receiver is turned into a fault.

Supporting Key-Value Coding

func value(forKey: String)

Returns the value for the property specified by key.

func setValue(Any?, forKey: String)

Sets the specified property of the receiver to the specified value.

func primitiveValue(forKey: String)

Returns from the receiver’s private internal storage the value for the specified property.

func setPrimitiveValue(Any?, forKey: String)

Sets in the receiver's private internal storage the value of a given property.

Validation

func validateForDelete()

Determines whether the receiver can be deleted in its current state.

func validateForInsert()

Determines whether the receiver can be inserted in its current state.

func validateForUpdate()

Determines whether the receiver’s current state is valid.

Supporting Key-Value Observing

func didAccessValue(forKey: String?)

Provides support for key-value observing access notification.

func observationInfo()

Returns the observation info of the receiver.

func setObservationInfo(UnsafeMutableRawPointer?)

Sets the observation info of the receiver.

func willAccessValue(forKey: String?)

Provides support for key-value observing access notification.

func didChangeValue(forKey: String)

Invoked to inform the receiver that the value of a given property has changed.

func didChangeValue(forKey: String, withSetMutation: NSKeyValueSetMutationKind, using: Set<AnyHashable>)

Invoked to inform the receiver that the specified change was made to a specified to-many relationship.

func willChangeValue(forKey: String)

Invoked to inform the receiver that the value of a given property is about to change.

func willChangeValue(forKey: String, withSetMutation: NSKeyValueSetMutationKind, using: Set<AnyHashable>)

Invoked to inform the receiver that the specified change is about to be made to a specified to-many relationship.

Constants

The following constants relate to errors returned following validation failures.

NSSnapshotEventType

Constants returned from awake(fromSnapshotEvents:) to denote the reason why a managed object may need to reinitialize values.

Relationships

Inherits From