Как выполнить два обновления интерфейса одновременно? - PullRequest
6 голосов
/ 01 августа 2011

Из того, что я могу сказать, прочитав документацию Apple, обновления пользовательского интерфейса можно запускать только в главном потоке.

Мое приложение выполняет рендеринг в верхней половине экрана и имеет вид таблицы в нижней части.половина.Если пользователь прокручивает таблицу, в то время как верхняя половина перерисовывает себя, таблица блокируется на полсекунды или около того.Можно ли как-нибудь улучшить эту ситуацию?

Ответы [ 2 ]

1 голос
/ 02 августа 2011

Если рисование вида занимает заметное количество времени, я бы рекомендовал нарисовать его в виде изображения в фоновом потоке при обновлении, и чтобы вид просто нарисовал изображение. Это предотвратит блокировку основного потока на длительное время.

Следующий код показывает, как создавать и рисовать в растровом контексте из фонового потока. Когда вы вызываете метод updateInBackground, он создает новый фоновый поток, который создает и рисует в контексте, а затем создает изображение, используя этот контекст. Если вы поместите это в пользовательский подкласс UIImageView, то изображение будет автоматически выведено на экран.

- (void)updateInBackground {
    [self performSelectorInBackground:@selector(_drawInBackground:) withObject:[NSValue valueWithCGRect:self.bounds]];
}
- (void)_drawInBackground:(NSValue *)boundsValue {
    NSAutoreleasePool *pool = [NSAutoreleasePool new];
    CGRect bounds = [boundsValue CGRectValue];
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    if(!colorSpace) {
        [pool drain];
        return;
    }
    CGContextRef context = CGBitmapContextCreate(NULL,bounds.size.width, bounds.size.height, 8, bounds.size.width * 32, colorSpace, kCGImageAlphaPremultipliedFirst);
    CGColorSpaceRelease(colorSpace);
    if(!context) {
        [pool drain];
        return;
    }
    CGContextConcatCTM(context, CGAffineTransformMake(1,0,0,-1,0,bounds.size.height));

    // do drawing here

    CGImageRef image = CGBitmapContextCreateImage(context);
    [self performSelectorOnMainThread:@selector(setImage:) withObject:[UIImage imageWithCGImage:image] waitUntilDone:YES];
    CGImageRelease(image);
    CGContextRelease(context);
    [pool drain];
}

При рисовании в фоновом потоке вы НЕ можете использовать объекты и методы UIKit. Все рисование должно быть выполнено с использованием Кварцевые функции . Если вам нужно использовать UIKit, фоновый поток может вызвать метод в основном потоке для выполнения этого раздела чертежа:

[self performSelectorOnMainThread:@selector(drawInMainThread:) withObject:[NSValue valueWithPointer:context] waitUntilDone:YES];

- (void)drawInMainThread:(NSValue *)value {
    UIGraphicsPushContext((CGContextRef)[value pointerValue]);
    // do drawing using UIKit
    UIGraphicsPopContext();
}
0 голосов
/ 02 августа 2011

Похоже, что рисунок верхней половины занимает некоторое время.Вы пробовали это через инструменты?

Важно помнить, что если вы хотите плавную прокрутку 60FPS, ваш рендеринг (и любой другой процессор в главном потоке) должен занять менее 16 мс на цикл, иначе вы начнете отбрасывать кадры.

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