I have a UITableView that should have 33 rows. Each row represents a specific time slot in a day. When the view that holds the table view loads, I need it to populate each row accordingly.
I have an array of reservation objects that gets passed to the view. Each reservation contains a slot number, a reservation name and the duration of the reservation in slots.
What is the best way to populate the table, I am currently iterating through the array of reservations in the - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath method.
This is not giving me the results or the behavior I am expecting. The performance is extremly poor as it keeps iterating through loops and cells that shouldn’t be blue are blue after scrolling. What is the best way to approach this? I have included the code below.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 33;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
NSString *timeStamp = [NSString stringWithFormat:@"%.2f", (indexPath.row + 14.0 ) / 2.0];
timeStamp = [timeStamp stringByReplacingOccurrencesOfString:@".50" withString:@":30"];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = [NSString stringWithFormat:@"%@: ", timeStamp];
for (Reservation *temp in bookingsArray) {
if ((temp.slotNumber - 1) == indexPath.row) {
cell.textLabel.text = [NSString stringWithFormat:@"%@: %@", timeStamp, temp.reservationName];
cell.contentView.backgroundColor = [UIColor blueColor];
}
for (NSNumber *tempNo in temp.slotIdentifiers) {
if ([tempNo intValue] -1 == indexPath.row) {
//cell.textLabel.text = [NSString stringWithFormat:@"%@: Booked", timeStamp];
cell.contentView.backgroundColor = [UIColor blueColor];
}
}
}
return cell;
}
UPDATE
Trying the following gives me strange behaviour where all the cells turn blue after I start scrolling.
- (void)viewDidLoad
{
[super viewDidLoad];
bookManager = appDelegate.bookingManager;
bookingsArray = [[NSArray alloc] initWithArray:[bookManager getBookingsForCourt:1 onDate:[NSDate date]]];
namesArray = [[NSMutableDictionary alloc] init];
slotIndexSet = [NSMutableIndexSet indexSet];
for (int c = 0; c < 33; c++) {
[namesArray setObject:@"Available" forKey:[NSNumber numberWithInt:c]];
}
for (Reservation *temp in bookingsArray) {
[namesArray setObject:temp.reservationName forKey:[NSNumber numberWithInt:temp.slotNumber]];
for (NSNumber *slotNo in temp.slotIdentifiers) {
[slotIndexSet addIndex:[slotNo intValue] + 1];
}
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
NSString *timeStamp = [NSString stringWithFormat:@"%.2f", (indexPath.row + 14.0 ) / 2.0];
timeStamp = [timeStamp stringByReplacingOccurrencesOfString:@".50" withString:@":30"];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = [NSString stringWithFormat:@"%@: ", timeStamp];
cell.textLabel.text = [namesArray objectForKey:[NSNumber numberWithInt:indexPath.row]];
if ([slotIndexSet containsIndex:indexPath.row]) {
cell.contentView.backgroundColor = [UIColor blueColor];
}
return cell;
}
You need to do two things to speed this up:
bookingsArrayto abookingBySlotNumberarray in such a way that the object at indexihasslotNumber - 1equal toi. You can do it by iterating over the original bookings array when you receive it.NSIndexSetcalledisBookedBySlotNumbercontaining indexes of items that have been booked. You can prepare it by going through allReservation.slotIdentifiers, and marking the indexes ofisBookedBySlotNumberfor items that have been booked.With these two pre-processed items in place, you can eliminate the nested loops altogether: the outer one will be replaced by a lookup in
bookingBySlotNumber, and the inner one – by a loopup inisBookedBySlotNumber.