在BubbleLevel示例代码中重绘iPhone上的UIControls / UIButtons

时间:2010-09-08 16:14:38

标签: iphone objective-c uibutton

我很困惑何时应该调用-setNeedsDisplay。例如,为了更新按下之间具有不同图像的按钮(在两者之间切换),来自Apple的示例代码显示在UIButton上调用-setImage。但是,之后我无法调用-setNeedsDisplay。那么UIControl方法是否都在内部执行-setNeedsDisplay,因此-setNeedsDisplay仅在操作UIView的实例时使用?还是有更具体的语义?如果我是UIView的子类,我的方法是否总是在内部处理重绘?如何在文档中指定/在何处?

来自BubbleLevel源代码中的LevelView.m

- (void)toggleHoldButton:(id)sender {
    if (holdButtonIsShowing == YES) 
    {
        holdButtonIsShowing = NO;
        [holdButton setImage:[UIImage imageNamed:@"release_button.png"] forState:UIControlStateNormal];
    } else 
    {
        holdButtonIsShowing = YES;
        [holdButton setImage:[UIImage imageNamed:@"hold_button.png"] forState:UIControlStateNormal];
    }    
}

1 个答案:

答案 0 :(得分:1)

setNeedsDisplay用于重新渲染或重新绘制视图(An UIView或UIView子类实例)。从我们的角度来看:它调用drawRect:但实际上它之前它准备了上下文并使视图可以重新绘制。 (这就是你不应该直接调用drawRect的原因)

通常的情况是你实现了drawRect:方法(一些例子:在视图中使用OpenGL绘制内容或使用CoreText绘制文本或使用CoreGraphics绘制一些图形等) 如果你想在某个时刻明确地更新绘图,你可以调用setNeedsDisplay,它将调用drawRect:并且你将立即重新绘制视图。如果没有,则在视图边界发生变化时调用drawRect:方法,在系统决定需要重绘视图时调用其他情况。

如果是按钮,则不需要这样做,因为当按下按钮时,将完成对setNeedsDisplay的内部调用,使按钮发生变化等等。(谁真的知道后台会发生什么事情是你不必担心drawRect:当以这种方式使用UIButtons时)

您还可以通过移动子图层或子视图来更改视图的外观,这并不一定意味着重新绘制视图。当您将行为视为容器而不是图形对象时就是这种情况。

一个好的规则可能是,如果你没有实现drawRect:方法,则不需要显式调用setNeedsDisplay。

http://developer.apple.com/iphone/library/documentation/uikit/reference/UIView_Class/UIView/UIView.html#//apple_ref/occ/instm/UIView/drawRect

希望它有所帮助。

更新时间:2009/09/09

UIButton调用drawRect的方式取决于它的实现,我们不应该关心它(至少如果我们不是子类化的话)。但如果你真的知道它,你可以继承它并覆盖:

- (void) drawRect:(CGRect)frame{
    NSLog(@"%s is being called!!!", _cmd);
    [super drawRect:frame];
}

现在从另一个对象尝试加载它,调整大小,移动它,滚动它(如果可用),隐藏它并查看调试控制台(Cmd + Shift + R) 我建议不仅要为UIButton而且要为普通的UIView做这件事。 当drawRect:被调用时,这肯定会给出一个清晰的想法。 ;)(还有其他方法,如layoutSubviews:等)

我说我们不应该关心drawRect的原因:在UIButton中是因为我们不需要它,我们使用setImage:forState预设某个状态的图像,这就是全部。我们可以随时重新设置此图像,按钮将根据需要更改其图像,并可能根据苹果工程师设计的方式重新绘制视图。

关于你的问题,如果setNeedsDisplay符合我给你的规则。我相信是的。 我在每个方法的开头都放了一个断点,没有任何东西,并检查调用setNeedsDisplay时发生了什么。没有LeverView的方法被调用! 然后我评论了setNeedsDisplay的3个调用,结果是一样的! (的iOS4.1) 因此,不需要这三行代码。 ;)

调用setNeedsDisplay时必须小心,因为根据您的实现,它可能会使您的程序变得非常慢!既然要重新绘制所有内容,可能就没有必要了。 ;)

Pheeew ......哈哈。关于drawRect的相当长的帖子:

干杯