scooby scooby - 1 month ago 17
Swift Question

Problems with passing the correct Realm object from tableview for index section and row

I'm having issues with segue to next view controller. I have a tableview displaying realm data in rows and sections.
If I press the add button its goes to view controller and allows me to tha data and stores it all correctly.
If I select the cell it should take me to the same view controller and fill the text fields with correct data.

At the moment I can only select the data for the first section indexpath rows. Every cell I select from other sections still only displays the data from the first section.

I have tried numerous ways to get the correct section but failed.

Can someone please show me what I'm doing wrong.

I'm using xcode 7.3 and realm 2.0.3.

Below is the code in my tableview.

class TableViewController: UITableViewController {

let items = try! Realm().objects(ContactItem).sorted(["Initial", "Name"])

var sectionNames: [String] {
return Set(items.valueForKeyPath("Initial") as! [String]).sort()
}

//var sectionTitles = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]

override func viewDidLoad() {
super.viewDidLoad()
setupUI()
tableView.reloadData()
}

override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
tableView.reloadData()
}

func setupUI() {
tableView.registerClass(Cell.self, forCellReuseIdentifier: "cell")
}

func items(forSection section: Int) -> Results<ContactItem> {
return items.filter("Initial == %@", sectionNames[section])
}

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return sectionNames.count
}

override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return sectionNames[section]
}

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

override func sectionIndexTitlesForTableView(tableView: UITableView) -> [String]? {
return sectionNames as [String]
}

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

let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)

cell.textLabel?.text = items.filter("Initial == %@", sectionNames[indexPath.section])[indexPath.row].Name
return cell
}

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

let contact : ContactItem = items[indexPath.row]
performSegueWithIdentifier("editContact", sender: contact)
print("Selected row at \(indexPath.row)")
print("Selected section at \(indexPath.section)")
}

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
if(segue.identifier == "editContact")
{
let viewController = segue.destinationViewController as! AddEntryViewController
viewController.contact = sender as! ContactItem
}

}

@IBAction func addContact(sender: AnyObject) {

}


}

Answer

The issue is here in didSelectRowAtIndexPath

let contact : ContactItem = items[indexPath.row]

It should be getting the item and filtering them. You have a method of doing that already, so didSelectRowAtIndexPath should use that too.

let contact : ContactItem = items(forSection: indexPath.section)[indexPath.row]

You should probably use that in cellForRowAtIndexPath so you don't have the same filtering logic in two different places.

Comments