I am doing some heavy calculations when I am creating cells. I am trying to figure out the best way to keep the UITableView fluid, but at the same type do the calculations on the background (keep the UI thread without too much processing).
For testing purposes only, I am using this as my heavy calculation method:
+(NSString*)bigCalculation
{
int finalValue=0;
int j=0;
int i=0;
for (i=0; i<1000; i++) {
for (j=0; j<10000000; j++) {
j++;
}
finalValue+=j/100*i;
}
return [NSString stringWithFormat:@"%d",finalValue];
}
Inside the cellForRowAtIndexPath, I am only doing the following:
- (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *identifier=@"identifier";
UITableViewCell *cell=nil;
cell=[aTableView dequeueReusableCellWithIdentifier:identifier];
if(!cell)
{
cell=[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier];
}
NSString *text=[dataSource objectForKey:[[dataSource allKeys] objectAtIndex:indexPath.row]];
dispatch_queue_t a_queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);
;
dispatch_async(a_queue, ^{
NSString *subtitle=[CalculationEngine bigCalculation];
dispatch_async(dispatch_get_main_queue(), ^{
[[cell detailTextLabel] setText:subtitle];
dispatch_release(a_queue);
});
});
[[cell textLabel] setText:text];
return cell;
}
At the moment I have the UITableView fluid, while in the background everything is working ok. So my questions are:
1) Is this the best way to achieve what I want, could KVO be the answer as well?
2) Before doing this:
dispatch_queue_t a_queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);
I was doing:
dispatch_queue_create("com.mydomain.app.newimagesinbackground", DISPATCH_QUEUE_SERIAL)
And the performance was very poor. Could you explain me why?
This isn’t a good approach. You’re breaking MVC here by pushing the calculation work into the view controller. You should keep your data in model objects and manage the calculations there. The table view should then just display the current value from the model, using
reloadRowsAtIndexPaths:withRowAnimation:when the data changes. KVO is one reasonable way to determine when the data changes.If you want to be lazy in calculations, then you can make calls to the model like
recalculateIfNeededto let the model know that someone (the table view in this case) would like a fresh value. You shouldn’t recalculate if the input data hasn’t actually changed, however. The model is where to keep track of whether the data has changed.