Индикатор активности iPhone откладывается? - PullRequest
0 голосов
/ 19 августа 2011

Поэтому, когда я щелкаю по вспомогательному элементу выноски в моем mapView, в течение нескольких секунд ничего не происходит, потому что он делает запрос url и анализирует его, поэтому я хотел показать индикатор активности, чтобы пользователь не думал, что он заморожен. Вот код:

- (void)mapView:(MKMapView *)mv annotationView:(MKAnnotationView *)pin calloutAccessoryControlTapped:(UIControl *)control {
    // start activity indicator 
    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
    NSLog(@"tapped");

    ArtPiece *artPiece = (ArtPiece *)pin.annotation;

    //when annotation is tapped switches page to the art description page
    artDescription *artD = [[artDescription alloc] initWithNibName:@"artDescription" bundle:nil];
    artD.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
    artD.startingLocation = mapView.userLocation.location.coordinate;
    artD.selectedArtPiece = artPiece;
    NSLog(@"0");
    [self presentModalViewController:artD animated:YES];
    NSLog(@"1");

    [artD loadArt:artPiece];
    NSLog(@"2");
    // stop activity indicator 
    //[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;

    [artD release];
}

Странно (мне все равно, может быть, я упускаю что-то очевидное, поскольку я довольно неопытен), индикатор активности не отображается до тех пор, пока метод не будет завершен, и модальное представление не начинает анимацию. Я положил NSLogs, чтобы посмотреть, что занимает время. У меня была пауза в 2 секунды между «0» и «1» и еще пара секунд между «1» и «2». Затем индикатор наконец-то показал, так что я уверен, что он по какой-то причине ждет завершения метода. Есть идеи почему?

Ответы [ 3 ]

3 голосов
/ 20 августа 2011

Изменение пользовательского интерфейса, отображающего индикатор активности, не вступает в силу до тех пор, пока управление не вернется в основной цикл выполнения приложения . Это не происходит до тех пор, пока ваш метод не завершится и стек не будет размотан. Вам нужно показать индикатор активности, а затем сбросить ожидаемую активность в фоновый поток:

[self performSelectorInBackground:@selector(doThingINeedToWaitFor:)
                       withObject:anObject];

(Обратите внимание, что Apple рекомендует , чтобы вы явно отказались от использования потоков ; performSelectorInBackground:withObject: - это самый простой способ заставить некоторый код работать с основной нить. Более сложные опции доступны для других ситуаций. См. Руководство по программированию параллелизма .)

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

- (void) doThingINeedToWaitFor: (id)anObject {
    // Creating an autorelease pool should be the first thing
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    // Do your work...
    // ...
    // Update the UI back on the main thread
    [self performSelectorOnMainThread:@selector(allDoneWaiting:)
                           withObject:nil
                        waitUntilDone:YES];
    // Clear out the pool as the final action on the thread
    [pool drain];
}

В вашем методе обратного вызова вы снова скрываете индикатор активности и делаете любую другую необходимую постобработку.

3 голосов
/ 19 августа 2011

Вы не можете запускать и останавливать индикатор активности в одной и той же функции.

См. Ответ, который я дал на этот вопрос: Как показать индикатор активности при нажатии кнопки для загрузки следующего просмотра или веб-просмотра?

Для ясности отредактируйте:

- (void) someFunction
{
    [activityIndicator startAnimation];

    // do computations ....

    [activityIndicator stopAnimation];  
}

Приведенный выше код не будет работать, поскольку вы не предоставляете время для обновления пользовательского интерфейса, когда вы включаете ActivityIndicator в текущую выполняемую функцию.Так что я и многие другие делим это на отдельные темы, например:

- (void) yourMainFunction {
    activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];

    [NSThread detachNewThreadSelector:@selector(threadStartAnimating) toTarget:self withObject:nil];

    //Your computations

    [activityIndicator stopAnimating];

}

- (void) threadStartAnimating {
    [activityIndicator startAnimating];
}
0 голосов
/ 19 августа 2011

Что-то замедляет ваш счетчик.Я бы порекомендовал делать тяжелую работу в фоновом режиме, используя нить.Попробуйте это:

-(void)myMethod{
    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
    [NSThread detachNewThreadSelector:@selector(startWorkingThread) toTarget:self withObject:nil];
}

-(void)startWorkingThread{
     //Heavy lifting
     [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}

Я предполагаю, что вы прокомментировали:

[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;

Для целей тестирования ...

...