Search code examples
swiftcore-dataswift2uiprogressview

Use Core Data to Insert data asynchronously in Swift with UIProgressView


I receive a JSon that I convert to a array of dictionaries and insert this array to Core Data.

The result of this Array has 8.000 items.

How to insert an UIProgressView while the Core Data is working with the code bellow?

Thank you!

func CreateContext() -> NSManagedObjectContext {
    let AppDel: AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
    let Context: NSManagedObjectContext = AppDel.managedObjectContext
    return Context
}

static func AddData(arrayDictionary: [[String : AnyObject]]) {
    for Item in arrayDictionary {
        let Context = CreateContext()
        let DAO = NSEntityDescription.insertNewObjectForEntityForName("Customers", inManagedObjectContext: Context)

        // Insert at Core Data
        if let item = Item["UserID"] as? Int {
            DAO.setValue(item, forKey: "userID")
        }
        if let item = Item["Name"] as? String {
            DAO.setValue(item, forKey: "name")
        }
        if let item = Item["Email"] as? String {
            DAO.setValue(item, forKey: "email")
        }

        do {
            try Contexto.save()
        } catch {
            let nserror = error as NSError
            //abort()
        }
        }
    }
}

EDIT

The data is being inserted by a custom class. I tried to create a Protocol and Delegate but I don't know where is the error (sincerely, I don't know how to work with Protocol and Delegate. I tried to follow the example in Howto Update a gui (progressview) from a download delegate in swift)

My ViewController class:

import UIKit

protocol ProgressBarDelegate: class {
    func UpdateProgressBar(progress: Float)
}

class MyViewController: UIViewController {

    @IBOutlet var progressView: UIProgressView!

    func AddDataFromArray() {
        let DB = MyCustomClass()
        DB.delegate?.UpdateProgressBar(progressView.progress)
        DB.AddData(getArrayDictionaryData())
    }

}

My Custom class:

class MyCustomClass {

    var delegate: ProgressBarDelegate?

    func initWithDelegate(delegate: ProgressBarDelegate) {
        self.delegate = delegate
    }

    func CreateContext() -> NSManagedObjectContext {
        let AppDel: AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
        let Context: NSManagedObjectContext = AppDel.managedObjectContext
        return Context
    }

    func AddData(arrayDictionary: [[String : AnyObject]]) {
        var addedItems: Int = 0
        var Progress = Float()

        for Item in arrayDictionary {
        addedItems += 1
        Progress = ((Float(100.0) / Float(arrayDictionary.count)) * Float(addedItems)) / Float(100)

            let Context = CreateContext()
            let DAO = NSEntityDescription.insertNewObjectForEntityForName("Customers", inManagedObjectContext: Context)

            // Insert at Core Data
            if let item = Item["UserID"] as? Int {
                DAO.setValue(item, forKey: "userID")
            }
            if let item = Item["Name"] as? String {
                DAO.setValue(item, forKey: "name")
            }
            if let item = Item["Email"] as? String {
                DAO.setValue(item, forKey: "email")
            }

            do {
                try Contexto.save()
            } catch {
                let nserror = error as NSError
                //abort()
            }

            delegate!.UpdateProgressBar(Progress)
        }
    }
}

Solution

  • You seem to be misunderstanding the relationships a little bit.

    A class can take a delegate if it requires some information to be supplied or wants to make a callback to let someone know that something happened. The delegate implements the methods specified in the delegate protocol and handles the notifications:

    Delegate (observer)
      -> conforms to the delegate protocol
      -> registers itself
      -> handles notifications
    
    Interesting class
      -> holds a reference to a delegate
      -> notifies the delegate when things happen
    

    In your case. MyViewController should conform to the delegate protocol, so it should implement UpdateProgressBar. It creates an instance of MyCustomClass to do some work for it and sets itself as the delegate. MyCustomClass then does some work and calls UpdateProgressBar, where MyViewController then updates the UI.

    You get a crash at the moment because you never set the delegate. This line:

    DB.delegate?.UpdateProgressBar(progressView.progress)
    

    should be

    DB.delegate = self
    

    aside:

    Don't call something CreateContext if it isn't actually creating something. Also, the first letter of functions should be lower case.