viewDidLoad - оптимизация кода - PullRequest
0 голосов
/ 11 января 2011

У меня есть код, но я не понимаю, как его оптимизировать.Хотя я знаю, что код написан плохо (сам).

У меня есть список названий железнодорожных станций.То, что я хочу сделать, это добавить эти названия станций в табличное представление и иметь раздел для первой буквы названия каждой станции.Те секции, в которых нет станций, должны быть пропущены.

Первая секция должна называться "-" и должна показывать ближайшую станцию.

Пример:

--A--
Astation C
Alaska C
Alabama C
--C--
Cstation
Cathedral station
Central station

Так что у меня все это работает, но я чувствую, что делаю много, должен быть более легкий путь.Кроме того, приложение зависает на 1 секунду при загрузке этого представления на моем iPhone 4. Это тоже не хорошо.Вот мой код:

- (void)viewDidLoad{
    self.filteredListContent = [NSMutableArray array];

    UIBarButtonItem *rightBarButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSearch
                                                                                    target:self
                                                                                    action:@selector(searchBar:)];
    self.navigationItem.rightBarButtonItem = rightBarButton;

    [rightBarButton release];

    UISearchBar *mySearchBar = [[UISearchBar alloc] init];
    mySearchBar.delegate = self;
    [mySearchBar setAutocapitalizationType:UITextAutocapitalizationTypeNone];
    [mySearchBar sizeToFit];
    theTable.tableHeaderView = mySearchBar;

    if (UIInterfaceOrientationLandscapeRight == [[UIDevice currentDevice] orientation] ||
        UIInterfaceOrientationLandscapeLeft == [[UIDevice currentDevice] orientation])
    {
        theTable.tableHeaderView.frame = CGRectMake(0.f, 0.f, 480.f, 44.f);
    }
    else
    {
        theTable.tableHeaderView.frame = CGRectMake(0.f, 0.f, 320.f, 44.f);
    }

    searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:mySearchBar contentsController:self];
    [self setSearchDisplayController:searchDisplayController];
    [searchDisplayController setDelegate:self];
    [searchDisplayController setSearchResultsDataSource:self];

    [mySearchBar release];

    /* Set the data */
    NSArray *stationenPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *stationenDocumentsDirectory = [stationenPath objectAtIndex:0];
    NSString *path = [stationenDocumentsDirectory stringByAppendingPathComponent:@"stations.plist"];

    NSDictionary* stationenDictionary = [[[NSDictionary alloc] initWithContentsOfFile:path] autorelease];
    xmlStationenList* stationsXml = [[xmlStationenList alloc] initWithDictionary:stationenDictionary];

    NSSortDescriptor *stationSorter = [[NSSortDescriptor alloc] initWithKey:@"_station" ascending:YES];
    NSMutableArray *xmlResult = [stationsXml getTimeResult];

    NSArray *objects = [[[NSArray alloc] initWithObjects:stationSorter,nil] autorelease];
    [xmlResult sortUsingDescriptors:objects];

    [stationSorter release];

    /* prefName is decided by the page opening chooseStationViewController. Using this class init function */
    NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
    self.prefValue = [prefs valueForKey:prefName];

    self.listContent = [NSMutableArray array];

    for (stationenListSet *theList in xmlResult)
    {
        [self.listContent addObject:[theList get_station]];
    }
    /* END set the data */

    /* Set sections */
    self.sectionArray = [NSMutableArray array];
    [self.sectionArray addObject:@"-"];
    [self.sectionArray addObject:@"A"];
    [self.sectionArray addObject:@"B"];
    [self.sectionArray addObject:@"C"];
    [self.sectionArray addObject:@"D"];
    [self.sectionArray addObject:@"E"];
    [self.sectionArray addObject:@"F"];
    [self.sectionArray addObject:@"G"];
    [self.sectionArray addObject:@"H"];
    [self.sectionArray addObject:@"I"];
    [self.sectionArray addObject:@"J"];
    [self.sectionArray addObject:@"K"];
    [self.sectionArray addObject:@"L"];
    [self.sectionArray addObject:@"M"];
    [self.sectionArray addObject:@"N"];
    [self.sectionArray addObject:@"O"];
    [self.sectionArray addObject:@"P"];
    [self.sectionArray addObject:@"Q"];
    [self.sectionArray addObject:@"R"];
    [self.sectionArray addObject:@"S"];
    [self.sectionArray addObject:@"T"];
    [self.sectionArray addObject:@"U"];
    [self.sectionArray addObject:@"V"];
    [self.sectionArray addObject:@"W"];
    [self.sectionArray addObject:@"X"];
    [self.sectionArray addObject:@"Y"];
    [self.sectionArray addObject:@"Z"];
    [self.sectionArray addObject:@"Å"];
    [self.sectionArray addObject:@"Ä"];
    [self.sectionArray addObject:@"Ö"];

    [sectionSubArray release];
    sectionSubArray = [[NSMutableArray alloc] init];
    NSMutableArray *sectionTempArray = [[NSMutableArray alloc] init];

    [sectionTempArray addObject:@"-"];
    [sectionSubArray addObject:[[NSArray alloc] init]];

    for(NSString *sectionChar in self.sectionArray)
    {
        sectionChar = [sectionChar uppercaseString];
        int i = 0;

        NSMutableArray *sectionRowArray = [[NSMutableArray alloc] init];
        for (NSString* theStation in listContent)
        {
            NSString *firstChar = [[NSString alloc] initWithFormat:@"%C", toupper([theStation characterAtIndex:0])];

            if([firstChar isEqualToString:sectionChar])
            {
                [sectionRowArray addObject:theStation];

                i++;
            }

           [firstChar release];
        }

        if(i > 0)
        {
            [sectionSubArray addObject:sectionRowArray];
            [sectionTempArray addObject:sectionChar];
        }

       [sectionRowArray release];
    }

    self.sectionArray = sectionTempArray;
    [sectionTempArray release];

    [theTable reloadData];
    theTable.scrollEnabled = YES;
    [stationsXml release];

    locationManager = [[CLLocationManager alloc] init];
    locationManager.delegate=self;
    locationManager.desiredAccuracy=kCLLocationAccuracyBest;

    [locationManager startUpdatingLocation];
}

