W3Schools Learner's Blog

W3Schools Programming knowledge summary website



CRUD Operations using Core data - Swift

How to do CRUD Operations using Core data with Swift, Here is a best tutorial to do CRUD Operations in ios.

Step 1 : Create New iOS Application with "Single View Application"

Step 2 :  Name you app, and don't forget to CHECK "Use Core Data" from bottom section. By checking this xCode will add ".xcdatamodeld" file automatically in project and also write code for context in AppDelegate.swift. So you don't have to make any efforts for context handling.

Step 3 : In AppDelegate.swift file you can find some code for core data that xCode has writes for you.

Step 4 : Here you can see file structure of ".xcdatamodeld" file. 

Step 5 : To create new entity in Core data you can find "Add Entity" button at bottom. Edit the default name to your required name. Like Person, Friends, History, List. This name will considered in query as a table name (In sql database query to update table we are using table name in sql query, same like here the entity name will used as a table name.)

Step 6 : After adding entity (Table) add its attribute (Field) and also specify types of attribute.

Step 7 : Let's make pretty design for app. I have taken 2 controllers. 

> The first is Table View Controller which will show list of record. In TableView the prototype cell is customised and there is two labels for name and phone number. Also added one + button on top right to present second view controller.
> Second view controller has two textfield to accept text from user and there is two buttons to handle navigation and saving data.

And now the Coding is started. 

Write import statement in view controllers.
1import CoreData
Add below code in Top of AppDelegate.swift file to access globally.
123456let kEntityStr = "Contacts"
let kNameStr = "name"
let kPhoneStr = "phonenum"

class AppDelegate: UIResponder, UIApplicationDelegate {.....}


In TableViewController create local constant of appdelegate object to access managedContext.
1let appDelegateObj : AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate

Create array of NSManagedObject
1var dataArray = [NSManagedObject]()
Write below function to fetch data.
123456789101112131415func fetchData() {
    let entityDescription = NSEntityDescription.entityForName(kEntityStr, inManagedObjectContext: appDelegateObj.managedObjectContext)

    let fetchRequest = NSFetchRequest()
    fetchRequest.entity = entityDescription

    do {
        dataArray = try appDelegateObj.managedObjectContext.executeFetchRequest(fetchRequest) as! [NSManagedObject]

    } catch {
        let fetchError = error as NSError

Call this function in viewDidAppear() So every time when screen is appeared the data will be refreshed.
1234override func viewDidAppear(animated: Bool) {

I have created custom class for UITableViewCell.
123456class ContactCell : UITableViewCell {

    @IBOutlet weak var lblName: UILabel!
    @IBOutlet weak var lblContactNo: UILabel!


Now code for UITableViewDataSource methods :
12345678910override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return self.dataArray.count

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! ContactCell
    cell.lblName.text = dataArray[indexPath.row].valueForKey(kNameStr) as? String
    cell.lblContactNo.text = dataArray[indexPath.row].valueForKey(kPhoneStr) as? String
    return cell

To delete record write below code :
1234567891011121314151617override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
    return true

override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
    if editingStyle == .Delete {
        do {
            try appDelegateObj.managedObjectContext.save()
            tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
        } catch {
            let saveError = error as NSError

To edit a record call segue and pass record index.
123override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    self.performSegueWithIdentifier("SegueAdd", sender: indexPath.row)

To add new record call segue to another view controller. This is a action of "+" button from first view controller (Top Right positioned)
123@IBAction func btnAddTapped(sender: AnyObject) {
    self.performSegueWithIdentifier("SegueAdd", sender: -1)

Segue to Add / Edit view controller. Here i'm passing index of record. If the call is from add new record then the sender value will be -1 to identify the request.
12345678override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "SegueAdd" {
        let vc : AddVC = segue.destinationViewController as! AddVC
        vc.dataArray = dataArray
        vc.editRecNo = sender as! Int


ADD / EDIT View controller.

Don't forgot to add 
1import CoreData

Here we have two IBOutlets of UITextField.
12@IBOutlet weak var txtName: UITextField!
@IBOutlet weak var txtPhone: UITextField!

Constant and Variable 
123let appDelegateObj : AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
var editRecNo = Int()
var dataArray = [NSManagedObject]()

In viewDidLoad() check if request for edit record or not. If editRecNo variable is equal to -1 then its new record request otherwise have to edit.
1234567override func viewDidLoad() {
    if editRecNo != -1 {
        txtName.text = self.dataArray[editRecNo].valueForKey(kNameStr) as? String
        txtPhone.text = self.dataArray[editRecNo].valueForKey(kPhoneStr) as? String

To close view controller "X" button from top left.
123@IBAction func btnCancelTappe(sender: AnyObject) {
    self.dismissViewControllerAnimated(true, completion: nil)

To add / edit record i have coded in IBAction of Done button.
1234567891011121314151617181920212223242526@IBAction func btnDoneTapped(sender: AnyObject) {

    if editRecNo != -1 {
        self.dataArray[editRecNo].setValue(txtName.text!, forKey: kNameStr)
        self.dataArray[editRecNo].setValue(txtPhone.text!, forKey: kPhoneStr)

        do {
            try self.dataArray[editRecNo].managedObjectContext?.save()
        } catch {
            print("Error occured during updating entity")
    } else {
        let entityDescription = NSEntityDescription.entityForName(kEntityStr, inManagedObjectContext: appDelegateObj.managedObjectContext)
        let newPerson = NSManagedObject(entity: entityDescription!, insertIntoManagedObjectContext: appDelegateObj.managedObjectContext)
        newPerson.setValue(txtName.text!, forKey: kNameStr)
        newPerson.setValue(txtPhone.text!, forKey: kPhoneStr)

        do {
            try newPerson.managedObjectContext?.save()
        } catch {
            print("Error occured during save entity")

    self.dismissViewControllerAnimated(true, completion: nil)

In above code i have checked that if the request for edit record then get the managed object from the Array and update the value from the textfield. Then save the context.

If the request to add new record then create NSEntityDescription  it taken entity name for identification of the entity and object of managed object context.
Then create new NSManagedObject with NSEntityDescription  and object of managed object context. NSManagedObject has many types of initialisation. Here we are about to add record so we have used  insertIntoManagedObjectContext

Now set the value  NSManagedObject and save the context. After completion of add or edit dismiss the view controller. List will updated automatically.

Download Demo project of CoreData : CoreDataDemo-Swift

No comments:

Post a Comment

Note: only a member of this blog may post a comment.