I'm having a problem with my Swift/iOS app when it comes to dealing with a UITableView using static cells.
My tableview has a couple of sections in it, which in turn each section has a couple of rows in it. In my code, if you tap on one of the cells, it will dynamically insert another cell into the table. For example, tapping on a row for date, will insert a data picker in a new cell, thus pushing the other row down the screen further.
On devices with larger screens this works just fine. The table row gets inserted and everything works fine because even with the data picker inserted, all the rows still fit on the screen. However, on a device with a smaller screen, if the inserted row pushes any of the rows below if off screen, and I try to scroll down to those rows, I get an NSRangeException, beyond bounds. I can't seem to figure out how to handle telling the tableview that those rows do exist and allow me to scroll without crashing.
I can supply more information if this isn't enough.
Thanks!
[Updated with code]
// MARK: - Show/Hide Parent Airline Picker (Section 1, Row 0/1)
func showAirlineOperatedByAirlinePicker() {
airlineOperatedByAirlinePickerVisible = true
let indexPathAirlineOperatedByAirlineRow = NSIndexPath(forRow: 0, inSection: 1)
let indexPathAirlineOperatedByAirlinePicker = NSIndexPath(forRow: 1, inSection: 1)
airlineOperatedByAirlineLabel.textColor = UIColor.blueColor()
tableView.beginUpdates()
tableView.insertRowsAtIndexPaths([indexPathAirlineOperatedByAirlinePicker], withRowAnimation: .Fade)
tableView.reloadRowsAtIndexPaths([indexPathAirlineOperatedByAirlineRow], withRowAnimation: .None)
tableView.endUpdates()
}
func hideAirlineOperatedByAirlinePicker() {
if airlineOperatedByAirlinePickerVisible {
airlineOperatedByAirlinePickerVisible = false
let indexPathAirlineOperatedByAirlineRow = NSIndexPath(forRow: 0, inSection: 1)
let indexPathAirlineOperatedByAirlinePicker = NSIndexPath(forRow: 1, inSection: 1)
if airlineOperatedByAirlineLabel.text == "Operated By" {
airlineOperatedByAirlineLabel.textColor = UIColor.lightGrayColor()
} else {
airlineOperatedByAirlineLabel.textColor = UIColor.blackColor()
}
tableView.beginUpdates()
tableView.reloadRowsAtIndexPaths([indexPathAirlineOperatedByAirlineRow], withRowAnimation: .None)
tableView.deleteRowsAtIndexPaths([indexPathAirlineOperatedByAirlinePicker], withRowAnimation: .Fade)
tableView.endUpdates()
}
}
// MARK: - Table View Data Source Functions
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if indexPath.section == 1 && indexPath.row == 1 && airlineOperatedByAirlinePickerVisible {
return airlineOperatedByAirlinePickerCell
} else {
return super.tableView(tableView, cellForRowAtIndexPath: indexPath)
}
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 1 && airlineOperatedByAirlinePickerVisible {
return 3
} else {
return super.tableView(tableView, numberOfRowsInSection: section)
}
}
// MARK: - Table View Delegate Functions
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
airlineCallSignTextField.resignFirstResponder()
airlineIATATextField.resignFirstResponder()
airlineICAOTextField.resignFirstResponder()
airlineNameTextField.resignFirstResponder()
if indexPath.section == 1 && indexPath.row == 0 {
if !airlineOperatedByAirlinePickerVisible {
showAirlineOperatedByAirlinePicker()
} else {
hideAirlineOperatedByAirlinePicker()
}
}
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if indexPath.section == 1 && indexPath.row == 1 && airlineOperatedByAirlinePickerVisible {
return 217
} else {
return 44
}
}
override func tableView(tableView: UITableView, indentationLevelForRowAtIndexPath indexPath: NSIndexPath) -> Int {
var indexPath = indexPath
if indexPath.section == 1 && indexPath.row == 1 {
indexPath = NSIndexPath(forRow: 0, inSection: indexPath.section)
}
return super.tableView(tableView, indentationLevelForRowAtIndexPath: indexPath)
}
override func tableView(tableView: UITableView, willSelectRowAtIndexPath indexPath: NSIndexPath) -> NSIndexPath? {
if indexPath.section == 1 && indexPath.row == 0 && operatedByAirlineFetchedResultsController.fetchedObjects!.count > 0 {
return indexPath
} else {
return nil
}
}
And finally, here is the error I'm getting.
2016-05-15 09:19:18.305 My Flight Log[10375:222325] * Terminating app due to uncaught exception 'NSRangeException', reason: '* -[NSArrayI objectAtIndex:]: index 2 beyond bounds [0 .. 1]' *** First throw call stack: ( 0 CoreFoundation 0x00aa9494 __exceptionPreprocess + 180 1 libobjc.A.dylib 0x02e81e02 objc_exception_throw + 50 2 CoreFoundation 0x0097adee -[__NSArrayI objectAtIndex:] + 206 3 UIKit 0x0217a99d -[UITableViewDataSource tableView:cellForRowAtIndexPath:] + 184 4 UIKit 0x01dc981d -[UITableViewController tableView:cellForRowAtIndexPath:] + 69 5 My Flight Log 0x000c8a4b _TFC13My_Flight_Log32AirlineModifyTableViewController9tableViewfTCSo11UITableView21cellForRowAtIndexPathCSo11NSIndexPath_CSo15UITableViewCell + 523 6 My Flight Log 0x000c8af9 _TToFC13My_Flight_Log32AirlineModifyTableViewController9tableViewfTCSo11UITableView21cellForRowAtIndexPathCSo11NSIndexPath_CSo15UITableViewCell + 89 7 UIKit 0x01ae7934 -[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:] + 822 8 UIKit 0x01ae7a7d -[UITableView _createPreparedCellForGlobalRow:willDisplay:] + 90 9 UIKit 0x01ab7b32 -[UITableView _updateVisibleCellsNow:isRecursive:] + 3347 10 UIKit 0x01ad6416 __29-[UITableView layoutSubviews]_block_invoke + 52 11 UIKit 0x01af16cc -[UITableView _performWithCachedTraitCollection:] + 88 12 UIKit 0x01ad62eb -[UITableView layoutSubviews] + 214 13 UIKit 0x01a2c3d4 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 810 14 libobjc.A.dylib 0x02e96059 -[NSObject performSelector:withObject:] + 70 15 QuartzCore 0x07815096 -[CALayer layoutSublayers] + 144 16 QuartzCore 0x078088b6 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 388 17 QuartzCore 0x0780871a _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 26 18 QuartzCore 0x077faee7 _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 317 19 QuartzCore 0x0782f847 _ZN2CA11Transaction6commitEv + 561 20 QuartzCore 0x07830108 _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 92 21 CoreFoundation 0x009bb75e __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION + 30 22 CoreFoundation 0x009bb6be __CFRunLoopDoObservers + 398 23 CoreFoundation 0x009b103c __CFRunLoopRun + 1340 24 CoreFoundation 0x009b0846 CFRunLoopRunSpecific + 470 25 CoreFoundation 0x009b065b CFRunLoopRunInMode + 123 26 GraphicsServices 0x04cf3664 GSEventRunModal + 192 27 GraphicsServices 0x04cf34a1 GSEventRun + 104 28 UIKit 0x0195beb9 UIApplicationMain + 160 29 My Flight Log 0x000bebd1 main + 145 30 libdyld.dylib 0x03fb1a25 start + 1 ) libc++abi.dylib: terminating with uncaught exception of type NSException