CRUD Operations using Core data - Swift

I hope you are familiar with Core data fundamentals. It is not a Pure database and it is ORM blah.. blah.. blah.. Here I'm starting with Xcode.



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.
import CoreData
Add below code in Top of AppDelegate.swift file to access globally.
let kEntityStr = "Contacts"
let kNameStr = "name"
let kPhoneStr = "phonenum"

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

----------------------------------------------------------------------------------------------
ListViewController
----------------------------------------------------------------------------------------------

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

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

    let fetchRequest = NSFetchRequest()
    fetchRequest.entity = entityDescription

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

    } catch {
        let fetchError = error as NSError
        print(fetchError)
    }
}

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

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

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

}

Now code for UITableViewDataSource methods :
override 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 :
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
    return true
}

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

To edit a record call segue and pass record index.
override 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)
@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.
override 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 
import CoreData

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

Constant and Variable 
let 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.
override func viewDidLoad() {
    super.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.
@IBAction func btnCancelTappe(sender: AnyObject) {
    self.dismissViewControllerAnimated(true, completion: nil)
}

To add / edit record i have coded in IBAction of Done button.
@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

Thanks.

CRUD Operations using Core data - Swift CRUD Operations using Core data - Swift Reviewed by KIRIT MODI on 05:33:00 Rating: 5

No comments:

Powered by Blogger.