Core Data on iOS 5 Tutorial: Getting Started

Adam Burkepile By on April 13, 2010

This post is also available in: Russian

Core Data Failed Banks Model Diagram

Core Data Failed Banks Model Diagram

Update 4/17/12: Fully updated for iOS 5 (original post by Ray Wenderlich, update by Adam Burkepile).

Of all of the ways to persist data on the iPhone, Core Data is the best one to use for non-trivial data storage. It can reduce the memory overhead of your app, increase responsiveness, and save you from writing a lot of boilerplate code.

However, the learning curve for Core Data can be quite large. That’s where this tutorial series comes in – the goal is to get you up to speed with the basics of Core Data quickly.

In this first part of the series, we’re going to create a visual data model for our objects, run a quick and dirty test to make sure it works, and then hook it up to a table view so we can see a list of our objects.

In the second part of the series, we’re going to discuss how to import or preload existing data into Core Data so that we have some good default data when our app starts up.

In the final part of the series, we’re going to discuss how we can optimize our app by using NSFetchedResultsController, to reduce memory overhead and improve response time.

Before proceeding with this tutorial, I recommend checking out the tutorial series on SQLite for iPhone Developers first. By default, the backing store for Core Data is SQLite, so it helps to have an understanding of how that works first. Plus, the app we’re making is the same app as in that tutorial – just with Core Data this time!

Creating a Core Data Project

So let’s get started! Crack open Xcode and create a new project with the Master-Detail Application template.

At the next screen, enter FailedBankCD as the Product Name, anything you want as the Company Identifier, and FBCD as the Class Prefix.

 

Select iPhone as the device family and make sure Use Storyboards, Use Core Data, and Use Automatic Reference Counting are selected. Select Next, then Create.

Before we begin, we’ll want to remove some of the boilerplate code generated by the template. Select the following files in the project navigator:

  • FBCDMasterViewController.h
  • FBCDMasterViewController.m
  • FBCDDetailViewController.h
  • FBCDDetailViewController.m

and delete them. When it askes “Remove References” or “Move to Trash”, select “Move to Trash”.

 

Now right-click on the FailedBankCD group folder and select New File. Select iOS\Objective-C Class template and select Next. Name the class FBCDMasterViewController and make it a subclass of UITableViewController. Make sure that the two checkboxes are NOT selected. Click Next and Create.

Select FBCDMasterViewController.h in the project navigator and add the following line right before the @end line:

@property (nonatomic,strong) NSManagedObjectContext* managedObjectContext;

Now switch to the .m file and add synthesize the property right after the @implementation line:

@synthesize managedObjectContext;

Don’t worry if you don’t know what an “NSManagedObjectContext” is, we’ll talk about that in a moment.

 

But first we need to configure our Storyboard to no longer use the detail view controller (since we deleted it earlier). So open up MainStoryboard.storyboard and delete the detail view controller:

The last thing we want to do is click on FailedBanksCD.xcdatamodel. You’ll see a visual editor will pop up – this is what we’ll be using in a minute to diagram our model objects. Go ahead select the bubble in the middle that says “Entity” (or “Event”, depending on your version of Xcode) and delete it.

 

If your screen does not look like this, try switching the Editor Style (in the bottom right of this screen) to the visual view.

OK, great! Now let’s take a quick look at the project. If you give it a run it should just be a blank app.

Open FailedBanksCDAppDelegate.m. You’ll see that there are several new functions in here that are implemented for us, to set up the Core Data “stack”. One creates a managed object context, one creates a managed object model, and one creates a persistent store coordinator. Huh??

Don’t worry. The names sound confusing at first, but once you get a “mental shortcut” for what they’re all about they are easy to understand.

  • Managed Object Model: You can think of this as the database schema. It is a class that contains definitions for each of the objects (also called “Entities”) that you are storing in the database. Usually, you will use the visual editor you just peeked at to set up what objects are in the database, what their attributes, and how they relate to each other. However, you can do this with code too!
  • Persistent Store Coordinator: You can think of this as the database connection. Here’s where you set up the actual names and locations of what databases will be used to store the objects, and any time a managed object context needs to save something it goes through this single coordinator.
  • Managed Object Context: You can think of this as a “scratch pad” for objects that come from the database. It’s also the most important of the three for us, because we’ll be working with this the most. Basically, whenever you need to get objects, insert objects, or delete objects, you call methods on the managed object context (or at least most of the time!)

