Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS:Swift:CoreData: Values are not stored using PrivateManagedObjectContext

In my application I have used one class (say CoredataHandler.swift) for storing and retrieving objects. I have followed this tutorials . I have used Strategy 2: Parent/Child Managed Object Contexts. But Objects are not stored in the coredata. Instead of using NSOperation I have used normal class object.

class CoreDataHandler: NSObject {

//static var sharedInstance:CoreDataHandler = CoreDataHandler()

var privateManagedObjectContext:NSManagedObjectContext?
var mainManagedObjectContext:NSManagedObjectContext?


 override init() {

    print("core data handler constructor called")
    super.init()

    let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
    let privateManagedObjectContextlocal = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
    privateManagedObjectContextlocal.parentContext = appDelegate.managedObjectContext

    self.privateManagedObjectContext = privateManagedObjectContextlocal

    self.mainManagedObjectContext = appDelegate.managedObjectContext

    let notificationCenter = NSNotificationCenter.defaultCenter()
    notificationCenter.addObserver(self, selector: #selector(CoreDataHandler.managedObjectContextDidSave(_:)), name: NSManagedObjectContextDidSaveNotification, object: privateManagedObjectContext)
}

private func insertData(entityName:String,dataDictionary:Dictionary<String, AnyObject?>){
    synced(self) { () -> () in

        //        let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate

        let entityDescription = NSEntityDescription.entityForName(entityName, inManagedObjectContext: self.privateManagedObjectContext!)

        let newPerson = NSManagedObject(entity: entityDescription!, insertIntoManagedObjectContext: self.privateManagedObjectContext!)

        for (myKey, myVal) in dataDictionary {

            if myVal is Int {

                if let result_number = myVal as? NSNumber
                {
                    let result_string = "\(result_number)"
                    newPerson.setValue(result_string, forKey: myKey)

                }


            }else{
                newPerson.setValue(myVal, forKey: myKey)

            }

        }

        //print("insertData",newPerson)

        do {
            if ((self.privateManagedObjectContext?.hasChanges) != nil){

                try self.privateManagedObjectContext!.save()
            }



        } catch {

            // Replace this implementation with code to handle the error appropriately.

            // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.

            let nserror = error as NSError

            NSLog("Unresolved error \(nserror), \(nserror.userInfo)")

            abort()

        }
    }
}

// MARK: - Insert

func insertOfferObjects(arrOffer : Array<FoodItem>?) {
    synced(self) { () -> () in


        //Step1: Adding Offer Items
        if let _ = arrOffer {
            var foodArr:Array<NSManagedObject> = Array()

            for foodObj : FoodItem in arrOffer! {

                let offerItemEntity = self.createFoodItemEntity(foodObj)
                foodArr.append(offerItemEntity)

            }

            self.insertData("OfferCategory", dataDictionary: ["categoryTitle": "Offers", "foodItemArray": NSOrderedSet(array: foodArr)])

        }
    }
}

Values are not stored in the coredata. Please provide me the best way to do.

EDITED: Update :: From Answers, Need to save parent when child context is saved

            self.privateManagedObjectContext?.performBlockAndWait({ 

                if ((self.privateManagedObjectContext?.hasChanges) != nil){

                     do {

                        print("It has changes...............")

                        try self.privateManagedObjectContext!.save()

                        self.mainManagedObjectContext?.performBlock({
                            do {
                            try self.mainManagedObjectContext!.save()
                            }catch{

                            }
                        })

                     }catch {

                        // Replace this implementation with code to handle the error appropriately.

                        // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.

                        let nserror = error as NSError

                        NSLog("Unresolved error \(nserror), \(nserror.userInfo)")

                        abort()

                    }

                }
            })
like image 208
Sridhar Avatar asked Jul 26 '16 06:07

Sridhar


1 Answers

Saving a child context just pushes those changes up to the parent context. Unless you're also saving the parent context (which pushes changes to the persistent store) then your changes will not be written to disk.

From the NSManagedObjectContext class reference:

When you save changes in a context, the changes are only committed “one store up.” If you save a child context, changes are pushed to its parent. Changes are not saved to the persistent store until the root context is saved. (A root managed object context is one whose parent context is nil.)

If you're new to core data, I'd suggest not worrying about concurrency and multiple contexts unless you actually have a problem that requires that to solve it. Unless you're dealing with thousands of records or you're interested in creating editing contexts for reversible changes, a single main thread context will do everything you need.

like image 63
jrturton Avatar answered Oct 07 '22 18:10

jrturton