Глупая вещь, которую я делаю, состоит в том, что я зацикливаю свой массив из более чем 300 объектов для каждой буквы, которую я имею.Но я не могу найти лучший способ сделать это.

С уважением,Пол Пилен

-------- РЕЗУЛЬТАТ -------- Вот что стало результатом, благодаря всем вашим ответам:

- (void)viewDidLoad{
    self.filteredListContent = [NSMutableArray array];

    UIBarButtonItem *rightBarButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSearch
                                                                                    target:self
                                                                                    action:@selector(searchBar:)];
    self.navigationItem.rightBarButtonItem = rightBarButton;

    [rightBarButton release];

    UISearchBar *mySearchBar = [[UISearchBar alloc] init];
    mySearchBar.delegate = self;
    [mySearchBar setAutocapitalizationType:UITextAutocapitalizationTypeNone];
    [mySearchBar sizeToFit];
    theTable.tableHeaderView = mySearchBar;

    if (UIInterfaceOrientationLandscapeRight == [[UIDevice currentDevice] orientation] ||
        UIInterfaceOrientationLandscapeLeft == [[UIDevice currentDevice] orientation])
    {
        theTable.tableHeaderView.frame = CGRectMake(0.f, 0.f, 480.f, 44.f);
    }
    else
    {
        theTable.tableHeaderView.frame = CGRectMake(0.f, 0.f, 320.f, 44.f);
    }

    searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:mySearchBar contentsController:self];
    [self setSearchDisplayController:searchDisplayController];
    [searchDisplayController setDelegate:self];
    [searchDisplayController setSearchResultsDataSource:self];

    [mySearchBar release];

    /* Set the data */
    NSArray *stationenPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *stationenDocumentsDirectory = [stationenPath objectAtIndex:0];
    NSString *path = [stationenDocumentsDirectory stringByAppendingPathComponent:@"stations.plist"];

    NSDictionary* stationenDictionary = [[[NSDictionary alloc] initWithContentsOfFile:path] autorelease];
    xmlStationenList* stationsXml = [[xmlStationenList alloc] initWithDictionary:stationenDictionary];

    NSSortDescriptor *stationSorter = [[NSSortDescriptor alloc] initWithKey:@"_station" ascending:YES];
    NSMutableArray *xmlResult = [stationsXml getTimeResult];

    NSArray *objects = [[[NSArray alloc] initWithObjects:stationSorter,nil] autorelease];
    [xmlResult sortUsingDescriptors:objects];

    [stationSorter release];

    /* prefName is decided by the page opening chooseStationViewController. Using this class init function */
    NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
    self.prefValue = [prefs valueForKey:prefName];

    self.listContent = [NSMutableArray array];

    for (stationenListSet *theList in xmlResult)
    {
        [self.listContent addObject:[theList get_station]];
    }
    /* END set the data */

    /* Set sections */
    self.sectionArray = [[NSArray alloc] initWithObjects:@"-", @"A", @"B", @"C", @"D", @"E", @"F", @"G", @"H", @"I", @"J", @"K", @"L", @"M", @"N", @"O", @"P", @"Q", @"R", @"S", @"T", @"U", @"V", @"W", @"X", @"Y", @"Z", @"Å", @"Ä", @"Ö", nil];

    NSMutableDictionary *sectionDictionary = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                                              [[NSMutableArray alloc] init], @"-", 
                                              [[NSMutableArray alloc] init], @"A", 
                                              [[NSMutableArray alloc] init], @"B",
                                              [[NSMutableArray alloc] init], @"C",
                                              [[NSMutableArray alloc] init], @"D",
                                              [[NSMutableArray alloc] init], @"E",
                                              [[NSMutableArray alloc] init], @"F", 
                                              [[NSMutableArray alloc] init], @"G", 
                                              [[NSMutableArray alloc] init], @"H", 
                                              [[NSMutableArray alloc] init], @"I", 
                                              [[NSMutableArray alloc] init], @"J", 
                                              [[NSMutableArray alloc] init], @"K", 
                                              [[NSMutableArray alloc] init], @"L", 
                                              [[NSMutableArray alloc] init], @"M", 
                                              [[NSMutableArray alloc] init], @"N", 
                                              [[NSMutableArray alloc] init], @"O", 
                                              [[NSMutableArray alloc] init], @"P", 
                                              [[NSMutableArray alloc] init], @"Q", 
                                              [[NSMutableArray alloc] init], @"R", 
                                              [[NSMutableArray alloc] init], @"S", 
                                              [[NSMutableArray alloc] init], @"T", 
                                              [[NSMutableArray alloc] init], @"U", 
                                              [[NSMutableArray alloc] init], @"V", 
                                              [[NSMutableArray alloc] init], @"W", 
                                              [[NSMutableArray alloc] init], @"X", 
                                              [[NSMutableArray alloc] init], @"Y", 
                                              [[NSMutableArray alloc] init], @"Z", 
                                              [[NSMutableArray alloc] init], @"Å", 
                                              [[NSMutableArray alloc] init], @"Ä", 
                                              [[NSMutableArray alloc] init], @"Ö", nil];

    [sectionSubArray release];
    sectionSubArray = [[NSMutableArray alloc] init];

    for(NSString *theStation in listContent) {
        NSString *firstChar = [[[NSString alloc] initWithFormat:@"%C", toupper([theStation characterAtIndex:0])] uppercaseString];

        [[sectionDictionary objectForKey:firstChar] addObject:theStation];
    }

    NSArray *keys = [sectionDictionary allKeys];
    keys = [keys sortedArrayUsingSelector:@selector(localizedCompare:)];

    int indexPath = 0;

    NSMutableArray *sectionTempArray = [[NSMutableArray alloc] init];

    [sectionTempArray addObject:@"-"];
    [sectionSubArray addObject:[[NSArray alloc] init]];

    for(NSString *key in keys)
    {
        if ([[sectionDictionary objectForKey:key] count] > 0)
        {
            NSArray *subArray = [[sectionDictionary objectForKey:key] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];

            [sectionTempArray addObject:key];
            [sectionSubArray addObject:subArray];
        }

        indexPath++;
    }

    self.sectionArray = sectionTempArray;
    [sectionTempArray release];

    [theTable reloadData];
    theTable.scrollEnabled = YES;
    [stationsXml release];

    locationManager = [[CLLocationManager alloc] init];
    locationManager.delegate=self;
    locationManager.desiredAccuracy=kCLLocationAccuracyBest;

    [locationManager startUpdatingLocation];
}

