Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

iOS

How can I retrieve data from Parse into a Table View on iOS 9?

Hello Everyone,

I've been working on this app for a while now and I'm facing a problem which I don't know how to solve. I'm using Parse for my data management. I can read data from different classes one by one, but now I want to list my data into a table view. I've tried many options but I can't solve this problem.

How can I have global variables that can store some data I can use in any function? How can I set the number of rows based on the count function I do on the Parse query? How can I set the cell titles to my Object titles from Parse?

Can you guide me please? Thanks in advance. I'm sharing my code below:

import UIKit
import Parse

class faFirstTableViewController: UITableViewController {

    var totalRows = 3
    var objectTwo = ["arash"]

    override func viewDidLoad()
    {
        super.viewDidLoad()
        let query = PFQuery(className:"TestObject")
        query.whereKey("foo", equalTo:"bar")
        query.findObjectsInBackgroundWithBlock
            {
                (objects: [PFObject]?, error: NSError?) -> Void in

                if error == nil
                {
                    // The find succeeded.
                    print("Successfully retrieved \(objects!.count) scores.")
                    // Do something with the found objects
                    if let objects = objects as [PFObject]?
                    {
                        for object in objects
                        {
                            print(object.objectId)
                            self.objectTwo.append(object.objectId!)
                        }

                        self.totalRows = objects.count
                        print(self.totalRows)
                    }
                }
                else
                {
                    // Log details of the failure
                    print("Error: \(error!) \(error!.userInfo)")
                }
        }
        // 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()
    }

    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 0
    }

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


    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let Cell: faFirstTableViewCell = tableView.dequeueReusableCellWithIdentifier("Cell") as! faFirstTableViewCell

        Cell.CellTitle.text = objectTwo[indexPath.row] as String

        return Cell
    }

1 Answer

Martin Wildfeuer
PLUS
Martin Wildfeuer
Courses Plus Student 11,071 Points

Hey there!

First of all, in order to display data in a table view, it has to have at least one section. Therefore, in your case numberOfSectionsInTableView should return 1.

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 1
}

Secondly, numberOfRowsInSection should return the number of objects in your datasource, in your case called objectTwo. No need to use a temporary var called totalRows. This is particularly important here as you init it with 3, but your datasource only contains one String at that point, your app will crash if you have less than three objects in your array. Make sure to keep the number of rows in sync with your datasource, most easily by returning the count of your dataSource directly.

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return objectTwo.count
}

Thirdly, whenever your dataSource changes, you have to update our tableview manually. As you are loading data from Parse asynchronously, call self.tableView.reloadData() as soon as you have received your objects and appended them to objectTwo.

As I do not know how your custom cell looks like, I'll just assume that you are setting everything correctly in cellForRowAtIndexPath.

Table views / Collection views are a huge and important concept in iOS. I really do recommend to familiarize yourself with it, watch as many tutorials as you can, as they can be quite tricky, too :)

One last thing. Please make sure to follow Swift naming conventions:

// classes, structs, enums, protocols ALWAYS begin uppercase, no prefixes with swift:
class faFirstTableViewController ... // No
class FirstTableViewController ... // Yes

// variables, constants, class properties ALWAYS begin lowercase 
... Cell.CellTitle.text ... // No
... cell.cellTitle.text ... // Yes

Hope that helps!