Don’t worry too much about these methods – you won’t have to mess with them much. However, it’s good to know that they are there and what they represent.

Defining Our Model

When we created our database tables in the SQLite tutorial, we had a single table containing all of the data for a failed bank. To reduce the amount of data in memory at once (for learning purposes), we just pulled out the subset of the fields we needed for display in our first table view.

 

So we might be tempted to set up our model the same way with Core Data. However, with Core data you cannot retrieve only certain attributes of an object – you have to retrieve the entire object. However, if we factor the objects into two pieces – the FailedBankInfo piece and the FailedBankDetails piece – we can accomplish the exact same thing.

So let’s see how this will work. Open up the visual model editor (click FailedBanksCD.xcodedatamodel).

Let’s start by creating an object in our model – referred to as “Entity” in Core Data speak. In the bottom toolbar, click the plus button to add a new Entity.

Upon clicking the plus, it will create a new Entity, and show the properties for the Entity in the visual editor.

Name the Entity FailedBankInfo. Then click the entity and make sure the third tab is selected in the Utilities section (the Data Model Inspector). You will see it currently lists the class as a subclass of NSManagedObject. This is the default class for Entities, which we’ll use for now – later we’ll come back and set up custom objects.

So let’s add some attributes. First, make sure that your Entity is selected by either clicking on the Entity name in the left panel, or the diagram for the entity in the diagram view. In the middle panel, click and hold on the plus button and then click “Add Attribute” from the popup like the following:

In the Data Model Inspector on the right, name the attribute “name” and set the Type to “String” like the following:

Now, repeat this to add two more attributes, “city” and “state”, also both strings.

Next, we need to create an entity for FailedBankDetails. Create an Entity the same way you did before, name it FailedBankDetails, and add the following attributes to it: zip of type Integer 32, closeDate of type Date, and updateDate of type Date.

Finally, we need to associate these two types. Select FailedBankInfo, and click and hold the plus button in the middle pane, but this time select “Add relationship”:

Name the relationship “details”, and set the destination as “FailedBankDetails.”

Ok, so what did we just do here? We just set up a relationship in Core Data, which links up one entity to another entity. In this case, we are setting up a one-to-one relationship – every FailedBankInfo will have exactly 1 FailedBankDetails. Behind the scenes, Core Data will set up our database so that our FailedBankInfo table has a field for the ID of the corresponding FailedBankDetails object.

Apple recommends that whenever you create a link from one object to another, you create a link from the other object going back as well. So let’s do this.

Add a relationship to “FailedBankDetails” named “info”, set the destination to “FailedBankInfo”, and set the inverse to “details”.

Also, set the delete rule for both relationships to “cascade”. This means that if you delete one object with Core Data, Core Data will delete the associated object as well. This makes sense in this case because a FailedBankDetails wouldn’t mean anything without a corresponding FailedBankInfo.

Give it a run! What’s that? Crash?

Well, these things happens sometimes. See… when you change your storage model (Managed Object Model) and there is already a persistent store created, it doesn’t know how to read it. It’s like using a secret decoder ring to write a secret message, then changing the decoder ring. When you tried to read the message after changing it, it would just be jibberish.

You can perform a model upgrade, but that’s a conversion for a different day. For now just delete the existing persistent store (the written down message). Easiest way to do that is to just delete the application from you iPhone or simulator, which ever one you’re using. Click and hold on the application just like deleting on your phone. Give it another run and all should be well.

Testing our Model

Believe it or not, that was probably the most important thing we needed to do. Now it’s just a matter of testing out using Core Data and making sure it works!

 

First, let’s test out adding a test object to our database. Open FailedBanksCDAppDelegate.m and add the following to the top of application:didFinishLaunchingWithOptions:

NSManagedObjectContext *context = [self managedObjectContext];
NSManagedObject *failedBankInfo = [NSEntityDescription
    insertNewObjectForEntityForName:@"FailedBankInfo"
    inManagedObjectContext:context];
[failedBankInfo setValue:@"Test Bank" forKey:@"name"];
[failedBankInfo setValue:@"Testville" forKey:@"city"];
[failedBankInfo setValue:@"Testland" forKey:@"state"];
NSManagedObject *failedBankDetails = [NSEntityDescription
    insertNewObjectForEntityForName:@"FailedBankDetails"
    inManagedObjectContext:context];
