异步绘图和触摸

时间:2013-01-30 14:58:35

标签: ios objective-c uiview drawrect

我有一个绘制区域(UIView),我在CGContextRef中绘制。
当然,我正在接触画画。 当drawRect方法慢慢地抽取大量现有对象时,触摸不会被捕获 如果我在drawRect中调用drawRect在单独的线程中或使用函数“dispatch_async”,它不会绘制,因为它没有适当的上下文。
我已经进行了很多搜索,但一无所获。

dispatch_async(dispatch_get_main_queue(), ^{
    [_mainArea setNeedsDisplay];
});
  • 这些事情也无济于事。

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

1 个答案:

答案 0 :(得分:8)

如果您在开始进入多线程之前遇到了使图形保持最新的问题......

  1. 您应该移除对displaysetNeedsDisplay的所有来电,并将其替换为setNeedsDisplayInRect:

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

  3. 如果您正在绘制移动对象,请使用CoreAnimation。

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

  5. 使用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