I have been searching all over for this error and did find some few posts with a similar behavior but no solution that solves the problem.
I have a UITableViewController (declared as Static in SB) which has to Sections: Section 0 (Recipe) is static with 4 cells, Section 1 (Flavours) should be dynamic
This is the code I'm using to test:
- (void)viewDidLoad {
[super viewDidLoad];
rows = [[NSMutableArray alloc] initWithArray:@[@"test",@"test",@"test",@"test",@"test",@"test",@"test"]];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 2;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
switch (section) {
case 0:
return 4;
break;
case 1:
return rows.count;
break;
default:
break;
}
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell;
switch (indexPath.section) {
case 0:
return [super tableView:tableView cellForRowAtIndexPath:indexPath];
break;
case 1:
cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
if (!cell)
{
// create a cell
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"];
}
cell.textLabel.text = [rows objectAtIndex:indexPath.row];
return cell;
default:
break;
}
return cell;
}
Now the error I'm getting when running is: 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndex:]: index 1 beyond bounds [0 .. 0]'
I know I miss something small somewhere, can someone help me?
thanks so much
So it seems like I found the reason for this error to occur. The question is now whether I solved it correctly or whether there's another way to do programatically...
My Solution is: In the SB, select the section which should be dynamic and provide the number of maximum rows it will contain. Per se, in my case I don't want to let the user add more than 30 flavours to a recipe, so I provided 30 rows for this section.
When running the app, my Array has only 7 objects, although I set the rows to 30 for the section, it renders only the 7 defined in the array and doesn't display the other 23.
The reason for that error to occur seems to be that when you wanna mix static and dynamic sections, you gotta define your table to be static in order to work. In static mode and with SB, it seems like the code reads the number of cells you have in SB for a section. If this number is smaller than your data array, it spits an NSRangeException...
For now this is my solution as I know I won't have more than 30 cells, if someone knows how to remedy this issue in a more dynamic way, please let us know
I replaced the call to super with UITableViewAutomaticDimension for row heights and added the delegate method for estimated row height. In iOS 9 I was having issues with rows not expanding that did expand automatically in iOS8. My static cells were also dynamic heights and dynamic cells are fixed height.
}
}
The actual problem is the way how dynamic and static tableViewControllers work.
If you create a dynamic UITableViewController, most methods return nil or 0 or another default value. So nothing bad happens if you don't overwrite them in your UITableViewController subclass.
If you create a static UITableViewController, most methods "ask" the storyboard what to return. In reality there is probably something like a private array as a backing store that contains all the necessary data. And if you don't overwrite methods that query this backing store the default implementation will ask the array for objects at indexes that don't exist.
Your problem is that you tell the tableView that it has 2 sections and a couple of rows. So the tableView asks the static UITableViewController about things like the height of the cell in second row in second section. But this indexPath does not exist in the backing store (because you only put a single row into the second section) that is used by the static tableView.
So you have to implement a couple of dataSource and delegate methods and return your own values if the tableView wants to access information that does not exist in the static table store.
If you look at the call stack of the exception you should be able to see these methods.
E.g.:
At index 3 of the call stack you can see that
-[UITableViewDataSource tableView:heightForRowAtIndexPath:]
has called theobjectAtIndex:
code that raised the exception. This is one of the methods that relay their calls to the backend store if you don't stop them from doing that. So you have to implement this method and return something usefull. And then you continue until there are no more exceptions.How many methods are required might depend on the configuration of your tableView. I implemented the four that usually cause these exceptions, so you can see the pattern you should follow if you see more exceptions that are caused by not overwritten UITableViewDataSource/Delegate methods:
and here is a little trick to make your static content even more independent from your code:
If you mix dynamic and static cells, calling
super
becomes very useful.It seems that this behavior is not trivial. You may need to override all methods with
NSIndexPath
. You can read this discussion and this one for more information.