2010-08-31 2 views
3

Я пытаюсь создать UILabel, который будет информировать пользователя о том, что происходит, пока он ждет. Однако UILabel всегда задерживает обновление текста до тех пор, пока система не перейдет в режим ожидания.Как обновить UILabel сразу?

Процесс:

[infoLine performSelectorOnMainThread:@selector(setText:) withObject:@"Calculating..." waitUntilDone:YES]; 
[distanceManager calc]; // Parses a XML and does some calculations 
[infoLine performSelectorOnMainThread:@selector(setText:) withObject:@"Idle" waitUntilDone:YES]; 

не должны waitUntilDone, чтобы это произошло "сразу"?

+0

вы пытались указать waitUntilDone к NO? – vodkhang

+0

Да, попробовал это тоже ... – ciffa

+0

Вы делаете это на основной теме пользовательского интерфейса или из другого потока? – hotpaw2

ответ

4

Если вы делаете это в основном потоке пользовательского интерфейса, не используйте waitUntilDone. Сделайте setText, setNeedsDisplay в полном представлении, установите NSTimer для запуска того, что вы хотите сделать, начиная с 1 миллисекунды позже, а затем вернитесь из своей функции/метода. Возможно, вам придется разделить ваш расчет на патроны, которые могут быть вызваны по отдельности таймером, может быть, машина состояния с оператором switch (выберите chunk, execute chunk, index chunk index, exit), который вызывается таймером до тех пор, пока это не будет выполнено. Пользовательский интерфейс будет перескакивать между вашими кусками и обновлять вещи. Поэтому убедитесь, что ваши куски довольно короткие (я использую от 15 до 200 миллисекунд).

+0

Это работает! Благодаря! – ciffa

+0

Добро пожаловать. – hotpaw2

+0

Пожалуйста, напишите пример кода, как «установить NSTimer для запуска того, что вы хотите сделать, начиная с 1 миллисекунды позже». Благодаря! Кроме того, я хочу, чтобы он был запущен в следующем цикле запуска. Как вы знаете, 1 миллисекунда - это время для использования? – ma11hew28

0

Да waitUntilDone делает setText: произойдет сразу, но установка текста лейбла не означает экран обновляется немедленно.

Возможно, вам понадобится call -setNeedsDisplay или даже пусть основной цикл цикла будет отмечен один раз перед тем, как экран будет обновлен.

+0

Я пытался использовать [infoLine setNeedsDisplay]; но ничего не происходит. Как я могу дождаться, когда основной цикл будет отмечен один раз перед запуском distanceManager? – ciffa

0

Вот полезная функция, которую я добавил в подкласс UIViewController. Он выполняет селектор в следующем цикле выполнения. Он работает, но вы думаете, что я должен сделать переменную экземпляра, так как, скорее всего, этот метод будет вызываться более одного раза.

- (void)scheduleInNextRunloopSelector:(SEL)selector { 
    NSDate *fireDate = [[NSDate alloc] initWithTimeIntervalSinceNow:0.001]; // 1 ms 
    NSTimer *timer = [[NSTimer alloc] 
         initWithFireDate:fireDate interval:0.0 target:self 
         selector:selector userInfo:nil repeats:NO]; 
    [fireDate release]; 
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode]; 
    [timer release]; 
} 
0

Использование performSelector:(SEL) withObject:(id) afterDelay:(NSTimeInterval):

self.infoLine.text = @"Calculating..."; 
[self performSelector:@selector(likeABoss) withObject:nil afterDelay:0.001]; 
//... 
-(void) likeABoss { 
    // hard work here 
    self.infoLine.text = @"Idle"; 
} 
Смежные вопросы