Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Refreshing UITableView Asynchronously after Core Data Loaded Swift

I have a UITableView, tViewNews

I have a refresh function which downloads data from my server, stores it into core data, and then the table view loads this data from core data.

It works perfectly

func refresh(refreshControl: UIRefreshControl) {

    self.newsArray = [NewsItem]()
    self.newslists = [[NewsItem]]()
    self.getNewsFromServer()
    self.getNewsFromCoreData()
    self.tViewNews.reloadData()

    refreshControl.endRefreshing()
}

Now, when the user first opens the news viewDidLoad(), I would like for the table view to first load from the core data, then asynchronously populate my table view array from the server (using precisely the same method as the refresh function) and then reload the table view.

So I have tried the following code in my viewDidLoad() function.

override func viewDidLoad() {
    super.viewDidLoad()

    // Getting news from Core Data
    getNewsFromCoreData()

    // Updating core data from server and populating table view from core data
    dispatch_async(dispatch_get_main_queue()) {

        self.newsArray = [NewsItem]()
        self.newslists = [[NewsItem]]()
        self.getNewsFromServer()
        self.getNewsFromCoreData()
        self.tViewNews.reloadData()

    }

As you can see the functions being run inside the async request are identical to those inside the refresh function.

But!, the refresh function functions properly, populating and reloading the table view. But the async request does absolutely nothing. The table view remains empty. But the functions are running, as tested with print statements.

Anyone know why this is the case?

EDIT - Added extra fucntions

Get Core Data

func getNewsFromCoreData() {
    let temp = StaffCoreData()
    temp.getAllNews()

    newsDates = Dictionary<Int, [NewsItem]>()

    for newsobj in temp.newsArray{

        if var curdate = newsDates[toNewsItem(newsobj).age]{

            curdate.append(toNewsItem(newsobj))
            newsDates[toNewsItem(newsobj).age] = curdate


        }else{

            newsDates[toNewsItem(newsobj).age] = [toNewsItem(newsobj)]

        }
    }

    for var i = 0; i<50; ++i{if let curdate = newsDates[i]{newslists.append(curdate)}}

Get Server Data

runs instance with following method:

func NewsCallReturnsWithSuccess(data: NSData) {

    if let jsonObject : AnyObject! = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) {
        if let statusesArray = jsonObject as? NSArray{

            newsArray.removeAll(keepCapacity: true)

            for item in statusesArray {
                let datacon : NSData = item.dataUsingEncoding(NSUTF8StringEncoding)!
                let jsonObject : NSDictionary! = NSJSONSerialization.JSONObjectWithData(datacon, options: NSJSONReadingOptions.MutableContainers, error: nil) as! NSDictionary

                let title : NSString = jsonObject.objectForKey("title") as! NSString
                let content : NSString = jsonObject.objectForKey("content") as! NSString
                let publishedby : NSString = jsonObject.objectForKey("publishedby") as! NSString
                let modified : NSString = jsonObject.objectForKey("modified") as! NSString
                let imageurl : NSString = jsonObject.objectForKey("imageurl") as! NSString
                let category : NSString = jsonObject.objectForKey("category") as! NSString

                let newsItem = NewsItem(title: title as String, content: content as String, category: category as String, imageURL: imageurl as String, publishedBy: publishedby as String, modified: modified as String)

                newsArray.append(newsItem)
                }

            //add complete array to CoreData
            let temp = StaffCoreData()
            temp.addArrayOfNew(newsArray)

        }

    }

}
like image 650
Greg Peckory Avatar asked Oct 19 '22 07:10

Greg Peckory


1 Answers

When you are using a different thread for loading your data, you have to return to the main thread when finished loading to update the UI.

Like:

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
        // load data
        dispatch_async(dispatch_get_main_queue()) {
            // update ui
        }
    }

UPDATE

Pls show us your getNewsFromCoreData() and getNewsFromServer() methods and maybe your cellForRowAtIndexPath, too.

override func viewDidLoad() {
    super.viewDidLoad()

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
        // load data
        self.newsArray = [NewsItem]()
        self.newslists = [[NewsItem]]()
        self.getNewsFromServer()
        self.getNewsFromCoreData()
        dispatch_async(dispatch_get_main_queue()) {
            // update ui
            self.tViewNews.reloadData()
        }
    }
}
like image 134
matthias Avatar answered Oct 21 '22 23:10

matthias