首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在drawLayer:inContext过程中调用的setNeedsDisplayInRect:

在drawLayer:inContext过程中调用的setNeedsDisplayInRect:
EN

Stack Overflow用户
提问于 2011-11-17 03:17:07
回答 2查看 2.3K关注 0票数 5

我在我的应用程序中使用了CATiledLayer,因此,该图层的绘制是在后台线程中完成的。也就是说,我的委托的drawLayer:inContext:方法是从后台线程调用的。用于使CATiledLayer的某些部分无效的setNeedsDisplayInRect始终从主线程调用。

因为它们是独立的线程,所以当后台线程在drawLayer:inContext方法中时,偶尔会调用setNeedsDisplayInRect。我注意到在这种情况下setNeedsDisplayInRect被忽略了(不会再次调用drawLayer:inContext)。

我已经记录了一个bug to Apple,因为我认为这是不正确的。但我很难弄清楚如何解决这种情况。你有什么好主意吗?

编辑:

我使用以下代码测试了斯坦尼斯劳的答案:

代码语言:javascript
复制
- (void) setNeedsDisplayInRect:(CGRect)rect
{
    NSLog(@"setNeedsDisplayInRect:%@", NSStringFromCGRect(rect));
    [super setNeedsDisplayInRect:rect];
}

- (void) drawLayer:(CALayer *)layer inContext:(CGContextRef)gc
{
    CGRect bounds = CGContextGetClipBoundingBox(gc);
    NSLog(@"drawLayer:inContext: bounds=%@", NSStringFromCGRect(bounds));

    dispatch_async(dispatch_get_current_queue(), ^{
        [self setNeedsDisplayInRect:bounds];
    });

    CGContextSetFillColorWithColor(gc, testColor.CGColor);
    CGContextFillRect(gc, bounds);
    sleep(0.2); // simulate the time it takes to draw complicated graphics
    NSLog(@"end drawLayer:inContext: bounds=%@", NSStringFromCGRect(bounds));
}

正如所给出的,代码确实会导致绘制无限重复,但有时在setNeedsDisplayInRect:和相应的drawLayer:inContext:之间会有长达5秒的延迟,其中不会发生任何其他事情。请参见下面的日志作为示例。注意不规则的行为:在第一秒内,一些瓦片被重绘多次,而另一些瓦片只被重绘一次。然后有5秒的暂停,循环再次开始。

这是在使用IOS6.0的模拟器上测试的(我选择这个版本,因为早期版本有另一个在6.0中修复的bug :它们有时会绘制两次相同的瓦片)。