Ответы [ 4 ]

2 голосов
/ 11 января 2011

Вот код с изменениями fiew. Это изменения, которые я сделал:

1) Используйте локальную переменную вместо загрузки sectionArray 26 раз
2) Зацикливайтесь на станциях один раз вместо 29

Вы оставили где-нибудь код? sectionSubArray не определен в этой функции, но представляется локальной переменной. Он также никогда не присваивается свойству.

- (void)viewDidLoad{
    self.filteredListContent = [NSMutableArray array];

    UIBarButtonItem *rightBarButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSearch
                                                                                target:self
                                                                                action:@selector(searchBar:)];
    self.navigationItem.rightBarButtonItem = rightBarButton;

    [rightBarButton release];

    UISearchBar *mySearchBar = [[UISearchBar alloc] init];
    mySearchBar.delegate = self;
    [mySearchBar setAutocapitalizationType:UITextAutocapitalizationTypeNone];
    [mySearchBar sizeToFit];
    theTable.tableHeaderView = mySearchBar;

    if (UIInterfaceOrientationLandscapeRight == [[UIDevice currentDevice] orientation] ||
    UIInterfaceOrientationLandscapeLeft == [[UIDevice currentDevice] orientation])
    {
        theTable.tableHeaderView.frame = CGRectMake(0.f, 0.f, 480.f, 44.f);
    }
    else
    {
        theTable.tableHeaderView.frame = CGRectMake(0.f, 0.f, 320.f, 44.f);
    }

    searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:mySearchBar contentsController:self];
    [self setSearchDisplayController:searchDisplayController];
    [searchDisplayController setDelegate:self];
    [searchDisplayController setSearchResultsDataSource:self];

    [mySearchBar release];

    /* Set the data */
    NSArray *stationenPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *stationenDocumentsDirectory = [stationenPath objectAtIndex:0];
    NSString *path = [stationenDocumentsDirectory stringByAppendingPathComponent:@"stations.plist"];

    NSDictionary* stationenDictionary = [[[NSDictionary alloc] initWithContentsOfFile:path] autorelease];
    xmlStationenList* stationsXml = [[xmlStationenList alloc] initWithDictionary:stationenDictionary];

    NSSortDescriptor *stationSorter = [[NSSortDescriptor alloc] initWithKey:@"_station" ascending:YES];
    NSMutableArray *xmlResult = [stationsXml getTimeResult];

    NSArray *objects = [[[NSArray alloc] initWithObjects:stationSorter,nil] autorelease];
    [xmlResult sortUsingDescriptors:objects];

    [stationSorter release];

    /* prefName is decided by the page opening chooseStationViewController. Using this class init function */
    NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
    self.prefValue = [prefs valueForKey:prefName];

    self.listContent = [NSMutableArray array];

    for (stationenListSet *theList in xmlResult)
    {
        [self.listContent addObject:[theList get_station]];
    }
    /* END set the data */

    /* Set sections */
    NSMutableArray *sectionTempArray = [NSMutableArray array];
    self.sectionArray = sectionTempArray;
    [sectionTempArray addObject:@"-"];
    [sectionTempArray addObject:@"A"];
    [sectionTempArray addObject:@"B"];
    [sectionTempArray addObject:@"C"];
    [sectionTempArray addObject:@"D"];
    [sectionTempArray addObject:@"E"];
    [sectionTempArray addObject:@"F"];
    [sectionTempArray addObject:@"G"];
    [sectionTempArray addObject:@"H"];
    [sectionTempArray addObject:@"I"];
    [sectionTempArray addObject:@"J"];
    [sectionTempArray addObject:@"K"];
    [sectionTempArray addObject:@"L"];
    [sectionTempArray addObject:@"M"];
    [sectionTempArray addObject:@"N"];
    [sectionTempArray addObject:@"O"];
    [sectionTempArray addObject:@"P"];
    [sectionTempArray addObject:@"Q"];
    [sectionTempArray addObject:@"R"];
    [sectionTempArray addObject:@"S"];
    [sectionTempArray addObject:@"T"];
    [sectionTempArray addObject:@"U"];
    [sectionTempArray addObject:@"V"];
    [sectionTempArray addObject:@"W"];
    [sectionTempArray addObject:@"X"];
    [sectionTempArray addObject:@"Y"];
    [sectionTempArray addObject:@"Z"];
    [sectionTempArray addObject:@"Å"];
    [sectionTempArray addObject:@"Ä"];
    [sectionTempArray addObject:@"Ö"];

    [sectionSubArray release];
    sectionSubArray = [[NSMutableArray alloc] init];
    sectionTempArray = [[NSMutableArray alloc] init];

    [sectionTempArray addObject:@"-"];
    [sectionSubArray addObject:[[NSArray alloc] init]];

    NSMutableArray *sectionRowArrays[29];
    memset(sectionRowArrays,0,sizeof(NSMutableArray*)*29);
    for(NSString *theStation in listContent) {
        char currChar = toupper([theStation characterAtIndex:0]);
        uint8_t index;
        if(currChar == 'Å') index = 26;
          else if(currChar == 'Ä') index = 27;
          else if(currChar == 'Ö') index = 28;
          else index = currChar - 'A';
        if(!sectionRowArrays[index]) sectionRowArrays[index] = [[NSMutableArray alloc] init];
        [sectionRowArrays[index] addObject:theStation];
    }
    for(uint8_t index = 0; index < 29; ++index) {
        if(sectionRowArrays[index]) {
            [sectionSubArray addObject:sectionRowArrays[index]];
            NSString *currChar;
            if(index == 26) currChar = @"Å";
              else if(index == 27) currChar = @"Ä";
              else if(index == 28) currChar = @"Ö";
              else currChar = [NSString stringWithFormat:@"%c",index+'A'];
            [sectionTempArray addObject:currChar];
            [sectionRowArrays[index] release];
        }
    }

    self.sectionArray = sectionTempArray;
    [sectionTempArray release];

    [theTable reloadData];
    theTable.scrollEnabled = YES;
    [stationsXml release];

    locationManager = [[CLLocationManager alloc] init];
    locationManager.delegate=self;
    locationManager.desiredAccuracy=kCLLocationAccuracyBest;

    [locationManager startUpdatingLocation];
}
1 голос
/ 11 января 2011

