The real problem is how the dynamic and static tableViewControllers work.
If you create a dynamic UITableViewController, most methods return nil or 0 or another default value. Therefore, nothing bad happens if you do not overwrite them in a subclass of UITableViewController.
If you create a static UITableViewController, most methods "ask" the storyboard what needs to be returned. In fact, it is likely something like a private array as a backup storage that contains all the necessary data. And if you do not overwrite the methods that request this backup storage, the default implementation will request an array for objects in indexes that do not exist.
Your problem is that you tell tableView that it has 2 sections and several rows. Thus, tableView queries the static UITableViewController about things like cell height in the second row in the second section. But this indexPath does not exist in the backup storage (because you only put one row in the second section), which is used by the static table view.
So, you need to implement a couple of dataSource methods and delegate and return your own values ββif tableView wants to access information that does not exist in the storage of static tables.
If you look at the stack of exception calls, you can see these methods.
For instance:
*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndex:]: index 1 beyond bounds [0 .. 0]' *** First throw call stack: ( 0 CoreFoundation 0x000000010ebaaf35 __exceptionPreprocess + 165 1 libobjc.A.dylib 0x000000010e843bb7 objc_exception_throw + 45 2 CoreFoundation 0x000000010eaa301e -[__NSArrayI objectAtIndex:] + 190 3 UIKit 0x000000010f4dc856 -[UITableViewDataSource tableView:heightForRowAtIndexPath:] + 109 4 UIKit 0x000000010f21026b __66-[UISectionRowData refreshWithSection:tableView:tableViewRowData:]_block_invoke + 302 5 UIKit 0x000000010f20f8fe -[UISectionRowData refreshWithSection:tableView:tableViewRowData:] + 4125 6 UIKit 0x000000010f214e45 -[UITableViewRowData rectForFooterInSection:heightCanBeGuessed:] + 320 7 UIKit 0x000000010f214f3a -[UITableViewRowData heightForTable] + 56
In index 3 of the call stack, you can see that -[UITableViewDataSource tableView:heightForRowAtIndexPath:] called the code objectAtIndex: which caused the exception. This is one of the methods that transfers its calls to the backend store if you do not stop making them. Therefore, you must implement this method and return something useful. And then you continue until there are no more exceptions.
How many methods are required may depend on the configuration of your TableView. I have implemented four that usually throw these exceptions, so you can see the pattern that should be followed if you see more exceptions thrown by UITableViewDataSource / Delegate methods that are not overwritten:
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { CGFloat height = 0; if (section == 0) { // static section height = [super tableView:tableView heightForHeaderInSection:section]; } return height; } - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { CGFloat height = 0; if (section == 0) { // static section height = [super tableView:tableView heightForFooterInSection:section]; } return height; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { CGFloat height = 44; if (indexPath.section == 0) { // static section height = [super tableView:tableView heightForRowAtIndexPath:indexPath]; } return height; } - (NSInteger)tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath { NSInteger indentationLevel = 0; if (indexPath.section == 0) { // static section indentationLevel = [super tableView:tableView indentationLevelForRowAtIndexPath:indexPath]; } return indentationLevel; }
and here is a little trick to make your static content even more independent of your code:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { if (section == 0) { // static section return [super tableView:tableView numberOfRowsInSection:section]; } return self.objects.count; }
If you mix dynamic and static cell call super it becomes very useful.