0

誰かが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)

これは私の頭を今しばらくの間傷つけていますか?

乾杯、ダグ

4

2 に答える 2

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;
于 2009-10-06T03:39:10.613 に答える
0

この点で他の答えが正確に明確であるかどうかはわかりませんでしたが、ビューに設定したIBOutletsは、同じloadNibNamed:今日行っている呼び出しに接続されます。したがって、そのビューのヘッダーで、myViewとpageNumberLabelの両方のIBOutletsを宣言し、それらをxibのファイルの所有者にアタッチします(ファイルの所有者タイプを、loadNibNamed:fromを呼び出すビューに設定します)。

それはあなたの人生を楽にするためだけです。あなたが尋ねた質問に答えるために、「loadNibNamed:owner:options」のドキュメントには次のように書かれています。

nibファイルオブジェクトが時期尚早に解放されないように、返された配列またはそれに含まれるオブジェクトを手動で保持する必要があります。

したがって、配列は自動解放され、その中のすべてのオブジェクトも同様になります(自動解放された配列を返す呼び出しから予想されます)。ビューを保持したいので、それを保持します-そうすることは、ビューがサブビューとして設定されたものをすべて保持するため、メインビューのサブビューも保持されることを意味します。同時にラベルを解放しない限り、メインビューを解放したときにリークの原因となるラベルも保持している場合(ただし、それを行う意味はないようです)。

ただし、「ビューを保持する」と言うときは、投稿したコードで、コンテナビューにサブビューとして追加するだけで、すでにそうしていることに注意してください。前述のように、ビューはサブビューを保持します。MyViewは、サブビューから削除された場合に解放されるため、何らかの理由で削除して保持したい場合は、保持する必要があります。

ペン先の読み込みメモリ管理は最初は複雑に見えますが、実際にはルールは見た目よりもはるかに単純です。

于 2009-10-06T05:05:40.943 に答える