Search code examples
iosperformanceuitableviewnsarraynsdictionary

Load UITableView sections by NSDate from NSDictionary?


I have an NSArray of NSDictionaries in my app. In each dictionary I hold an NSDate called "RunDate." The problem I am having now is that the code I am trying to do it with is very inefficient. Basically I only want one section per date out of all the dictionaries. Then in each section (sorted by that date), I would load the appropriate dictionary that had that date.

In the code below I made a new NSArray of NSDictionarys which held a date and number of that date (so I could know how many rows are in each section). The problem is, this code looks and feels very inefficient and I was wondering if there were any ways my code is incorrect or could be improved upon. There can be over 500 entries and the code I have now would be very slow. Does anyone have any suggestions on it?

    runArray = [[NSMutableArray alloc] init];
    runArray = [[[NSUserDefaults standardUserDefaults] arrayForKey:@"RunArray"] mutableCopy];

    runDictTableArray = [[NSMutableArray alloc] init];
    for (NSDictionary *dict in runArray) {
        NSDictionary *runInfoDict = [[NSMutableDictionary alloc] init];
        NSDate *theDate = [dict objectForKey:@"RunDate"];

        //Check if we already have this date in the saved run array
        BOOL goToNextDict = FALSE;
        for (NSDictionary *savedDict in runDictTableArray) {
            if ([theDate compare:[savedDict objectForKey:@"RunDate"]] == NSOrderedSame) {
                goToNextDict = TRUE;
                break;
            }
        }
        if (goToNextDict)
            continue;
        ////////////////////////////

        //Now we check how many more we have of this date
        int numbOfDate = 1;
        int index = (int)[runArray indexOfObject:dict];
        for (int i = index; i < [runArray count]; i++) {
            NSDictionary *dictInner = [runArray objectAtIndex:i];
            if ([theDate compare:[dictInner objectForKey:@"RunDate"]] == NSOrderedSame) {
                numbOfDate++;
            }
        }
        ////////////////////////////

        [runInfoDict setValue:[NSNumber numberWithInt:numbOfDate] forKey:@"DateAmount"];
        [runInfoDict setValue:theDate forKey:@"Date"];
        [runDictTableArray addObject:runInfoDict];
    } 

Solution

  • Some suggestions:

    1. You probably only need 1 NSMutableDictionary, rather than a NSMutableArray of NSDictionary. While looping through runArray, check if your dictionary has a value for your date (objectForKey returns a value). If it does, add 1 to the count. If it does not, add that date as a key to the dictionary with a value of 1. This way, you won't have to do the inner loop to get the number of times a date occurs. You won't need the 'go to next dictionary' logic either, I would think.
    2. runArray = [[NSMutableArray alloc] init]; doesn't really do anything since you're immediately re-assigning runArray.
    3. Consider using NSInteger over regular int, NSInteger will give you the appropriate size for whatever architecture your app is running on.
    4. There's some cool syntax shortcuts you might like. You can avoid [runInfoDict setValue:[NSNumber numberWithInt:numbOfDate]... by simply writing [runInfoDict setValue:@(numbOfDate) ..., which will put the value into NSNumber for you.