[failedBankDetails setValue:[NSDate date] forKey:@"closeDate"];
[failedBankDetails setValue:[NSDate date] forKey:@"updateDate"];
[failedBankDetails setValue:[NSNumber numberWithInt:12345] forKey:@"zip"];
[failedBankDetails setValue:failedBankInfo forKey:@"info"];
[failedBankInfo setValue:failedBankDetails forKey:@"details"];
NSError *error;
if (![context save:&error]) {
    NSLog(@"Whoops, couldn't save: %@", [error localizedDescription]);
}

In the first line, we grab a pointer to our managed object context using the helper function that comes included with the template.

 

Then we create a new instance of an NSManagedObject for our FailedBankInfo entity, by calling insertNewObjectForEntityForName. Every object that Core Data stores derives from NSManagedObject. Once you have an instance of the object, you can call setValue for any attribute that you defined in the visual editor to set up the object.

So we go ahead and set up a test bank, for both FailedBankInfo and FailedBankDetails. At this point the objects are just modified in memory – to store them back to the database we need to call save on the managedObjectContext.

That’s all there is to it to insert objects – no SQL code necessary!

Before we try this out, let’s add some more code in there to list out all the objects currently in the database:

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
    entityForName:@"FailedBankInfo" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
for (NSManagedObject *info in fetchedObjects) {
    NSLog(@"Name: %@", [info valueForKey:@"name"]);
    NSManagedObject *details = [info valueForKey:@"details"];
    NSLog(@"Zip: %@", [details valueForKey:@"zip"]);
}

Here we create a new object called a fetch request. You can think of a fetch request as a SELECT clause. We call entityForName to get a pointer to the FailedBankInfo entity we want to retrieve, and then use setEntity to tell our fetch request that’s the kind of Entity we want.

 

We then call executeFetchRequest on the managed object context to pull all of the objects in the FailedBankInfo table into our “scratch pad”. We then iterate through each NSManagedObject, and use valueForKey to pull out various pieces.

Note that even though we pulled out just the objects from the FailedBankInfo table, we can still access the associated FailedBankDetails object by acessing the details property on the FAiledBankInfo entity.

How does this work? Behind the scenes, when you access that property Core Data notices that it doesn’t have the data in the context, and “faults”, which basically means it runs over to the database and pulls in that data for you right as you need it. Pretty convenient!

Give this code a run and take a look in your output window (note you won’t see anything visually, just in the output window!), and you should see a test bank in your database for every time you run the program.

Seeing the Raw SQL Statements

I don’t know about you, but when I’m working on this kind of stuff I really like to see the actual SQL statements going on to understand how things are working (and make sure it’s doing what I expect!)

 

Once again Apple has provided an easy solution to this. Open the Scheme drop-down in XCode and select ‘Edit Scheme…’. Select the ‘Run’ scheme and select the ‘Arguments’ tab. Add the following argument: “-com.apple.CoreData.SQLDebug 1”. When you’re done it should look like the following:

Now when you run your code, in the debug output you should see useful trace statements like this showing you what’s going on:

So here we see things are working as we expect. The first two selects and update are Core Data doing some bookkeeping work keeping track of what the next ID for the entity should be.

Then we have our inserts into the details and info tables. After that, we select the entire bank info table in our query. Then as we iterate through the results, each time we access the details variable, behind the scenes Core Data faults and issues another select statement to get the data from the ZFAILEDBANKDETAILS table.

Auto Generating Model Files

So far, we’ve been using NSManagedObject to work with our Entities. This isn’t the best way to do things, because NSManagedObject is not a strongly typed class. As you can see, you are accessing attributes on entities via strings, and it’s quite easy to make a mistake and type an attribute name incorrectly, or set data using the wrong type, etc.

 

The better way to do things is to create a Model file for each entity, so we have the benefits of strong typing, can avoid making mistakes, and can even subclass this with extra methods/properties. You can do this by hand, but XCode makes this quite easy with a class generator.

Let’s try it out. Open up FailedBanksCD.xcdatamodel, click on the FailedBankInfo entity, and go to File\New\File. Select the Core Data\NSManagedObject subclass, and click Next, and then click Create again on the following view.

