Search code examples
didselectrowatindexpathnsindexpath

Select a Row in a tableView after fetching CoreData to pass the result to sender View Controller


I have been struggling with this issue for a long time being a novice in Swift iOs coding. Hope that someone can point me to the right direction.

In the following code I do a Fetchrequest to a CoreData Entity with names of persons. Once I get the results I am trying to pick (tapping on the corresponding row) one name and pass it back to the ViewController that invoked this view with a prepare for segue.

But each time I click on the row of the name I want to select, I end up with a: "*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid index path for use with UITableView. Index paths passed to table view must contain exactly two indices specifying the section and row. Please use the category on NSIndexPath in UITableView.h if possible.'"

It seems I am invoking my indexPath in the wrong way.

Here below my code:

    .....
    .....

    let fetchedResults =
    managedObjectContext.executeFetchRequest(fetchRequest,
        error: &error) as [NSManagedObject]?

    if let results = fetchedResults {
        names = results
    } else {
        println("Could not fetch \(error), \(error!.userInfo)")
    }
}

// MARK: - UITableViewDataSource

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

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

    let kidName = names[indexPath.row]
    cell.textLabel!.text = kidName.valueForKey("kidName") as String?
    if kidName != selectedKid {
        cell.accessoryType = .None

    } else {
        cell.accessoryType = .Checkmark
        selectedIndexPath = indexPath
    }

    return cell
}

// MARK: - UITableViewDelegate

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    if indexPath.row != selectedIndexPath.row {
        if let newCell = tableView.cellForRowAtIndexPath(indexPath) {
            newCell.accessoryType = .Checkmark
        }

        if let oldCell = tableView.cellForRowAtIndexPath(selectedIndexPath) {
            oldCell.accessoryType = .None
        }

        selectedIndexPath = indexPath
    }
}

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "SelectedKid" {
        let cell = sender as UITableViewCell
        if let indexPath = tableView.indexPathForCell(cell) {
            let kidName = names[indexPath.row]
            selectedKid = kidName.valueForKey("kid") as String!
        }
    }

} }

The idea is that when I tap on the name I go back with an unwind segue to the sender controller and I put the selectedName in the correct place.

Thank you fro any help! Cristiano


Solution

  • your problem are with the lines below...

    let cell = tableView.dequeueReusableCellWithIdentifier("KidCell") as   UITableViewCell
    
    let kidName = names[indexPath.row]
    cell.textLabel!.text = kidName.valueForKey("kidName") as String?
    

    your code should look like...

    let cell = tableView.dequeueReusableCellWithIdentifier("KidCell", forIndexPath: indexPath ) as UITableViewCell
    
    let kidName = names[indexPath.row]
    cell.textLabel!.text = kidName.valueForKey(kidName)