I have such method and have a hard time optimizing it to run better. It takes roughly 1 sec with 100 units to get between NSLog(@"Debug2")
and NSLog(@"Debug3")
. And 2 sec on iPhone.
Method idea:
Input:
NSMutableArray
times
- containing times (2012-12-12, 2013-01-19) and etcNSMutableArray
objectArray
- containsLogUnit
objects.
Output: Array of computed views.
Main idea: a view for each time with objects from objectArray
whose time is the same.
I have made it faster by showing a small proportion of objects (see counted
in code and _breakPlease
), yet it's still not fast enough.
- (NSMutableArray*) sortViews: (NSMutableArray *)times and:(NSMutableArray *)objectArray
{
NSLog(@"debug2");
NSMutableArray *views = [[NSMutableArray alloc] initWithCapacity:times.count];
NSString *number = [NSString stringWithFormat:@"SortLog%i ",[[NSUserDefaults standardUserDefaults] stringForKey:@"ObjectNumber"].intValue];
NSString *comp = [[NSUserDefaults standardUserDefaults] stringForKey:number];
LogUnit *unit;
int counted = 0;
for(int x = 0; x != times.count; x++)
{
@autoreleasepool {
UIView *foo = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 400)];
foo.backgroundColor = [UIColor clearColor];
int f = 0;
int h = 0;
NSString *attributeName = @"realTime";
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K IN %@", attributeName, [times objectAtIndex:x]];
// Filter the objectArray by the time, so we don't have to run through all the objects in objectArray, and check if time is right.
NSArray *filtered = [objectArray filteredArrayUsingPredicate:predicate];
for(int i = 0; i != filtered.count; i++)
{
unit = [filtered objectAtIndex:i];
// Filter units by user choice (comp). Like comp = Warnings or comp = Errors and etc.
if([[unit status] isEqualToString:comp] || [comp isEqualToString:NULL] || comp == NULL)
{
// testing if the unit is correct to use
if([unit getEvent] != NULL)
{
// below is some computation for frames, to get them to proper position
unit.view.frame = CGRectMake(unit.view.frame.origin.x, f * unit.view.frame.size.height + 30, unit.view.frame.size.width, unit.view.frame.size.height);
[foo addSubview:unit.view];
counted++;
f++;
h = unit.view.frame.size.height * f;
}
}
}
UILabel *myLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 320, 30)];
myLabel.backgroundColor = [UIColor clearColor];
myLabel.font = [UIFont boldSystemFontOfSize:20];
myLabel.textColor = [UIColor colorWithRed:88 green:154 blue:251 alpha:1];
myLabel.textAlignment = UITextAlignmentCenter;
myLabel.text = [times objectAtIndex:x];
// Just adding a label with "2012-12-30" or etc on top of the view.
[foo addSubview:myLabel];
foo.frame = CGRectMake(0,0, 320, h + 30 );
h = 0;
[views addObject:foo];
// counting added views for performance, if more than 30, return, and show only small portion of whole units, user has the option to show all the units if he wants to, but that takes a time to load..
if(counted > 30 && filtered.count != counted)
{
if(_breakPlease == false)
{
_broken = true;
break;
}
}
}
}
NSLog(@"debug3");
return views;
}