Skip to content

Instantly share code, notes, and snippets.

@JeOam
Last active August 29, 2015 14:04
Show Gist options
  • Save JeOam/d5d1cd5d9e939a11df9d to your computer and use it in GitHub Desktop.
Save JeOam/d5d1cd5d9e939a11df9d to your computer and use it in GitHub Desktop.
Core Data

Include Core Data into your project is to include the umbrella header file:

#import <CoreData/CoreData.h>

To be able to work with Core Data, you need to understand that a Core Data stack is based on the following concepts:

  • Persistent store: The object that represents the actual data base on disk. We never use this object directly.
  • Persistent store coordinator: The object that coordinates reading and writing of information from and to the persistent store. The coordinator is the bridge between the managed object context and the persistent store.
  • Managed object model (MOM): This is a simple file on disk that will represent our data model. Think about it as your database schema.
  • Managed object: This class represents an entity that we want to store in Core Data. Traditional database programmers would know such entities as tables. A managed object is of type NSManagedObject, and its instances are placed on managed object contexts. They adhere to the schema dictated by the managed object model, and they get saved to a persistent store through a persistent store coordinator.
  • Managed object context (MOC): This is a virtual board. That sounds strange, right? But let me explain. We create Core Data objects in memory and set their properties and play with them. All this playing is done on a managed object context. The context keeps track of all the things that we are doing with our managed objects and even allows us to undo those actions. Think of your managed objects on a context as toys that you have brought on a table to play with. You can move them around, break them, move them out of the table, and bring new toys in. That table is your managed object context, and you can save its state when you are ready. When you save the state of the managed object context, this save operation will be communicated to the persistent store coordinator to which the context is connected, upon which the persistent store coordinator will store the information to the persistent store and subsequently to disk.

If you check the relevant box of "Use Core Data" in the process of creating a new project, your app delegate will have some new properties and methods(with fully implementation):

@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;

- (void)saveContext;
- (NSURL *)applicationDocumentsDirectory;

####1. Creating a Core Data Model with Xcode:

  • Find the file with the extension of xcdatamodel in your application bundle in Xcode and click it to open the visual data editor
    • Entity: Corresponds to a table in a database
    • Attribute: Corresponds to a column in a table
  • Click: Add Entity button on the bottom panel.

####2. Generating Class Files for Core Data Entities

  • Create a new class: [New File...] - [iOS - Core Data] - [NSManagedObject subclass], and [Next]
  • On the next screen, choose the managed object model that you want to save to disk and ensure it is ticked.(linked with you .xcdatamodeld file)
  • And next, pick the entities that you want to export from your model on disk as Objective-C files
  • and .... There you go! We turned our managed object into a real definition and implementation.!

When you create your data model using the editor in Xcode, you are creating the data relationships, entities, attributes, and so forth. However, to be able to use your model in your app, you must generate the code for your model. If you view the .h and .m files for your entities, you will realize that all the attributes are assigned dynamically. You can even see the @dynamic directive in the .m file of your entities to tell the compiler that it will fulfill the request of each attribute at runtime using dynamic method resolution.

####3. Creating and Saving Data Using Core Data

  • Import the entities class header before instantiate it(This is similar to creating a new row (managed object) in a table (entity) in a database (managed object context):

    #import "Person.h"
  • Use the insertNewObjectForEntityForName:inManagedObjectContext: class method of NSEntityDescription to create a new object of a type specified by the first parameter of this method.After you are done, save your managed object context using the save: instance method of the managed object context. )

    Person *newPerson = [NSEntityDescription insertNewObjectForEntityForName:@"Person"
                                                      inManagedObjectContext:self.managedObjectContext];
    if (newPerson != nil) {
        newPerson.firstName = @"Anthony";
        newPerson.lastName = @"Robbins";
        newPerson.age = @51;
        
        NSError *savingError = nil;
        
        if ([self.managedObjectContext save:&savingError]) {
            return YES;
        } else {
            NSLog(@"Failed to save the new person. Error = %@", savingError);
        }
    }
  • Attempting to insert an unknown entity into a managed object con‐ text will raise an exception of type NSInternalInconsistencyExcep tion. After inserting a new entity into the context, we must save the context. This will flush all the unsaved data of the context to the persistent store.

####4. Reading Data from Core Data Use an instance of NSFetchRequest to read the contents of your entities (tables) using Core Data.

// Tell the request that we want to read the contents of the Person entity 
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc]
                                 initWithEntityName:@"Person"];
NSError *requestError = nil;
// And execute the fetch request on the context
NSArray *persons = [self.managedObjectContext executeFetchRequest:fetchRequest
                                                            error:&requestError];
// Make sure we get the array
if ([persons count] > 0){
    /* Go through the persons array one by one */
} else {
    NSLog(@"Could not find any Person entities in the context.");
}

For those of you who are familiar with database terminology, a fetch request is similar to a SELECT statement. In the SELECT statement, you specify which rows, with which conditions, have to be returned from which table. With a fetch request, we do the same thing. We specify the entity (table) and the managed object context (the database layer). We can also specify sort descriptors for sorting the data we read.

####5. Deleting Data from Core Data Use the deleteObject: instance method of NSManagedObjectContext: to delete a managed object (a row in a table) from a managed object context (your database).

Person *lastPerson = [persons lastObject];
[self.managedObjectContext deleteObject:lastPerson];=
if ([lastPerson isDeleted]) {
    NSLog(@"Successfully delete the last person in the array");
    
    NSError *savingError = nil;
    if ([self.managedObjectContext save:&savingError]) {
        NSLog(@"Successfully deleted the last person in the array.");
    } else {
        NSLog(@"Failed to deleted the last person in the array.");
    }
}

This method doesn’t return an error to you in any of its parameters, nor does it return a BOOL value, so you really have no good way of knowing whether an object was successfully deleted using the managed object context. The best way to determine this is to use that managed object’s isDeleted method.

####6. Sorting Data in Core Data Create instances of NSSortDescriptor for each attribute (column, in the database world) of an entity that has to be sorted. Add the sort descriptors to an array and assign the array to an instance of NSFetchRequest using the setSortDescriptors: instance method.

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc]
                                 initWithEntityName:@"Person"];
NSError *requestError = nil;
NSSortDescriptor *ageSort = [[NSSortDescriptor alloc] initWithKey:@"age"
                                                        ascending:YES];
fetchRequest.sortDescriptors = @[ageSort];
NSArray *persons = [self.managedObjectContext executeFetchRequest:fetchRequest
                                                            error:&requestError];
if ([persons count] > 0){
    /* Go through the persons array one by one */
} else {
    NSLog(@"Could not find any Person entities in the context.");
}

An instance of NSFetchRequest can carry with itself an array of NSSortDescriptor instances. Each sort descriptor defines the attribute (column) on the current entity that has to be sorted and whether the sorting has to be ascending or descending.
You can assign more than one sort descriptor to one fetch request. The order in the array determines the order in which descriptors are provided. In other words, The output is sorted according to the first descriptor of the array, and within that order, entries are sorted according to the second descriptor of the array, etc.

@JeOam
Copy link
Author

JeOam commented Jul 28, 2014

获取 AppDelegate.h 中 Core Data 相关属性:

AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
return appDelegate.managedObjectContext;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment