Графический интерфейс iPad обновляется только после касания

#objective-c #ios #multithreading #ipad

#цель-c #iOS #многопоточность #iPad #objective-c

Вопрос:

Я создаю многопоточное приложение для iPad. У меня есть этот класс, который извлекает кадры из видеоклипа, и у меня есть UIScrollView, чтобы показать то, что я извлек. Экстрактор фреймов запущен в другом потоке, и я хочу начать создавать вид прокрутки только после того, как я извлек определенное количество фреймов. Поэтому я создал это свойство BOOL, называемое буферизацией, которое я обновляю через поток. Мой контроллер просмотра соблюдает это свойство, и только после того, как это свойство равно NO, я начинаю создавать ScrollView.

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

Вот что я делаю:

Чтобы создать поток:

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

Код, выполняемый в потоке:

 -(void) startReadingWithTimeRange:(STimeRange *) timeRange;
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // Top-level pool
    //setting the time range for reading the file
    [assetReader setTimeRange:timeRange.timeRange];

    //start reading
    [assetReader startReading];

    //declearing about the buffer
    CMSampleBufferRef buffer;
    int z = 0;
    while ( [assetReader status]==AVAssetReaderStatusReading)
    {
        z  ;
        //reading buffer
        buffer = [assetReaderTrackOutput copyNextSampleBuffer];

        if (buffer == NULL) break;
        //converting the buffer to UIImage
        UIImage *frameImage = imageFromSampleBuffer(buffer);
        CMTime time = CMSampleBufferGetOutputPresentationTimeStamp(buffer);
        NSLog(@"###duration %lld",time.value/time.timescale);


        SFrame *frame = [[SFrame alloc] initWithImage:frameImage andTime:time];
        //add it to the frame array
        [framesArray addObject:frame];

        [frame release];
        //check if buffer is not null and needed release


        //release the buffer
        CFRelease(buffer);


        if ([framesArray count] > 100 amp;amp; self.buffering) {
            [self willChangeValueForKey:@"buffering"];
            self.buffering = NO;
            [self didChangeValueForKey:@"buffering"];

        }


    }
    [pool release];

}
  

Я действительно невежественен, я был бы очень признателен за любую помощь

Комментарии:

1. Ваш селектор не соответствует имени метода…

2. startReading вызывается только startReadingWithTimeRange: с правильным диапазоном

3. Интересной частью, вероятно, является код, в котором вы на самом деле «создаете вид прокрутки». Я предполагаю, что вам нужен setNeedsDisplay вызов где-нибудь.

4. @Or.Ron, вы нашли решение этой проблемы? Сейчас у меня такая же проблема.

Ответ №1:

Во-первых, не вызывайте willChangeValueForKey и didChangeValueForKey, поскольку вы запускаете уведомление KVO только дважды, оно уже запущено self.буферизация = НЕТ;

Во-вторых, изменения свойств / ivar вне основного потока должны выполняться внутри блока @synchronized, например:

 @synchronized (self) {
     self.buffering = NO;
}
  

Вы могли бы альтернативно использовать performSelectorOnMainThread для вызова метода буферизации, например:

 [self performSelectorOnMainThread:@selector(buffering:) withObject:[NSNumber numberWithBool:YES] waitUntilDone:NO];
  

Если это не решает вашу проблему, то у вас может возникнуть другая проблема в вашем коде, например, необходимость вызвать setNeedsDisplay для некоторого представления или вида.

Вы не сказали, что происходит с уведомлением KVO, вы его не получили, поэтому явно пытались его отправить?

Комментарии:

1. Вероятно, ему следует использовать performSelectorOnMainThread:... ; Держу пари, он не переходит в основной поток в своем уведомлении KVO и, следовательно, в конечном итоге (незаконно) выполняет задачи UIKit в фоновом потоке.

2. просто для справки, легко проверить свой ход с помощью [NSThread isMainThread] и посмотреть