1

I'm quite new to working with Parse and I'm building a todo list as part of a CRM. Each task in the table view shows the description, due date, and client name. The description and due date are in my Task class, as well as a pointer to the Deal class. Client is a string in the Deal class. I'm able to query the description and due date properly, but I am not able to retrieve the client attribute from within the Deal object by using includeKey. I followed the Parse documentation for includeKey.

The description and due date show up properly in the resulting table view, but not the client. The log shows client label: nil and the printed task details include <Deal: 0x7ff033d1ed40, objectId: HffKOiJrTq>, but nothing about the client attribute. How can I retrieve and assign the pointer object's attribute (client) to my label within the table view? My relevant code is below. Thank you in advance.

Edit: I've updated my code with func fetchClients() based on this SO answer, but I'm still not sure whether my function is complete or where to call it.

class TasksVC: UITableViewController {


var taskObjects:NSMutableArray! = NSMutableArray()

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)

    println("\(PFUser.currentUser())")

    self.fetchAllObjects()
    self.fetchClients()

}

func fetchAllObjects() {

    var query:PFQuery = PFQuery(className: "Task")

    query.whereKey("username", equalTo: PFUser.currentUser()!)

    query.orderByAscending("dueDate")
    query.addAscendingOrder("desc")

    query.includeKey("deal")

    query.findObjectsInBackgroundWithBlock { (tasks: [AnyObject]!, error:NSError!) -> Void in

        if (error == nil) {

            var temp:NSArray = tasks! as NSArray
            self.taskObjects = temp.mutableCopy() as NSMutableArray

            println(tasks)   

            self.tableView.reloadData()

        } else {

            println(error?.userInfo)

        }
    }
}

func fetchClients() {
    var task:PFObject = PFObject(className: "Task")
    var deal:PFObject = task["deal"] as PFObject

    deal.fetchIfNeededInBackgroundWithBlock {
        (deal: PFObject!, error: NSError!) -> Void in
        let client = deal["client"] as NSString
    }
}

//MARK: - Tasks table view
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 1
}

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

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = self.tableView.dequeueReusableCellWithIdentifier("TaskCell", forIndexPath: indexPath) as TaskCell

    var dateFormatter:NSDateFormatter = NSDateFormatter()
    dateFormatter.dateFormat = "M/dd/yy"

    var task:PFObject = self.taskObjects.objectAtIndex(indexPath.row) as PFObject

    cell.desc_Lbl?.text = task["desc"] as? String
    cell.date_Lbl.text = dateFormatter.stringFromDate(task["dueDate"] as NSDate)
    cell.client_Lbl?.text = task["client"] as? String

    var clientLabel = cell.client_Lbl?.text
    println("client label: \(clientLabel)")

    return cell

}

}

1 Answer 1

3

If the deal column is a pointer then includeKey("deal") will get that object and populate it's properties for you. There is no need to perform a fetch of any type on top of that.

You really should be using Optionals properly though:

if let deal = task["deal"] as? PFObject {
  // deal column has data
  if let client = deal["client"] as? String {
    // client has data
    cell.client_Lbl?.text = client
  }
}

Alternatively you can replace the last if let with a line like this, which handles empty values and uses a default:

cell.client_Lbl?.text = (deal["client"] as? String) ?? ""

In your posted cellForRowAtIndexPath code you are trying to read client from the task instead of from the deal: task["client"] as? String.

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

2 Comments

Thanks so much for your help Timothy. I thought that I needed the extra fetch because of what is written in the iOS Relational Data section of the Parse documentation "By default, when fetching an object, related PFObjects are not fetched..." I guess fetchIfNeededInBackgroundWithBlock is similar to the includeKey function? Thanks for setting me straight.
Yes, fetch() would be like doing an includeKey() for everything that is a pointer (big waste if you have multiple pointers and only need to populate one or two!)

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.