1

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

  • How are you inserting these new rows?, It would help people to help you if you showed some code ;) – Wez May 11 '16 at 15:22
  • You added a lot of code. Which line specifically is causing the error? – Daniel May 15 '16 at 14:30
  • That's just it. When the app crashes, it crashed back to the AppDelegate: (class AppDelegate: UIResponder, UIApplicationDelegate) which isn't very helpful. – user5823259 May 17 '16 at 13:45
  • In the error index 2 beyond bounds [0 .. 1]' . The system is attempting to get index 2 when there are only two items avaliable. Are you returning the correct value in your numberOfRowsInSection? – tgunr Dec 09 '16 at 20:03
  • 1
    Hi, asking for a friend but did you ever find a solution to this problem? – Nick Ayres Oct 25 '17 at 15:38
  • I re-engineered the code so that it's not trying to insert new rows. Instead I constructed the table with all the rows already in the table, but hid some of them by setting their row height to 0 on load, and resizing the row when I need to display it. – user5823259 Oct 27 '17 at 13:16

0 Answers0