1

I am loading Core Data from an online database and then populating my tableview from core data (so that it will be available offline as well). Everything is working fine, except I can't figure out how to get the completion handler working so that the fetch completes before loading. I was following this example, but can't figure out what it doesn't call my function (CloudUpdate).

func CloudUpdate(completionHandler: () -> Void) {
            var appDel:AppDelegate = (UIApplication.sharedApplication().delegate as AppDelegate)
            var context:NSManagedObjectContext = appDel.managedObjectContext!

            // Clear the table before reloading to avoid duplicates

            let request = NSFetchRequest(entityName: "News")

            let managedObjectContext: NSManagedObjectContext? = (UIApplication.sharedApplication().delegate as? AppDelegate)?.managedObjectContext
            var fetchedResultsController: NSFetchedResultsController?
            var results:NSArray = context.executeFetchRequest(request, error: nil)!

            var bas: NSManagedObject!

            for bas: AnyObject in results
            {
                context.deleteObject(bas as NSManagedObject)
            }

            context.save(nil)


            let url = NSURL(string: "http://www.appsforteacher.com/news.php")
            let task = NSURLSession.sharedSession().dataTaskWithURL(url!) {(data, response, error) in
                var d = NSString(data: data, encoding: NSUTF8StringEncoding)
                var arr = d!.componentsSeparatedByString("<")
                var dataweneed:NSString = arr[0] as NSString
                if let data = NSJSONSerialization.JSONObjectWithData(dataweneed.dataUsingEncoding(NSUTF8StringEncoding)!, options: NSJSONReadingOptions.MutableContainers, error: nil) as? NSArray
                {
                    for dd in data{

                        //time is set to UTC. See if you can fix it.
                        var dateFormatter = NSDateFormatter()
                        dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"


                        var courseID : Int = (dd["courseID"]! as String).toInt()!
                        var timeStamp =  dateFormatter.dateFromString(dd["timeStamp"]! as String)
                        var heading : String = dd["heading"]! as String
                        var detail : String = dd["detail"]! as String


                        var newNews = NSEntityDescription.insertNewObjectForEntityForName("News", inManagedObjectContext: context) as NSManagedObject
                        newNews.setValue(heading, forKey: "heading")
                        newNews.setValue(detail, forKey: "detail")
                        newNews.setValue(timeStamp, forKey: "timeStamp")
                        newNews.setValue(courseID, forKey: "courseID")
                        context.save(nil)

                    }
                }
            }

            task.resume()

            completionHandler()
        }

        func application(application: UIApplication!, performFetchWithCompletionHandler completionHandler: ((UIBackgroundFetchResult) -> Void)!) {
            CloudUpdate() {
                completionHandler(UIBackgroundFetchResult.NewData)
            }
        }
Community
  • 1
  • 1
  • 1
    Are you saying that you don't want to call `completionHandler` until your data task is done? If so, move the `completionHandler()` line _inside_ the `dataTaskWithURL` closure. And remember, if you want that to be called on the main thread, you'll have to manually dispatch it back to the main thread (because that closure happens on background thread). – Rob Apr 09 '15 at 21:39
  • Ok, that makes sense to move it inside, but right now the code doesn't execute. I was calling the CloudUpdate separately and it would execute, but how do I get it to kick off now? Do I call the application? – David Burnham Apr 09 '15 at 22:48
  • OK, you have to clarify: Are you saying that `performFetchWithCompletionHandler` is never called? Or that it is getting called, but CloudUpdate is not getting called? That doesn't seem possible. Now, possible problems include that you're not calling the `completionHandler` quickly enough (shouldn't be more than 30 seconds, IIRC ... if its longer than that, you should use background `NSURLSession`). Or maybe you put the completion handler in the wrong place (it's in the `dataTaskWithURL` block, but not the `if let data =...` block). It's hard to say on the basis of the limited info provided. – Rob Apr 10 '15 at 01:39
  • By the way, it looks like you return `.NewData` regardless of whether there was real data or not. If you're going to be a good citizen, you should do the call to see if there was new data, return `.NewData` if so, and use `.NoData` if not. Also, it looks like the signature of this function (in latest release, at least) is that `application` and `completionHandler` of `performFetchWithCompletionHandler` are not optional, so you might want to check that, too. – Rob Apr 10 '15 at 01:42

0 Answers0