setNeedsDisplay 只被调用一次

Posted

技术标签:

【中文标题】setNeedsDisplay 只被调用一次【英文标题】:setNeedsDisplay only gets called once 【发布时间】:2013-04-04 20:22:38 【问题描述】:

在我的代码中,我想“动画化”绘制一条线的延迟,因此在向视图添加新线后,我调用 setNeedsDisplay - 一次可以正常工作。

在 drawRect 方法中,我绘制了线条并调用线条的方法来增加线条长度l。现在我想再次调用 setNeedsDisplay 来重绘线条 - 所以它是一个“成长”的动画..

但它只调用一次 setNeedsDisplay 并且再也不会调用,除非我添加了另一行。 我还尝试调用这个类中的一个方法,它调用 setNeedsDisplay,以确保你不能在 drawRect 内部调用它。..

- (void)drawRect:(CGRect)rect 

    for(GameLine *line in _lines) 

        if(line.done) 
            CGContextRef c = UIGraphicsGetCurrentContext();
            CGContextSetLineWidth(c, 5.0f);
            CGContextSetStrokeColor(c, lineColor);

            CGContextBeginPath(c);
            CGContextMoveToPoint(c, line.startPos.x, line.startPos.y);
            CGContextAddLineToPoint(c, line.endPos.x, line.endPos.y);
            CGContextStrokePath(c);
        else 
            CGContextRef c = UIGraphicsGetCurrentContext();
            CGContextSetLineWidth(c, 5.0f);
            CGContextSetStrokeColor(c, delayColor);

            CGContextBeginPath(c);
            CGContextMoveToPoint(c, line.delayStartPos.x, line.delayStartPos.y);
            CGContextAddLineToPoint(c, line.delayEndPos.x, line.delayEndPos.y);
            CGContextStrokePath(c);

            [line incrementDelayLine];
            [self setNeedsDisplay];
        
    

_lines 是具有 GameLine 对象(非原子,保留)属性的 NSMutableArray。

【问题讨论】:

【参考方案1】:

这是意料之中的。

当您调用 setNeedsDisplay 时,您将视图标记为需要重绘。好的。系统得到它。 它会在你的应用程序的主循环下次运行时完成

如果您真的想现在刷新视图,请致电:

[[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode beforeDate: [NSDate date]];

就在setNeedsDisplay之后。

确实,apple documentation 状态(强调我的):

当您的视图的实际内容发生变化时,它是您的 有责任通知系统您的视图需要 重绘。您可以通过调用视图的 setNeedsDisplay 或 setNeedsDisplayInRect:视图的方法。 这些方法让 系统知道它应该在下一次绘图期间更新视图 周期。因为它会等到下一个绘图周期更新 视图,您可以在多个视图上调用这些方法来更新它们 同一时间。

另外,请参阅这些 SO 问题:

How to force a view to render itself? Is there a way to make drawRect work right NOW?(和你一样担心)

【讨论】:

我添加了一个 "NSLog(@"Count: %d", [_lines count]);"到for循环之前的drawRect,它在添加一行之前出现了几次 - 然后又出现了一次,之后就没有了.. @Christian'fuzi'Orgler 一旦你调用了setNeedsDisplay,系统将不会考虑任何其他调用,直到视图被重绘(即直到你的应用程序主循环运行我>)。这是因为您已经明确表示下次模态循环运行时应该重绘视图。如果您希望每次调用 setNeedsDisplay 时都重新绘制视图,请使用我的答案中提供的代码。 注意:请注意在drawRect: 中调用setNeedsDisplay 会导致循环调用,从而导致性能非常糟糕。【参考方案2】:

如果您需要动画 - 启动计时器,一旦它被触发 - 调整您想要的任何行参数并调用 setNeedsDisplay

【讨论】:

以上是关于setNeedsDisplay 只被调用一次的主要内容,如果未能解决你的问题,请参考以下文章

uiview 子类在第一次调用 setneedsdisplay 时显示为黑色矩形,但在那之后就可以了

cellForRowAtIndexPath 只被调用一次

didSelectRowAtIndexPath 只被调用一次

viewWillAppear 只被调用一次[重复]

KnockoutJs - 为啥初始化绑定处理程序只被调用一次?

为啥析构函数被调用两次而构造函数只被调用一次?