【问题标题】:asynchronous drawing and touches异步绘图和触摸
【发布时间】:2013-01-30 14:58:34
【问题描述】:

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

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

我能做什么?任何人都可以帮助捕捉触摸并同时绘制大量对象吗?

【问题讨论】:

    标签: ios objective-c uiview drawrect


    【解决方案1】:

    当您在更新图形时遇到问题时,在开始使用多线程之前...

    1. 您应该删除对displaysetNeedsDisplay 的所有调用,并将它们替换为setNeedsDisplayInRect:

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

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

    4. 如果你有很多重复的对象,使用CGLayerRefs

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

    UIGraphicsGetCurrentContext() 不是线程安全的。但是,您可以做的是在您的异步块中创建一个位图上下文,描边并填充它,然后将此上下文作为 CGImageRef 获取,该 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
    

    【讨论】:

    • 非常感谢,这是一个非常好的解决方案。 (我考虑过使用第二个画布,但我不知道 CGImage)但是 1)我需要两个 CGImage 来同时绘制和重绘,并且复制图像需要很多时间(好的,我可以通过使用指针来处理); 2)这段代码有内存泄漏。我尝试使用 CGImageRelease,但它没有帮助!该怎么办?有没有办法用CGImage的位图替换uiview的画布?
    • 哦,它接缝,泄漏​​也是由上下文引起的。在我添加 CGContextRelease 内存警告后,长时间绘制后停止。
    • 下一步是分析你的绘图代码,看看它在哪里花费了所有时间。你知道每次重绘你要进行多少次绘制操作吗?
    • 更改指针会导致“错误访问”崩溃,原因不明。无论如何,现在滞后只与图像大小有关。并且触摸处理得很好(开始和结束除外)。但这些是其他问题和其他问题。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2017-11-17
    • 1970-01-01
    • 1970-01-01
    • 2023-03-13
    • 1970-01-01
    • 1970-01-01
    • 2012-04-03
    • 1970-01-01
    相关资源
    最近更新 更多