Отображение UIActivityIndicator в течение x секунд - PullRequest
3 голосов
/ 03 марта 2009

У меня есть UITableViewController, который является RootViewController. Это XIB имеет только табличное представление. Я добавил UIActivityIndicator через IB и создал IBOutlet. Я программно добавил панель инструментов с кнопкой удаления в RootViewController. Когда пользователь нажимает кнопку удаления на панели инструментов, я хочу отобразить индикатор по центру экрана. Метод ниже удаляет данные из базы данных, что происходит очень быстро. Я хочу, чтобы пользователь знал, что что-то происходит. Если я запускаю приведенный ниже код без sleep (), это происходит быстро, и я не вижу индикатор. Но некоторые почему-то не видят индикатор в любом случае. Я предполагаю, что sleep () блокирует перекрашивание? Если я уберу sleep () и последние две строки, я увижу индикатор, но, конечно, он никогда не исчезнет. Он также отображается в верхнем левом углу окна.

Как заставить работать приведенный ниже код, чтобы индикатор отображался как минимум на 1/2 - 1 секунду?

Как выровнять индикатор по центру окна?

[self.navigationController.view addSubview:activityIndicator];
[activityIndicator startAnimating];
[activityIndicator setNeedsDisplay];

//do something which might happen really fast

sleep(1); //create illusion
[activityIndicator stopAnimating];
[activityIndicator removeFromSuperview];

Ответы [ 4 ]

6 голосов
/ 03 марта 2009

Вращатель не начнет вращаться, пока вы не обработаете событие и не вернетесь в цикл выполнения. Обходной путь - попросить цикл выполнения завершить работу за вас.

Вот пример того, что я имею в виду:

- (IBAction)deleteAction:(id)sender {
    [self.navigationController.view addSubview:activityIndicator];
    [activityIndicator startAnimating];

    // Spinner won't start spinning until we finish processing this event, so
    // we're just going to schedule the rest of what we need to do.

    // doDelete: will run when the main thread gets its next event.
    [self performSelectorOnMainThread:@selector(doDelete:)
                           withObject:record
                        waitUntilDone:NO];

    // removeSpinner: will run in at least one second, but will wait if
    // another event (like the doDelete: one) is in the middle of running.
    [self performSelector:@selector(removeSpinner:)
               withObject:activityIndicator
               afterDelay:1.0];
}
- (void)doDelete:(id)record {
    [record delete];   // or whatever it is you need to do
}
- (void)removeSpinner:(UIActivityIndicator*)activityIndicator {
    [activityIndicator stopAnimating];
    [activityIndicator removeFromSuperview];
}

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

1 голос
/ 21 февраля 2010

Как упоминал Адам, прядильщик не будет отображаться, если работа (в данном случае операция удаления) не выполняется в фоновом потоке. Это код, который я начал работать на основе исходного кода Брента. Я изменил его так, чтобы он вызывал мою функцию, выполняющую работу в фоновом потоке, а затем использовал основной поток для удаления счетчика, когда закончил.

- (void)removeSpinner:(id)record {
    [activityIndicator stopAnimating];
    [activityIndicator removeFromSuperview];

    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Thank You" message:@"Thanks for your feedback!"
                                                                                                 delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
    [alert show];
    [alert release];

    // return to feedings tab
  tabBarController.selectedIndex = 0;
}


- (void)doFeedback:(id)record {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    int j;
    for (int i = 0; i < 1000000000; i++) {
        j = j + i;
    }
    [self performSelectorOnMainThread:@selector(removeSpinner:) withObject:nil waitUntilDone:NO];

    [pool release];
}


- (IBAction)handleSend {        
    [self.view addSubview:activityIndicator];
    [activityIndicator startAnimating];

    // Spinner won't start spinning until we finish processing this event, so
    // we're just going to schedule the rest of what we need to do. 
    // doFeedback: will run when the main thread gets its next event.   
    [self performSelectorInBackground:@selector(doFeedback:) withObject:nil];
}
0 голосов
/ 07 апреля 2011

[self.navigationController.view addSubview: ActivityIndicator]; [ActivityIndicator startAnimating];

[self executeSelector: @selector (removeSpinner :) withObject: activityIndicator afterDelay: 5.0];

0 голосов
/ 03 марта 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...