0

Whenever I run my app, the first time the view containing the tableview loads, the table view does not get populated. But once i switch tabs (i am using a tab bar controller), and then switch back, the table view becomes populated. Does anyone have any ideas on how to fix this? Here is the code:

import UIKit
import Parse

class NotesViewController: UITableViewController {

var notes = [PFObject]()

var cacheNotes = Bool()

@IBOutlet var showContentTableView: UITableView!

func findNotes() {

    if let user = PFUser.currentUser()?.username! {

        let network = Reachability.isConnectedToNetwork()

        let query = PFQuery(className: "notes")
        query.whereKey("username", equalTo: user)

        if network == true {
            print("connected to network")
        } else {
            ("not connected to network")
            query.fromLocalDatastore()
        }

        query.findObjectsInBackgroundWithBlock({ (objects: [PFObject]?, error: NSError?) -> Void in
            if error == nil {

                self.notes = objects!

                for object in objects! {
                    if self.cacheNotes == true && network == true {object.pinInBackground()}
                }
            }
        })

    }



    showContentTableView.reloadData()
}


override func viewDidLoad() {
    super.viewDidLoad()

    // Uncomment the following line to preserve selection between presentations
    // self.clearsSelectionOnViewWillAppear = false

    // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
    // self.navigationItem.rightBarButtonItem = self.editButtonItem()

    if NSUserDefaults.standardUserDefaults().objectForKey("cacheNotes") == nil {
        NSUserDefaults.standardUserDefaults().setObject(true, forKey: "cacheNotes")
    }

}

override func viewDidAppear(animated: Bool) {

    cacheNotes = NSUserDefaults.standardUserDefaults().objectForKey("cacheNotes") as! Bool


    print(cacheNotes)
    findNotes()
    showContentTableView.reloadData()
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

// MARK: - Table view data source

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    // #warning Incomplete implementation, return the number of sections
    return 1
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    // #warning Incomplete implementation, return the number of rows
    return notes.count
}


override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
    // Configure the cell...
    cell.textLabel?.text =  notes[indexPath.row]["title"] as? String

    return cell
    }
}
1
  • 1
    You need to reload the table inside the closure/block of findObjectsInBackgroundWithBlock Commented Oct 18, 2015 at 21:45

1 Answer 1

1

When you retrieve data from Parse using findObjectsInBackgroundWithBlock the network operation happens in the background, while the rest of the function keeps executing. So, the showContentTableView.reloadData() happens immediately, before the data has been returned. You need to reload the table data once the network operation has completed, that is, inside the block/closure

func findNotes() {
    if let user = PFUser.currentUser()?.username! {

        let network = Reachability.isConnectedToNetwork()

        let query = PFQuery(className: "notes")
        query.whereKey("username", equalTo: user)

        if network == true {
            print("connected to network")
        } else {
            ("not connected to network")
            query.fromLocalDatastore()
        }

        query.findObjectsInBackgroundWithBlock({ (objects: [PFObject]?, error: NSError?) -> Void in
            if error == nil {

                self.notes = objects!

                showContentTableView.reloadData()

                for object in objects! {
                    if self.cacheNotes == true && network == true {object.pinInBackground()}
                }
            }
        })
    }
}

Also, I would suggest that you call findNotes from viewWillAppear rather than viewDidAppear - it will get a head start on populating the data before the table is onscreen.

Sign up to request clarification or add additional context in comments.

1 Comment

I've made the suggested adjustments and it works. Thank you, and thank you for reminding me of the asynchronous blocks within the parse framework.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.