异步绘图和触摸

问题描述:

我有一个绘制区域(UIView),我在CGContextRef中绘制。

当然我正在接触画画。
当drawRect方法慢慢地抽取很多现有对象时,触摸不会被捕获。

如果我在drawRect中调用另一个线程中的绘图或者使用函数dispatch_async它不会绘制,因为它有没有合适的背景。

我已经很多人去了,但一无所获。

I have a draw area (UIView), where i draw within the CGContextRef.
Ofcourse i am catching touches to draw. While the drawRect method slowly draws lot's of existing objects the touches are not caught.
If i call drawing in drawRect in separate thread or with function "dispatch_async" it doesn't draw because it has no appropriate context.
I've seached a lot but found nothing.

dispatch_async(dispatch_get_main_queue(), ^{
    [_mainArea setNeedsDisplay];
});




  • 这些事情也无济于事。

  • 我该怎么办?任何人都可以帮忙接触并大量抽取大量物品吗?

    What can i do? Can anybody help to catch touches and draw lots of objects simultainiously?

当你遇到问题时你的图形保持最新,在你开始进入多线程之前......

When you're having problems keeping your graphics up to date, before you start getting into multithreading...


  1. 你应该删除所有对显示的调用 setNeedsDisplay 并将其替换为 setNeedsDisplayInRect:

您应该优化 drawRect:方法,这样您只需重新绘制需要它的视图部分。您可以在此方法中更加花哨,并忽略方法中的 rect 参数,并获取从 getRectsBeingDrawn中获取的原始rects:count:

You should optimize your drawRect: method so that you're only redrawing the parts of the view that need it. You can get even more fancy in this method and ignore the rect argument from the method and obtain the raw rects being drawn from getRectsBeingDrawn:count:.

如果您正在绘制移动物体,请使用CoreAnimation。

If you're drawing moving objects, use CoreAnimation.

如果您有很多重复的对象,请使用 CGLayerRef s

If you have a lot of repeated objects, use CGLayerRefs

使用 dispatch_async()调用 setNeedsDisplay 将不会在另一个线程上绘制视图;所有绘图都发生在 drawRect:中,而 drawRect:总是由主线程/队列调用。

Calling setNeedsDisplay with a dispatch_async() won't make the view draw on another thread; all drawing happens in drawRect:, and drawRect: is always called by the main thread/queue.

UIGraphicsGetCurrentContext()不是线程安全的。然而,你可以做的是在你的异步块中创建一个位图上下文,描边并填充它,然后将这个上下文作为CGImageRef获取,可以将其复制到CGContextRef(正在谈论的那个)到主屏幕上运行的屏幕)。它看起来像这样:

UIGraphicsGetCurrentContext() is not thread safe. What you can do however is create a bitmap context in your async block, stroke and fill into that, and then get this context as a CGImageRef that can be comp'd into the CGContextRef (the one that's talking to the screen) running on the main thread. It would look something like this:

@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