1. ホーム
  2. アイオス

[解決済み] [Solved] XibファイルからカスタムUITableViewCellをロードする方法は?

2022-03-29 07:54:35

質問

質問は簡単です。どのようにカスタム UITableViewCell をXibファイルから読み取ることができますか?そうすることで、Interface Builderを使ってセルをデザインすることができるようになります。答えはどうやらメモリ管理の問題で簡単ではなさそうです。 このスレッド は、この問題に言及し、解決策を提案していますが、NDAリリース前でコードがありません。以下はその例です。 長いスレッド は、この問題について議論していますが、明確な答えはありません。

以下は私が使用したコードです。

static NSString *CellIdentifier = @"MyCellIdentifier";

MyCell *cell = (MyCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
    NSArray *nib = [[NSBundle mainBundle] loadNibNamed:CellIdentifier owner:self options:nil];
    cell = (MyCell *)[nib objectAtIndex:0];
}

このコードを使用するには、MyCell.m/.h を作成し、新しいサブクラスの UITableViewCell を追加し IBOutlets を、必要なコンポーネントに置き換えてください。次に、新しい "Empty XIB" ファイルを作成します。IB で Xib ファイルを開き、その中に UITableViewCell オブジェクトを作成し、その識別子を "MyCellIdentifier" に設定し、クラスを MyCell に設定して、コンポーネントを追加してください。最後に IBOutlets をコンポーネントに追加します。なお、IBではFileのOwnerを設定していない。

他の方法は、File's Ownerの設定を提唱し、Xibが追加のファクトリークラスを介してロードされない場合、メモリリークを警告します。Instruments/Leaksで上記をテストしたところ、メモリリークはありませんでした。

では、Xibからセルをロードする標準的な方法は何でしょうか?FileのOwnerを設定するのか?ファクトリーが必要なのか?ファクトリーが必要な場合、そのコードはどのようなものでしょうか?複数のソリューションがある場合、それぞれの長所と短所を明らかにしましょう。

どのように解決するのか?

以下は 原著者は、IB のエンジニアが推奨していると述べています。 .

詳しくは実際の投稿をご覧ください。 私は2の方法の方がシンプルに思えて好きです。

方法その1。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"BDCustomCell"];
    if (cell == nil) {
        // Create a temporary UIViewController to instantiate the custom cell.
        UIViewController *temporaryController = [[UIViewController alloc] initWithNibName:@"BDCustomCell" bundle:nil];
        // Grab a pointer to the custom cell.
        cell = (BDCustomCell *)temporaryController.view;
        [[cell retain] autorelease];
        // Release the temporary UIViewController.
        [temporaryController release];
    }

    return cell;
}

方法その2。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"BDCustomCell"];
    if (cell == nil) {
        // Load the top-level objects from the custom cell XIB.
        NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"BDCustomCell" owner:self options:nil];
        // Grab a pointer to the first object (presumably the custom cell, as that's all the XIB should contain).
        cell = [topLevelObjects objectAtIndex:0];
    }

    return cell;
}

アップデート(2014年)。 2の方法はまだ有効ですが、それに関するドキュメントはもうありません。以前は 公式ドキュメント しかし、現在はストーリーボードに取って代わられ、削除されています。

Githubに動作例を投稿しました。

https://github.com/bentford/NibTableCellExample

Swift 4.2用に編集

override func viewDidLoad() {
    super.viewDidLoad()

    // Do any additional setup after loading the view.
    self.tblContacts.register(UINib(nibName: CellNames.ContactsCell, bundle: nil), forCellReuseIdentifier: MyIdentifier)
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCell(withIdentifier: MyIdentifier, for: indexPath) as! ContactsCell

    return cell
}