Просто добавление к другим ответам, так как это гораздо меньше, и это не так важно, но то, что вы, по крайней мере, должны знать.

Это:

NSMutableArray *sectionTempArray = [NSMutableArray array];
self.sectionArray = sectionTempArray;
[sectionTempArray addObject:@"-"];
[sectionTempArray addObject:@"A"];
[sectionTempArray addObject:@"B"];
[sectionTempArray addObject:@"C"];
[sectionTempArray addObject:@"D"];
[sectionTempArray addObject:@"E"];
[sectionTempArray addObject:@"F"];
[sectionTempArray addObject:@"G"];
[sectionTempArray addObject:@"H"];
[sectionTempArray addObject:@"I"];
[sectionTempArray addObject:@"J"];
[sectionTempArray addObject:@"K"];
[sectionTempArray addObject:@"L"];
[sectionTempArray addObject:@"M"];
[sectionTempArray addObject:@"N"];
[sectionTempArray addObject:@"O"];
[sectionTempArray addObject:@"P"];
[sectionTempArray addObject:@"Q"];
[sectionTempArray addObject:@"R"];
[sectionTempArray addObject:@"S"];
[sectionTempArray addObject:@"T"];
[sectionTempArray addObject:@"U"];
[sectionTempArray addObject:@"V"];
[sectionTempArray addObject:@"W"];
[sectionTempArray addObject:@"X"];
[sectionTempArray addObject:@"Y"];
[sectionTempArray addObject:@"Z"];
[sectionTempArray addObject:@"Å"];
[sectionTempArray addObject:@"Ä"];
[sectionTempArray addObject:@"Ö"];

