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

Iphone IB和UIView。从nib加载视图层次结构的正确方法是什么?,iphone,cocoa-touch,uiview,interface-builder,nib,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 t

谁能教我如何从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)
这让我头疼了好一阵子

干杯,
Doug

如果您使用Interface Builder中的IBOutlets返回到代码中,事情会简单一些。这样,只要您尝试访问已设置的UIView outlet,它就会被加载及其所有子项,然后UIView的initWithCoder就会被调用(如果您已经对其进行了子类化,则会很有用)

否则,我会这样做:

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;

我不确定另一个答案在这一点上是否完全清楚,但您在视图上设置的任何IBOutlets都会被连接到相同的loadnib中,该loadnib名为:callyoureadoday。因此,在该视图的标题中,您需要为myView和pageNumberLabel声明IBOutlets,然后将它们附加到xib中的文件所有者(并将文件的所有者类型设置为调用loadNibNamed:from的视图)

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

您应该保留返回的 数组或它包含的对象 手动阻止nib文件 防止对象被释放 过早地

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

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


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

Kendall,我已经仔细阅读了《资源编程指南》中的文档,据我所知。我应该完全清楚这段代码。它应该能正常工作。循环抛出的每个迭代都应该启动对nib文件的新读取。因为我没有做任何分配/拷贝,所以我应该可以走了。如“规则”所述。我仍然不清楚为什么这个简单的代码不能像预期的那样工作。事实上,我同意上面的代码是应该工作的-它是如何破坏的?
IBOutlet UIButton *nextButton,
          *stopButton1,
          *stopButton2,
          *infoButton,
          *bitsonthegoButton;
IBOutlet UILabel *pointsLabel1,
         *pointsLabel2,
         *totalPointsLabel1,
         *totalPointsLabel2;