You should see some new files added to your project: FailedBankInfo.h/m and FailedBankDetails.h/m. These classes are very simple, and just declare properties based on the attributes you added to the entities. You will notice that the properties are declared as dynamic inside the .m files – this is because Core Data handles wiring the properties up automatically.

Do the same steps with the FailedBankDetails entity.

There is one problem with the autogenerated classes that we have to fix. If you look at FailedBankDetails.h, you’ll notice that the info variable is correctly declared as a FailedBankInfo class, but in FailedBankInfo.h the details variable is defined as an NSManagedObject (but it should be a FailedBankDetails object).

This happens because you ran the generator for FailedBankInfo before you ran the generator for FailedBankDetails, so it didn’t know that there would be a FailedBankDetails class available.

You can fix this manually, but there’s an even easier way. Just re-run the generator again for FailedBankInfo, and select “Replace” to overwrite the existing file. Viola, fixed!

Also, take a peek back in FailedBanksCD.xcdatamodel. When you look at the properties for the entities, you’ll notice that the classes have now been set automatically to the names of the autogenerated classes:

Now, let’s tweak our test code in the FBCDAppDelegate.m to use our new subclasses of NSManagedObject. First add the headers we’ll need up top:

#import "FailedBankInfo.h"
#import "FailedBankDetails.h"

Then change the code as follows:

NSManagedObjectContext *context = [self managedObjectContext];
FailedBankInfo *failedBankInfo = [NSEntityDescription
    insertNewObjectForEntityForName:@"FailedBankInfo"
    inManagedObjectContext:context];
failedBankInfo.name = @"Test Bank";
failedBankInfo.city = @"Testville";
failedBankInfo.state = @"Testland";
FailedBankDetails *failedBankDetails = [NSEntityDescription
    insertNewObjectForEntityForName:@"FailedBankDetails"
    inManagedObjectContext:context];
failedBankDetails.closeDate = [NSDate date];
failedBankDetails.updateDate = [NSDate date];
failedBankDetails.zip = [NSNumber numberWithInt:12345];
failedBankDetails.info = failedBankInfo;
failedBankInfo.details = failedBankDetails;
NSError *error;
if (![context save:&error]) {
    NSLog(@"Whoops, couldn't save: %@", [error localizedDescription]);
}
 
// Test listing all FailedBankInfos from the store
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"FailedBankInfo"
    inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
for (FailedBankInfo *info in fetchedObjects) {
    NSLog(@"Name: %@", info.name);
    FailedBankDetails *details = info.details;
    NSLog(@"Zip: %@", details.zip);
}

This is pretty much the same code we had before, except instead of using NSManagedObject directly, we use our new subclasses. Now we have type safety and cleaner code!

Creating a Table View

Open up FBCDMasterViewController.h and add a member variable for the failedBankInfos which we’ll display in the table view.

@property (nonatomic, strong) NSArray *failedBankInfos;

Note it already has the managed object context which we’ll use to retrieve this list, which we set up earlier. If you look at the bottom of application:didFinishLaunchingWithOptions in FBCDAppDelegate.m, you’ll see that it sets the managed object context there.

 

Switch over to FBCDMasterViewController.m and make the following changes:

// At very top, in import section
#import "FailedBankInfo.h"
 
// At top, under @implementation
@synthesize failedBankInfos;

Then modify viewDidLoad to look like the following:

- (void)viewDidLoad {
    [super viewDidLoad];
 
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription
                                   entityForName:@"FailedBankInfo" inManagedObjectContext:managedObjectContext];
    [fetchRequest setEntity:entity];
    NSError *error;
    self.failedBankInfos = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
    self.title = @"Failed Banks";
 
}

This code should look pretty familiar to our test code from earlier. We simply create a fetch request to get all of the FailedBankInfos in the database, and store it in our member variable.

 

The rest of the mods are exactly like we did in the SQLite tutorial. For quick reference, I’ll list the remaining steps here again:

Return 1 for numberOfSectionsInTableView:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

Replace numberOfRowsInSection with the following:

- (NSInteger)tableView:(UITableView *)tableView
    numberOfRowsInSection:(NSInteger)section {
    return [failedBankInfos count];
}

Modify cellForRowAtIndexPath to look like the following:

- (UITableViewCell *)tableView:(UITableView *)tableView
    cellForRowAtIndexPath:(NSIndexPath *)indexPath {
 
    static NSString *CellIdentifier = @"Cell";
 
    UITableViewCell *cell =
        [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
 
    // Set up the cell...
    FailedBankInfo *info = [failedBankInfos objectAtIndex:indexPath.row];
    cell.textLabel.text = info.name;
    cell.detailTextLabel.text = [NSString stringWithFormat:@"%@, %@",
        info.city, info.state];
 
    return cell;
}

Lastly, select the MainStoryboard.storyboard and select the Master View Controller. Select the tableview cell in the table and set the style to Subtitle.

 

Compile and run the project, and if all looks well you should see the sample banks we added earlier!

Where to Go From Here?

Here’s the sample code for the project so far (direct download).

 

So far so good – except we’re missing the actual data from the failed banks. So next in this tutorial series we’ll cover how to preload/import existing data!

Adam Burkepile

Adam Burkepile is currently a full-time Software Consultant and independent iOS developer. If he isn’t at the computer, he’s probably getting punched in the face at Krav Maga. Check out his latest app – Pocket No Agenda. You can reach him for work or just to chat at Twitter, Github, his website, or email.

Comments

Add a Comment

Username:     Password:    

User Comments

104 Comments

[ 1 , 2 , 3 , 4 , 5 , 6 , 7 ]
  • Thanks for a great tutorial!
    dovtuan
  • Hi, thank you for greate tutorial! I have one thing that I don't understand:
    In FBCDMasterViewController, managedObjectContext variable hadn't been initialised before being used in viewDidLoad function:
    NSFetchRequest* fetchRequest = [[NSFetchRequest alloc]init];
    NSEntityDescription* entity = [NSEntityDescription entityForName:@"FailedBankInfo" inManagedObjectContext:managedObjectContext] ;
    How can it be used without being initialised or am I missed something?
    brucelee206
  • @brucelee206 it's because managedObjectContext was initialized and assigned to FBCDMasterViewController in AppDelegate
    usergio2
  • Ray,

    Hats off to you for creating the wonderful tutorials!

    Every time I run the program, I see a new line is added to the table. Why is it so?

    If you have already answered a similar question, please point me to the link.

    Thanks.
    rutvijk
  • rocky wrote:Hi, great tutorial works a treat. Although there was a bit of head scratching when I hit this line:

    Switch over to FailedBanksListViewController.m and make the following changes:


    think you meant

    Switch over to FailedBanksMasterViewController.m and make the following changes:


    Moving on to part 2! :)


    With the latest update, this line should now read:
    Switch over to FBCDMasterViewController.m and make the following changes:
    dejo
  • I am on my first compile and I am getting the following error -
    Code: Select all
    2012-11-25 15:17:57.107 FailedBankingCD[17321:c07] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Cannot create an NSPersistentStoreCoordinator with a nil model'


    I have restarted twice and am not sure what step I must be getting wrong... any suggestions or pointers on where I should look? Thanks
    theapapp
  • Hi,

    I was just wondering about this paragraphs:

    You’ll take an optimistic approach here when persisting your data. You’ll attempt to same the response first, without scanning for NSNull objects. If that attempt fails, then scan for NSNull objects, remove any that are found, and try again. If THAT attempt fails, then all you can do is to fall back to standard error handling techniques, where you alert the user or report the issue. this tutorial won’t cover those error handling operations, but you can easily add your own if you so desire.


    First, I assume the second sentence: "You'll attempt to same the response first..." is a typo and should be "save" instead of "same".

    Second, my actual question is, what does this paragraph mean with respect to the code. Here is the method it refers to and I have commented what I understand from it.

    Code: Select all
    - (void)writeJSONResponse:(id)response toDiskForClassWithName:(NSString *)className {

    //1. create a fileURL with the class name relative to the URL for the local directory
        NSURL *fileURL = [NSURL URLWithString:className relativeToURL:[self JSONDataRecordsDirectory]];

    //2. if when writing the response to file fails, log there was such an error and will attempt to remove NULLs
        if (![(NSDictionary *)response writeToFile:[fileURL path] atomically:YES]) {
            NSLog(@"Error saving response to disk, will attempt to remove NSNull values and try again.");
    //3. create a records array
            NSArray *records = [response objectForKey:@"results"];
    //4. create a nullFreeRecords array
            NSMutableArray *nullFreeRecords = [NSMutableArray array];
    //5. loop thru every record in the records array
            for (NSDictionary *record in records) {
    //6. create a nullFreeRecord dictionary with the current dictionary-record in the loop
                NSMutableDictionary *nullFreeRecord = [NSMutableDictionary dictionaryWithDictionary:record];
    //7. enumerate each KV pair in the current dictionary-record in the loop
    //8. if that record is NULL, replace that null value with nil???
                [record enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
                    if ([obj isKindOfClass:[NSNull class]]) {
                        [nullFreeRecord setValue:nil forKey:key];
                    }
                }];
    //9. add that once-NULL, but NOW-NIL record to a nullFreeRecords array
                [nullFreeRecords addObject:nullFreeRecord];
            }
    //10.Add those records to a nullFreeDictionary
            NSDictionary *nullFreeDictionary = [NSDictionary dictionaryWithObject:nullFreeRecords forKey:@"results"];
    //11.If writing this new nullFreeDictionary to file fails, NSLog again....???
            if (![nullFreeDictionary writeToFile:[fileURL path] atomically:YES]) {
                NSLog(@"Failed all attempts to save response to disk: %@", response);
            }
        }
    }


    I get lost in step 8 which is where i added the ? marks :)
    User avatarmarciokoko
  • The subclass creation is more complicated than it needs to be. If you select both entities before choosing New > File, then both subclasses are created at the same time so they know the other exists and the correct parent class is assigned.
    martinjbaker
  • Great Tutorial, thank you :mrgreen:

    Just one thing I learned somewhere else. If you select all the entities before creating the NSManageObject subclasses, they will all be created at the same time and will automatically know about each other.
    macaco
  • Yes Xcode generates the class files for you
    User avatarmarciokoko
  • JUST AWESOME, WANT MORE
    Laser100
  • Thanks for the tutorial. Very easy to follow and understand.
    vinhkhoa
  • usergio2 wrote:@brucelee206 it's because managedObjectContext was initialized and assigned to FBCDMasterViewController in AppDelegate


    Thanks
    nqsang
  • Hi, thanks for the tutorial.
    But I got a fault message when debug it.

    Tools : Xcode 4.6.2
    Source Code : direct download from https://github.com/acburk/CoreData-Tuto ... all/master
    iPhone : iOS6.1.3 / iPhone4S

    If I add "-com.apple.CoreData.SQLDebug 1", and run it more than once, fault will come(search fault fullfilled):


    2013-06-05 09:09:22.749 FailedBankCD[41981:907] CoreData: annotation: Connecting to sqlite database file at "/var/mobile/Applications/CDBC3016-1E2F-480A-9637-39725AD07267/Documents/FailedBankCD.sqlite"
    2013-06-05 09:09:22.755 FailedBankCD[41981:907] CoreData: sql: pragma cache_size=200
    2013-06-05 09:09:22.757 FailedBankCD[41981:907] CoreData: sql: SELECT Z_VERSION, Z_UUID, Z_PLIST FROM Z_METADATA
    2013-06-05 09:09:22.769 FailedBankCD[41981:907] CoreData: sql: BEGIN EXCLUSIVE
    2013-06-05 09:09:22.771 FailedBankCD[41981:907] CoreData: sql: SELECT Z_MAX FROM Z_PRIMARYKEY WHERE Z_ENT = ?
    2013-06-05 09:09:22.773 FailedBankCD[41981:907] CoreData: sql: UPDATE Z_PRIMARYKEY SET Z_MAX = ? WHERE Z_ENT = ? AND Z_MAX = ?
    2013-06-05 09:09:22.778 FailedBankCD[41981:907] CoreData: sql: COMMIT
    2013-06-05 09:09:22.786 FailedBankCD[41981:907] CoreData: sql: BEGIN EXCLUSIVE
    2013-06-05 09:09:22.789 FailedBankCD[41981:907] CoreData: sql: INSERT INTO ZFAILEDBANKDETAILS(Z_PK, Z_ENT, Z_OPT, ZINFO, ZCLOSEDATE, ZUPDATEDATE, ZZIP) VALUES(?, ?, ?, ?, ?, ?, ?)
    2013-06-05 09:09:22.793 FailedBankCD[41981:907] CoreData: sql: INSERT INTO ZFAILEDBANKINFO(Z_PK, Z_ENT, Z_OPT, ZDETAILS, ZCITY, ZNAME, ZSTATE) VALUES(?, ?, ?, ?, ?, ?, ?)
    2013-06-05 09:09:22.795 FailedBankCD[41981:907] CoreData: sql: COMMIT
    2013-06-05 09:09:22.804 FailedBankCD[41981:907] CoreData: sql: pragma page_count
    2013-06-05 09:09:22.806 FailedBankCD[41981:907] CoreData: annotation: sql execution time: 0.0019s
    2013-06-05 09:09:22.808 FailedBankCD[41981:907] CoreData: sql: pragma freelist_count
    2013-06-05 09:09:22.809 FailedBankCD[41981:907] CoreData: annotation: sql execution time: 0.0018s
    2013-06-05 09:09:22.812 FailedBankCD[41981:907] CoreData: sql: SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZCITY, t0.ZNAME, t0.ZSTATE, t0.ZDETAILS FROM ZFAILEDBANKINFO t0
    2013-06-05 09:09:22.815 FailedBankCD[41981:907] CoreData: annotation: sql connection fetch time: 0.0021s
    2013-06-05 09:09:22.816 FailedBankCD[41981:907] CoreData: annotation: total fetch execution time: 0.0041s for 2 rows.
    2013-06-05 09:09:22.818 FailedBankCD[41981:907] Name: Test Bank
    2013-06-05 09:09:22.822 FailedBankCD[41981:907] CoreData: sql: SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZCLOSEDATE, t0.ZUPDATEDATE, t0.ZZIP, t0.ZINFO FROM ZFAILEDBANKDETAILS t0 WHERE t0.Z_PK = ?
    2013-06-05 09:09:22.824 FailedBankCD[41981:907] CoreData: annotation: sql connection fetch time: 0.0024s
    2013-06-05 09:09:22.826 FailedBankCD[41981:907] CoreData: annotation: total fetch execution time: 0.0043s for 1 rows.
    2013-06-05 09:09:22.828 FailedBankCD[41981:907] CoreData: annotation: fault fulfilled from database for : 0x1fd530f0 <x-coredata://5F34EA02-C9BF-45F0-AF1D-81657EB74239/FailedBankDetails/p1>
    2013-06-05 09:09:22.830 FailedBankCD[41981:907] Zip: 12345
    2013-06-05 09:09:22.832 FailedBankCD[41981:907] Name: Test Bank
    2013-06-05 09:09:22.834 FailedBankCD[41981:907] Zip: 12345
    2013-06-05 09:09:22.849 FailedBankCD[41981:907] CoreData: sql: SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZCITY, t0.ZNAME, t0.ZSTATE, t0.ZDETAILS FROM ZFAILEDBANKINFO t0
    2013-06-05 09:09:22.851 FailedBankCD[41981:907] CoreData: annotation: sql connection fetch time: 0.0024s
    2013-06-05 09:09:22.853 FailedBankCD[41981:907] CoreData: annotation: total fetch execution time: 0.0044s for 2 rows.
    leidong
[ 1 , 2 , 3 , 4 , 5 , 6 , 7 ]

Other Items of Interest

Ray's Monthly Newsletter

Sign up to receive a monthly newsletter with my favorite dev links, and receive a free epic-length tutorial as a bonus!

Advertise with Us!

Vote for Our Next Tutorial!

Every week, we alternate between Gaming and Gaming tutorial votes. This week: Non-Gaming!

    Loading ... Loading ...

Last week's winner: Advanced UIView Animations. Coming soon!

Suggest a Tutorial - Past Results

Our Books

Our Team

Tutorial Team

  • Colin Eberhardt
  • Abdul Azeem Khan
  • Sohei Azarpour

... 42 total!

Editorial Team

  • Mic Pringle
  • Ray Wenderlich
  • Matt Galloway

... 9 total!

Translation Team

  • Team Tyran
  • Hadeel Almushaigh
  • Cosmin Pupaza

... 27 total!

Subject Matter Experts

  • Marcio Valenzuela
  • Richard Casey
  • Adam Eberbach

... 5 total!