Может быть заменено следующим:

NSArray sectionTempArray = [[NSArray alloc] initWithObjects: @"-", @"A", @"B", 
    @"C", @"D", @"E", @"F", @"G", @"H", @"I", @"J", @"K", @"L", @"M", @"N", 
    @"O", @"P", @"Q", @"R", @"S", @"T", @"U", @"V", @"W", @"X", @"Y", @"Z", 
    @"Å", @"Ä", @"Ö", nil];

Устраняет необходимость в изменяемом массиве (сокращая накладные расходы) и, если компилятор не оптимизирует эти 30 вызовов addObject, немного ускоряет процесс. Если вам не нужно изменять содержимое NSArray (или NSString, NSDictionary и т. Д.) После его инициализации, не используйте версию Mutable, если можете помочь.

1 голос
/ 11 января 2011

вам нужно профилировать выполнение вашего приложения, если вы хотите тратить время на улучшение кода, который требует времени.

совет 1: используйте unichar здесь, это сэкономит сотни или тысячи ассигнований:

NSString *firstChar = [[NSString alloc] initWithFormat:@"%C", toupper([theStation characterAtIndex:0])];

совет 2: некоторые из ваших коллекций заполнены с использованием постепенного роста. это поможет уменьшить количество приростов / перераспределений, где это возможно. Вторая часть Apple уже догадалась, поэтому их оптимизация, основанная на реальном использовании, иногда будет работать в вашу пользу, но не всегда. если вы перепределили свои коллекции во время заполнения, вы можете сгладить их, создав копию, а затем избавившись от временной.

совет 3: по возможности избегайте автоматически выпущенных объектов. (Серьезно)

Конечно, вы также захотите оптимизировать свои алгоритмы поиска / сортировки / заполнения.

но если серьезно, вы должны зарегистрироваться, если хотите понять, на что тратится ваше время.

удачи!

1 голос
/ 11 января 2011

Как насчет итерации по списку станций и простого добавления каждой в соответствующий «сегмент»?

Если вам не нужны NSObjects и NSArrays, то вы можете рассмотреть возможность использования шаблона map <> стандартной библиотеки шаблонов.Но если вы не знакомы с этим, то это может привести к большей сложности (с точки зрения кривой обучения), чем это того стоит.

Если коротко, как насчет NSMutableDictionary с ключами NSString, которые являются первыми буквами, а объектыNSMutableArrays.

Я этого не делал - но это уменьшило бы ваши итерации 30x300 до 300.

...