Persisting Data Using Core Data

Core Data is basically a model layer technology which helps to build the model layer that represents the state of the app. Core Data can also be used as a persistent technology which helps to persist the state of the model object to the file storage. In this post, we will learn how to use Core Data to persist data, say, username and password given by the user in a persistent storage/database. Here are the prerequisites

  • Should have Xcode 5 running on your Mac
  • Fair knowledge on Xcode/iOS development
  • Should have created any applications using basic UI elements like UILabel, UIButton,etc

Lets get started by creating a Single View Application as shown below

CredentialManager_01

 

Open Main.storyboard and embed the view controller in a navigation controller. Now, drag and drop two UIViews in the storyboard and name it as RegistrationView and LoginView. The first time when the application is launched, we will show the RegistrationView. Once the user enters the credentials and logs in, for subsequent launches, we will show the LoginView. In the RegistrationView, create IBOutlets for the textfields and methods for the buttons as show below

CredentialManager_02

Similarly, In the LoginView, create IBOutlets for the textfields and methods for the buttons as shown below

CredentialManager_03

 

Before we get started with Core Data, lets write some logic to show registration screen on the first launch of the application.We store a flag in NSUserDefaults to indicate whether its a first time launch or not.

NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
NSString *launchFlag = [userDefaults objectForKey:@"LaunchFlag"];
self.isFirstTimeLaunch = (launchFlag.length) >0 ? YES:NO;

Handle basic operations like showing alert if username & password fields are blank and update the methods which gets called on Register/Login. Now, lets start writing code to persist user credentials using Core Data. Core Data has 3 main components – Managed Object Model – Its a database schema, contains definitions for each of the Entities that you are storing in the database Persistent Store Coordinator – Its a database connection which has the information about name and location of the database Managed Object Context – Its a single instance (in most of the case) which holds all the managed objects

CredentialManager_04

 

A simple way to generate code for Core Data is to create a Master-Detail Application and marking the checkbox when prompted for “Use Core Data”. I don’t know why Apple has provided this option only in Master-Detail Application.

CredentialManager_05 CredentialManager_06 CredentialManager_07

 

Now, use this code in our application to create a data base schema to store the login credentials of the user. Copy the core data code in the Master-Detail Application AppDelegate and paste it in our application CredentialManager AppDelegate. If you try to compile our application, it will throw an error pointing NSPersistentStoreCoordinator & NSManagedObjectModel. Inorder to resolve this error, add CoreData framework in the Build Phases as shown below.

CredentialManager_08

 

Import core Data in AppDelegate #import <CoreData/CoreData.h> This should resolve all our errors !! Right click on the project navigation panel, select Core Data, select DataModel, name the model as “Credentials” and click on create as shown below

CredentialManager_09

 

Once Credentials.xcdatamodeld is created, click on that make following changes

1. Click on Add Entity and name the entity as “UserCredentials”

2. Click on + symbol in the attributes and add attributes username & password, select the type as string. This will be our database schema. Note : You can add more entities and create relationships between entities by using Editor Style (3)

CredentialManager_10

 

Now, go back to AppDelegate and change the name of momd to Credentials and sqlite to CredentialManager.sqlite as shown below

CredentialManager_11

The beauty of Core Data is that we need not have to take pain in creating model classes for the entities in our data base schema. Create a new file -> Core Data -> NSManagedObject subclass , select Credentials, select UserCredentials to create a new modal file. We will call a method when user taps on Register/Login button. This method will have the logic to save or update the credentials entered by the user. I know we should not save the credentials in clear text but lets not worry about the encryption part as this post is more about persisting the data ! 🙂

Paste this code in the method which gets called when user taps Register/Login button

BOOL isSuccess = NO;
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSError *error;
// Fetch all the available username/password stored in the database
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"UserCredentials"
                                              inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
if ([fetchedObjects count]) {    
        UserCredentials *userCredentials = [fetchedObjects objectAtIndex:0];
        if ([[userCredentials.username lowercaseString] isEqualToString:[self.usernameTextField.text lowerca seString]]

        && [[userCredentials.password lowercaseString] isEqualToString:[self.passwordTextField.text lowercaseString]])
        {

            userCredentials.username = self.usernameTextField.text;

            userCredentials.password = self.passwordTextField.text;

            if (![context save:&error]) {

                NSLog(@"Error in saving Credentials: %@", [error localizedDescription]);

            }else{

                NSLog(@"Update Credentials in DB : Username - %@, Password - %@", userCredentials.username, userCredentials.password);

                isSuccess = YES;

            }

        }

        else{

            isSuccess = NO;

        }

    }else{

        UserCredentials *userCredentials = [NSEntityDescription insertNewObjectForEntityForName:@"UserCredentials" inManagedObjectContext:context];

        userCredentials.username = self.usernameTextField.text;

        userCredentials.password = self.passwordTextField.text;

        if (![context save:&error]) {

            NSLog(@"Error in saving Credentials: %@", [error localizedDescription]);

        }else{

            NSLog(@"Insert Credentials in DB : Username - %@, Password - %@", userCredentials.username, userCredentials.password);

            isSuccess = YES;

        }

    }

Here, we are going to rely on the managed object context from AppDelegate. We query the user credentials from the entity we created in our Credentials.xcdatamodel.  With the help of NSFetchRequest & NSEntityDescription, we query if any credentials are saved in the DB. If present, we compare with the values given by the user and display messages based on the result of comparison operation!

CredentialManager_13

 

Hope this post helped you to understand how Core Data can be used to persist data in your application. You can download the source code from this link.

Leave a comment