IB和UIView。从笔尖加载视图层次结构的正确方法是什么?

时间:2009-10-05 20:41:24

标签: iphone cocoa-touch uiview interface-builder nib

有人可以通过正确的方式向我学习从nib文件加载视图层次结构。我使用加载的视图作为模板来消除一系列视图,我正在使用的当前方法被巧妙地破解。在我应该的时候,我似乎没有复制或保留。这是相关的代码:

// pageSet is a list of view tag numbers I'll be using
for (NSNumber *n in pageSet) {

    NSUInteger viewTag = [n integerValue];

    // Ingest the nib. Should there be a copy or retain here?
    NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"RandomStripe" owner:self options:nil];

    // Pull the view from the nib. Should there be a copy or retain here?
    MyView *view = (MyView *)[topLevelObjects objectAtIndex:0];

    // The view has a label as it's subview
    UILabel *pageNumberLabel = [view.subviews objectAtIndex:0];
    pageNumberLabel.text     = [NSString stringWithFormat:@"%d", viewTag];

    CGFloat xOffset = ((float) viewTag) * self.scrollView.bounds.size.width;

    view.frame = CGRectMake(xOffset, 0, self.scrollView.bounds.size.width, self.scrollView.bounds.size.height);
    view.tag = viewTag;

    // Insert the view as a child of my containerView
    [self.containerView addSubview:view];

} // for (pageSet)

现在这让我头疼吗?

干杯, 道格

2 个答案:

答案 0 :(得分:2)

如果您将Interface Builder中的IBOutlets用于代码,那么事情会更容易一些。这样,一旦你尝试访问你已经设置的UIView插座,它就会被所有子节点加载,然后UIView的initWithCoder将被调用(如果你已经将其子类化了,那么它很有用)。

@property (retain, nonatomic) IBOutlet iiView   *iiView;

否则,我这样做:

if (self.numberView == nil) {
    NumberView  *numView = [[NumberView alloc] initWithNibName:@"NumberView" bundle:[NSBundle mainBundle]];
    self.numberView = numView;
    [numView release];
}

(对于numberView的IBOutlet,我只是继续使用numberView而不是上面的代码)

在这两种情况下,numberView的所有子视图(子视图)都会同时加载。如果我需要访问标签或按钮,我会为那些人做一个IBOutlet,所以我不必遍历视图层次结构来寻找它们。

IBOutlet UIButton *nextButton,
          *stopButton1,
          *stopButton2,
          *infoButton,
          *bitsonthegoButton;
IBOutlet UILabel *pointsLabel1,
         *pointsLabel2,
         *totalPointsLabel1,
         *totalPointsLabel2;

答案 1 :(得分:0)

我不确定其他答案在这一点上是否完全清楚,但是您在视图上设置的任何IBOutlet都将使用相同的loadNibNamed连接:您今天正在进行的调用。因此,在该视图的标题中,您将为myView和pageNumberLabel声明IBOutlets,然后将它们附加到xib中的File的Owner(并将File的Owner类型设置为您正在调用loadNibNamed的视图:from)。

这只是为了让你的生活更轻松。要回答您提出的问题,“loadNibNamed:owner:options”的文档告诉我们:

  

你应该保留退回的   数组或它包含的对象   手动阻止nib文件   对象被释放   过早。

因此,数组是自动释放的,并且其中的所有对象也是如此(您可以从调用返回自动释放的数组中获得该对象)。由于您希望保留视图,因此您将保留该视图 - 这样做意味着主视图的任何子视图也将保留,因为视图将保留任何设置为子视图的内容。如果您在释放主视图时也保留了可能导致泄漏的标签,除非您同时发布标签(但似乎没有意义)。

但是请注意,当我说“保留视图”时,您已经在您发布的代码中这样做,只需将其作为子视图添加到容器视图中 - 如上所述视图保留子视图。如果MyView已从子视图中删除,那么MyView将被释放,因此如果您因任何原因这样做而希望保留它,那么您希望保留它。

Nib加载内存管理起初看起来很复杂,但规则实际上要比看起来简单得多。