Просмотр не обновляется - PullRequest
       18

Просмотр не обновляется

0 голосов
/ 04 октября 2009

Вроде новичок в программировании iPhone и экспериментировал с потоками

- (void)viewDidLoad {
    [super viewDidLoad];

    [NSThread detachNewThreadSelector:@selector(changeMain) toTarget:self withObject:nil];
    [NSThread detachNewThreadSelector:@selector(changeThread) toTarget:self withObject:nil];
}

- (void)changeMain{
    NSAutoreleasePool* arp = [[NSAutoreleasePool alloc] init];

    for (int i = 0; i < 1000000; i++) {
        [mainValue setText:[NSString stringWithFormat:@"%d",i]];
        [self.view setNeedsDisplay];    
    }

    [arp release];
}
- (void)changeThread{
    NSAutoreleasePool* arp = [[NSAutoreleasePool alloc] init];

    for (int i = 0; i < 1000000; i++) {
        [threadValue setText:[NSString stringWithFormat:@"%d",i]];
        [self.view setNeedsDisplay];
    }

    [arp release];
}

mainValue и threadValue - это всего лишь UILabels. Я ожидал, что он запустится и увидит, что обе метки работают до 999999, но вместо этого он начинается с некоторого небольшого числа (которое, как я полагаю, происходит при первоначальном обновлении экрана), немного останавливается, затем обновляется до 999999. Я думаю, экран просто не освежает.

Это правильно? Я делаю это неправильно?

Ответы [ 4 ]

1 голос
/ 04 октября 2009

Не используйте for() для анимации. for будет обрабатываться в том же «кадре». Может быть, просто есть ivar i, а в changeMain вы можете иметь if (i<10000) { mainValue.text = [NSString stringWithFormat:@"%d",i]; i++;} или что-то в этом роде. Таким образом, setText происходит только один раз за «кадр».

1 голос
/ 04 октября 2009
  1. Вы должны выполнять любые операции Cocoa Touch в главном потоке, в противном случае результаты непредсказуемы.
  2. Вам не нужно звонить setNeedsDisplay вручную.

Поэтому я бы рекомендовал использовать следующую конструкцию:

[threadValue performSelectorOnMainThread:@selector(setText:) withObject:[NSString stringWithFormat:@"%d",i] waitUntilDone:YES];

Дополнительные примечания: 1. 100000 запусков могут переполнить очередь основного потока, поэтому некоторые значения исчезнут 2. Вы можете использовать waitUntilDone:NO тоже

1 голос
/ 04 октября 2009

Сообщение setNeedsDisplay вызывает перерисовку, но это происходит только в следующий раз, когда основной поток становится активным. Таким образом, ваши побочные потоки вызывают миллион перерисовок, но они стоят в очереди. Как только основной поток продолжается, он «сворачивает» все запросы в одну перерисовку.

Скорее всего, setNeedsDisplay просто устанавливает флаг, который проверяется один раз при каждом запуске основного цикла, поэтому установка 1000000 в значение true ни на что не влияет. Попробуйте дать "рабочим потокам" спать после каждой итерации, чтобы дать основному потоку некоторое время для перерисовки.

0 голосов
/ 04 октября 2009

Я не уверен, сработает ли это, но вы можете попытаться принудительно выполнить метод setNeedsDisplay в главном потоке, например, используя. [self performSelectorOnMainThread:@selector(setNeedsDisplay) withObject:nil waitUntilDone:YES]. Это должно (надеюсь, я не проверял это!) Обновлять представление после каждого приращения. Вы также можете попытаться установить waitUntiDone:NO, но я не уверен, что произойдет тогда.

Смотрите здесь

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