Асинхронное рисование и касания

У меня есть область рисования (UIView), где я рисую в CGContextRef.
Конечно, я ловлю прикосновения к рисованию. Хотя метод drawRect медленно рисует множество существующих объектов, прикосновения не улавливаются.
Если я вызываю рисование в drawRect в отдельном потоке или с помощью функции "dispatch_async", оно не рисует, потому что не имеет соответствующего контекста.
Я много искал, но ничего не нашел.

dispatch_async(dispatch_get_main_queue(), ^{
    [_mainArea setNeedsDisplay];
});
  • эти вещи тоже не помогают.

Что я могу сделать? Кто-нибудь может помочь поймать прикосновения и рисовать много объектов одновременно?

1 ответ

Решение

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

  1. Вы должны удалить все звонки на display или же setNeedsDisplay и заменить их setNeedsDisplayInRect:

  2. Вы должны оптимизировать свой drawRect: метод, так что вы перерисовываете только те части представления, которые в этом нуждаются. Вы можете получить еще больше фантазии в этом методе и игнорировать rect аргумент от метода и получить необработанные ректы, взятые из getRectsBeingDrawn:count:,

  3. Если вы рисуете движущиеся объекты, используйте CoreAnimation.

  4. Если у вас много повторяющихся объектов, используйте CGLayerRefs

призвание setNeedsDisplay с dispatch_async() не заставит представление рисовать на другой нити; все рисование происходит в drawRect:, а также drawRect: всегда вызывается основным потоком / очередью.

UIGraphicsGetCurrentContext() не является потокобезопасным. Однако вы можете создать растровый контекст в своем асинхронном блоке, обвести его и заполнить, а затем получить этот контекст в виде CGImageRef, который может быть скомпонован в CGContextRef (тот, который обращается к экрану), работающий на Основная тема. Это будет выглядеть примерно так:

@implementation BGDrawingClass : UIVew {
    CGImageRef bgImage;
}

-(void)prepBGImage {

CGRect rect = TheRectISpendALotOfTimeIn();
dispatch_async(_myBGQueue,^{

        CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
        CGContextRef ctx = CGBitmapContextCreate(nil, rect.size.width, rect.size.height, 8, rect.size.width * (CGColorSpaceGetNumberOfComponents(space) + 1), space, kCGImageAlphaPremultipliedLast);
        CGColorSpaceRelease(space);

        /* do expensive drawing in this context */

        bgImage = CGBitmapContextCreateImage(ctx);

        dispatch_async(dispatch_get_main_queue(),^{ 
             [self setNeedsDisplayInRect:rect];
        });
    });
}

-(void)drawRect:(NSRect)rect {
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    /* do drawing behind this ... */
    if (CGRectIntersectsRect(rect, TheRectISpendALotOfTimeIn()) {
        CGContextDrawImage(ctx, TheRectISpendALotOfTimeIn(), bgImage);
    }
    /* do drawing in front of this */
}
@end
Другие вопросы по тегам