Reputation: 3829
I've got a static UITableView
with two sections
. When the user taps the cell at index 2 in section 1, a UITableViewCell
needs to be added below the tapped cell. Each subsequent cell tap should result in another cell being added below any already added cells.
This is what I've tried so far, but I'm crashing with an NSRangeException
stating that index 6 is beyond the available bounds so i'm clearly not updating the number of rows properly somehow..
As per Adding unknown number of rows to 'Static Cells' UITableView I've overridden all UITableView
methods that use an indexPath but their situation is slightly different to mine.
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 1 {
// subTaskRow is an array holding all the indexes of the added cells
// so I know where to add the next one. I also know how many I've added
return 6 + subTaskRow.count
} else {
return super.tableView(tableView, numberOfRowsInSection: section)
}
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
// If the Sub Task cell is picked
if (indexPath.section == 1 && indexPath.row == 3) {
// If this is the first subtask we want it to appear under Sub Tasks
// We know the index of the cell below sub task so we can add it in directly
if (subTaskRow.count == 0) {
subTaskRow.addObject(5)
tableView.insertRowsAtIndexPaths([NSIndexPath(forRow: 5, inSection: 1)], withRowAnimation: .Automatic)
tableView.reloadData()
// Other sub tasks should appear below previous sub tasks
} else {
// The last object in sub tasks will always be the
// indexPath of the previous added cell
let row = (subTaskRow.lastObject as! Int) + 1
subTaskRow.addObject(row)
tableView.insertRowsAtIndexPaths([NSIndexPath(forRow: row, inSection: 1)], withRowAnimation: .Automatic)
tableView.reloadData()
}
}
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
// Now we override all the other methods to ensure we don't get a crash
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return false
}
override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return false
}
override func tableView(tableView: UITableView, editingStyleForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCellEditingStyle {
return .None
}
override func tableView(tableView: UITableView, indentationLevelForRowAtIndexPath indexPath: NSIndexPath) -> Int {
return super.tableView(tableView, indentationLevelForRowAtIndexPath: indexPath)
}
My guess would be that adding in a cell in the middle of a section doesn't update the indexPaths of the already existing cells or something? I'm not sure how I'd do that though.
Upvotes: 0
Views: 632
Reputation: 1301
I got this to work, but this code is only using one section:
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Potentially incomplete method implementation.
// Return the number of sections.
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// subTaskRow is an array holding all the indexes of the added cells
// so I know where to add the next one. I also know how many I've added
return 6 + subTaskRow.count
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
// If the Sub Task cell is picked
if (indexPath.section == 0 && indexPath.row == 3) {
// If this is the first subtask we want it to appear under Sub Tasks
// We know the index of the cell below sub task so we can add it in directly
if (subTaskRow.count == 0) {
subTaskRow.append(5)
tableView.insertRowsAtIndexPaths([NSIndexPath(forRow: 5, inSection: 0)], withRowAnimation: .Automatic)
tableView.reloadData()
// Other sub tasks should appear below previous sub tasks
} else {
// The last object in sub tasks will always be the
// indexPath of the previous added cell
let row = subTaskRow.last! + 1
subTaskRow.append(row)
tableView.insertRowsAtIndexPaths([NSIndexPath(forRow: row, inSection: 0)], withRowAnimation: .Automatic)
tableView.reloadData()
}
}
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! UITableViewCell
cell.textLabel!.text = "the row: \(indexPath.row)"
return cell
}
try out this code and see if it works for you. From here, you just need to add the code to handle sections, which means adding code to numberOfSectionsInTableView. You shouldn't be calling super.numberOfRowsInTableview here because if you have 2 sections of data, you should know how many rows are in each
Upvotes: 1