1

I basically have a ViewController which shows a few different categories (solved that with a PFQueryTableViewController). Depending on which Cell I tap a segue to the next ViewController is performed, where all objects, which belong to the tapped Category, should appear.

What I did:

I have 2 classes in parse. The class which shows the objects in a Category (the Questions) has a pointer-column to the Category class (filled that pointer-column with the objectIDs from the Category class objects, is that correct?)

In my firstVC: Here I fill my TableView with the categories (works)

class ChooseCategoriesVC: PFQueryTableViewController {

var textOfSelectedCell:String = ""

// Initialise the PFQueryTable tableview
override init!(style: UITableViewStyle, className: String!) {
    super.init(style: style, className: className)
}

required init(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)

    // Configure the PFQueryTableView
    self.parseClassName = "Category"
    self.textKey = "categoryName"
    self.pullToRefreshEnabled = true
    self.paginationEnabled = false
}

    // Define the query that will provide the data for the table view
    override func queryForTable() -> PFQuery! {
    var query = PFQuery(className: "Category")
    query.orderByAscending("categoryName")
    query.whereKey("active", equalTo: true)
    return query
}

    //override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject) -> PFTableViewCell {

    var Cell = tableView.dequeueReusableCellWithIdentifier("Cell") as CustomChooseCategoriesCell!
    if Cell == nil {
        Cell = CustomChooseCategoriesCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
    }

    // Extract values from the PFObject to display in the table cell
    Cell.chooseCategoryLabel.text = object["categoryName"] as String!

    var thumbnail = object["categoryIcon"] as PFFile
    var initialThumbnail = UIImage(named: "categoryIcon")
    Cell.customChooseCategoryIcon.image = initialThumbnail
    Cell.customChooseCategoryIcon.file = thumbnail
    Cell.customChooseCategoryIcon.loadInBackground()

    return Cell
}

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

    //get text of selected Cell
    let indexPath = tableView.indexPathForSelectedRow()!
    let selectedCell = tableView.cellForRowAtIndexPath(indexPath) as CustomChooseCategoriesCell!
    textOfSelectedCell = selectedCell.chooseCategoryLabel.text!
    self.performSegueWithIdentifier("vcToChooseQuestion", sender: self)
}

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    //Pass ObjectId of selected Category from ChooseCategoryVC to ChooseQuestionVC
    var detailVC : ChooseQuestionVC = segue.destinationViewController as ChooseQuestionVC
    detailVC.selectedCategoryText = textOfSelectedCell
    }
}

In my secondVC: I need all detailObjects (Questions) to my category

class ChooseQuestionVC: PFQueryTableViewController{

var selectedCategoryText : String!
let appDelegate = UIApplication.sharedApplication().delegate as AppDelegate

// Initialise the PFQueryTable tableview
override init!(style: UITableViewStyle, className: String!) {
    super.init(style: style, className: className)
}

required init(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)

    // Configure the PFQueryTableView
    self.parseClassName = "Question"
    self.textKey = "question"
    self.pullToRefreshEnabled = true
    self.paginationEnabled = false
}

// Define the query that will provide the data for the table view
override func queryForTable() -> PFQuery! {
    var query = PFQuery(className: "Question")
    query.whereKey("column", equalTo: self.appDelegate.getParseData(selectedCategoryText))
    query.orderByAscending("question")
    return query
}

//override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject) -> PFTableViewCell {

    var Cell = tableView.dequeueReusableCellWithIdentifier("Cell") as CustomChooseQuestionCell!
    if Cell == nil {
        Cell = CustomChooseQuestionCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
    }

    // Extract values from the PFObject to display in the table cell
    Cell.chooseQuestionLabel.text = object["question"] as String!

    return Cell
}

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    performSegueWithIdentifier("nextVC", sender: self)
    }
}

My function in AppDelegate:

func getParseData(textOfSelectedCell: String) -> PFObject{

    var query2 = PFQuery(className:"Category")
    query2.whereKey("categoryName", equalTo: textOfSelectedCell)
    query2.findObjectsInBackgroundWithBlock {
        (objects: [AnyObject]!, error: NSError!) -> Void in
        if error == nil {
            // The find succeeded.
            println("Successfully retrieved \(objects.count) scores.")
            // Do something with the found objects
            if let objects = objects as? [PFObject] {
                for object in objects {
                    self.selectedObject = object
                }
            }
        }
        else {
            // Log details of the failure
            println("Error: \(error) \(error.userInfo!)")
        }
    }
    println(selectedObject)
    return selectedObject!

When running the code like this I always get the error

fatal error: unexpectedly found nil while unwrapping an Optional value

How can I solve that?

4
  • You need to show the data model, it sounds backwards as you don't describe how the category relates to the question (I'd expect a relationship or array, not a pointer, though each question could have a pointer to a category, it isn't clear what you have). Also, what line is the exception thrown on... Commented Mar 8, 2015 at 10:57
  • Each category has a yet undefined amount of questions. In the question class in Parse there is a Pointer-column which points to the category the question belongs to. Is that wrong? Commented Mar 8, 2015 at 11:01
  • And that pointer on the Question class is called column? If not, what is column and what is the pointer called? Commented Mar 8, 2015 at 11:04
  • Yes, the pointer on the question class to the category class is called column. Commented Mar 8, 2015 at 11:08

1 Answer 1

1

Ok, it sounds like your data model should be fine, it's just that how you're trying to use it isn't quite right.

To begin with, we want to be using the parse object instances, not text when we're looking to pass data between view controllers and make queries. The objects hold the most information and the pointers are to objects not strings. So, you want to change textOfSelectedCell to selectedCategory and make it a pointer to PFObject. You should be getting the selected object from the table view controller (because it manages the data source for you), not from the cell. Once you have that object, pass it to the second view controller (instead of the string).

Now, your query should be made against this object, not the string. A method called func getParseData(textOfSelectedCell: String) -> PFObject{ has no business being on the app delegate. The view controller should do the query directly, or you should have a data controller class. In either case you shouldn't actually be calling Parse to get the object, because the table view controller already has it.

Your unwrapping problem is related to your getParseData function because it will always return nil. The query runs in the background so it will never be complete when the function returns... Delete the getParseData function.

So, your question query becomes:

query.whereKey("column", equalTo: self.selectedCategory)

And you just need to look at the objectAtIndexPath: function on PFQueryTableViewController to fill the gaps.

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

3 Comments

Thanks! This clarified a lot for me. Unfortunately I don't know how to get the object in didSelectRowAtIndexPath which I need to pass it to my QuestionVC (through prepareForSegue).
call objectAtIndexPath: on self with the selected index path
Thanks a lot! Works absolutely fine and I've been struggling with this for quite some time.

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.