代码语言:javascript
复制
2012-10-27 15:51:38.771 TiledLayerTest[39934:15a13] drawLayer:inContext: bounds={{0, 300}, {300, 180}}
2012-10-27 15:51:38.774 TiledLayerTest[39934:15a13] end drawLayer:inContext: bounds={{0, 300}, {300, 180}}
2012-10-27 15:51:38.774 TiledLayerTest[39934:1570f] drawLayer:inContext: bounds={{300, 0}, {20, 300}}
2012-10-27 15:51:38.776 TiledLayerTest[39934:1570f] end drawLayer:inContext: bounds={{300, 0}, {20, 300}}
2012-10-27 15:51:38.776 TiledLayerTest[39934:1630b] setNeedsDisplayInRect:{{0, 300}, {300, 180}}
2012-10-27 15:51:38.777 TiledLayerTest[39934:1540f] setNeedsDisplayInRect:{{300, 0}, {20, 300}}
2012-10-27 15:51:38.780 TiledLayerTest[39934:15a13] drawLayer:inContext: bounds={{300, 0}, {20, 300}}
2012-10-27 15:51:38.781 TiledLayerTest[39934:15a13] end drawLayer:inContext: bounds={{300, 0}, {20, 300}}
2012-10-27 15:51:38.782 TiledLayerTest[39934:1540f] setNeedsDisplayInRect:{{300, 0}, {20, 300}}
2012-10-27 15:51:38.789 TiledLayerTest[39934:1570f] drawLayer:inContext: bounds={{0, 0}, {300, 300}}
2012-10-27 15:51:38.791 TiledLayerTest[39934:15a13] drawLayer:inContext: bounds={{300, 300}, {20, 180}}
2012-10-27 15:51:38.792 TiledLayerTest[39934:15a13] end drawLayer:inContext: bounds={{300, 300}, {20, 180}}
2012-10-27 15:51:38.793 TiledLayerTest[39934:1570f] end drawLayer:inContext: bounds={{0, 0}, {300, 300}}
2012-10-27 15:51:38.795 TiledLayerTest[39934:1540f] setNeedsDisplayInRect:{{0, 0}, {300, 300}}
2012-10-27 15:51:38.795 TiledLayerTest[39934:1540f] setNeedsDisplayInRect:{{300, 300}, {20, 180}}
2012-10-27 15:51:38.798 TiledLayerTest[39934:15a13] drawLayer:inContext: bounds={{0, 0}, {300, 300}}
2012-10-27 15:51:38.800 TiledLayerTest[39934:15a13] end drawLayer:inContext: bounds={{0, 0}, {300, 300}}
2012-10-27 15:51:38.802 TiledLayerTest[39934:1630b] setNeedsDisplayInRect:{{0, 0}, {300, 300}}
2012-10-27 15:51:38.806 TiledLayerTest[39934:1570f] drawLayer:inContext: bounds={{0, 300}, {300, 180}}
2012-10-27 15:51:38.808 TiledLayerTest[39934:1630b] setNeedsDisplayInRect:{{0, 300}, {300, 180}}
2012-10-27 15:51:38.809 TiledLayerTest[39934:1570f] end drawLayer:inContext: bounds={{0, 300}, {300, 180}}
2012-10-27 15:51:38.813 TiledLayerTest[39934:15a13] drawLayer:inContext: bounds={{0, 300}, {300, 180}}
2012-10-27 15:51:38.816 TiledLayerTest[39934:1630b] setNeedsDisplayInRect:{{0, 300}, {300, 180}}
2012-10-27 15:51:38.816 TiledLayerTest[39934:15a13] end drawLayer:inContext: bounds={{0, 300}, {300, 180}}
2012-10-27 15:51:43.774 TiledLayerTest[39934:1540f] drawLayer:inContext: bounds={{0, 300}, {300, 180}}
2012-10-27 15:51:43.776 TiledLayerTest[39934:1540f] end drawLayer:inContext: bounds={{0, 300}, {300, 180}}
2012-10-27 15:51:43.776 TiledLayerTest[39934:1630f] drawLayer:inContext: bounds={{0, 0}, {300, 300}}
EN

回答 2

Stack Overflow用户

发布于 2012-10-27 07:02:46

我已经发布了我对类似问题的答案:setNeedsDisplayInMapRect doesn't trigger new drawMapRect: call (这里只是一个不重复答案的链接)。

简而言之:您应该向dispatch_get_main_queue()分派一个setNeedsDisplayInRect方法调用。

票数 0
EN

Stack Overflow用户

发布于 2012-10-27 23:11:13

您可以尝试以这种方式使用NSRecursiveLock

代码语言:javascript
复制
- (void) setNeedsDisplayInRect:(CGRect)rect
{
    [self.lock lock]
    NSLog(@"setNeedsDisplayInRect:%@", NSStringFromCGRect(rect));
    [super setNeedsDisplayInRect:rect];
    [self.lock unlock]
}

- (void) drawLayer:(CALayer *)layer inContext:(CGContextRef)gc
{
    [self.lock lock]
    CGRect bounds = CGContextGetClipBoundingBox(gc);
    NSLog(@"drawLayer:inContext: bounds=%@", NSStringFromCGRect(bounds));


    // drawing code


    NSLog(@"end drawLayer:inContext: bounds=%@", NSStringFromCGRect(bounds));
    [self.lock unlock]
}

这可确保在绘图过程中不会调用setNeedsDisplayInRect。但是,这可能会影响性能,因为lock可能会阻塞主线程,并且您不能并行绘制多个平铺。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8157349

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档