为UIView定制initWithFrame

时间:2012-04-11 07:08:40

标签: iphone objective-c uiview uikit

我正在尝试为UIView定制初始化程序的最佳方法,以便可以将值传递给初始化程序,并立即将其存储为UIView子类中的iVar,因为此值是绘图所需的drawRect

目前我正在使用默认的initWithFrame,然后创建此UIView的类会在调用initWithFrame后将其iVar设置为值,并且它实际上正在工作;不知何故,drawRect获得此iVar的值,即使在初始化之后设置了

所以我需要两件事之一:

1)有信心知道这是可以的:我可以依赖drawRect以某种方式延迟绘图,以便在初始化UIView之后由另一个对象设置iVars。在这种情况下,只有在UIView初始化时才会调用drawRect吗?

或者,

2)我需要在初始化期间传递值:这是创建自定义初始化程序的最佳方法,该初始化程序需要(CGRect)frame作为initWithFrame.的参数,这可能就像这样简单:

 myNewView=[[MyCustomView alloc] initWithFrame:myRect andMore:myValue];

然后在MyCustomView.m中:

 - (id)initWithFrame:(CGRect)frame andMore:(int)someValue
  {
     self = [super initWithFrame:frame];
     if (self) {
       myIvar=someValue;
       ... //continue as normal
     }
  }

这段代码会是一个好方法吗?然后我会很容易地知道在调用drawRect之前值已存在。

4 个答案:

答案 0 :(得分:4)

1。)您可以依赖drawRect:init之后调用drawRect:。实际上,在完成视图绘制和合成时将调用super initWithFrame:,这通常是由于核心动画提交而发生的(如果修改任何CALayer或UIView,则在runloop结束时完成(总是如此)由CALayer支持))。

2。)从架构的角度来看,这种方法更好。如果你认为这个变量是你的类功能的一个组成部分(并且没有它,类就无法正常工作),它绝对应该是一个init参数。您也可以考虑在其他init-Methods中抛出NSInternalInconsistencyException(或任何其他异常)和/或将它们标记为已弃用(使用{{1}}调用时,超类的init-Methods仍然可以正常工作。)

答案 1 :(得分:2)

当您使用指定的指定初始化程序以编程方式显式创建视图时,第二种方法是理想的。警告:如果视图是通过NIB构建的,那么不是就是这种情况。

答案 2 :(得分:1)

简短的回答:你的两种方法都可以正常工作。

更长的答案:

  1. 在runloop中调用drawRect:方法,因此在完成所有初始化然后放弃控制回到runloop之前不会调用。当然,如果你初始化视图,然后立即设置属性,你就不会有问题。

  2. 你的第二种方法应该可以正常工作。

  3. 我会使用第二种方法。

答案 3 :(得分:1)

Martin Ullrich 正确地解决了这个问题。 但我想补充一点。

如果您在视图上致电initWithFrameinit。这不会调用drawRect方法。
将该视图添加到窗口时,以及in the next runLoop it will call this method,它会生成一个在屏幕上显示的位图。