1. ホーム
  2. オブジェクティブC

[解決済み】ストーリーボードで、複数のコントローラで使用するためのカスタムセルを作成する方法は?

2022-04-08 09:47:09

質問

制作中のアプリでストーリーボードを使おうとしています。アプリ内には リスト ユーザー で、それぞれが他のコレクション (あるリストのメンバー、あるユーザーが所有するリスト) を含んでいます。というわけで、それに応じて ListCellUserCell クラスがあります。目標は、これらのクラスをアプリ全体で再利用できるようにすることです(つまり、私のテーブルビューコントローラのどれでも)。

そこで問題にぶつかっている。

ストーリーボードで、どのビューコントローラでも再利用できるカスタムテーブルビューセルを作成するにはどうすればよいですか?

これまで試した具体的な内容は以下の通りです。

  • コントローラ #1 で、プロトタイプセルを追加し、クラスを私の UITableViewCell のサブクラスを作成し、再利用IDを設定し、ラベルを追加して、クラスのアウトレットに配線しました。Controller #2 では、空のプロトタイプセルを追加し、前と同じクラスと再利用 ID を設定しました。実行すると、Controller #2 でセルを表示したときにラベルが表示されません。Controller #1 では正常に動作しています。

  • 各セルタイプを別のNIBで設計し、適切なセルクラスに配線します。ストーリーボードで、空のプロトタイプセルを追加し、そのクラスと再利用IDを、私のセルクラスを参照するように設定しました。コントローラの viewDidLoad メソッドで、それらのNIBファイルを再利用IDに登録しました。表示すると、両方のコントローラのセルはプロトタイプと同じように空っぽになりました。

  • 両方のコントローラのプロトタイプを空にし、クラスと再利用IDを私のセルクラスに設定しました。セルのUIはすべてコードで構築しました。セルはすべてのコントローラで完全に動作します。

2つ目のケースでは、プロトタイプが常にNIBをオーバーライドしていると思われ、プロトタイプのセルを削除すれば、再利用IDに私のNIBを登録すればうまくいくでしょう。しかし、その場合、セルから他のフレームへのセグエを設定することができなくなります。

つまり、ストーリーボードでテーブルビューベースのフローを構築することと、セルのレイアウトをコードではなくビジュアルで定義することの2点です。この2つを実現する方法は、今のところ見当たりません。

どうすればいい?

私の理解では、あなたはそうしたいと思います。

  1. IBで複数のストーリーボードシーンで使用できるセルを設計する。
  2. セルが含まれるシーンに応じて、そのセルからユニークなストーリーボードセグメンテーションを設定する。

残念ながら、今のところこれを実現する方法はありません。これまでの試みがなぜうまくいかなかったのかを理解するには、ストーリーボードとプロトタイプテーブルビューのセルがどのように機能するのかをもっと理解する必要があります。(もし、あなたが なぜ 他の試みがうまくいかなかった場合は、今すぐお帰りください。バグを報告することを勧める以外、魔法のような回避策はありません)。

ストーリーボードとは、要するに.xibファイルの集合体以上のものではありません。ストーリーボードからいくつかのプロトタイプセルを持つテーブルビューコントローラをロードすると、次のようなことが起こります。

  • 各プロトタイプセルは、実はそれ自体が埋め込まれたmini-nibです。そのため、テーブルビューコントローラーがロードされる際に、プロトタイプセルの nib をそれぞれ実行し、以下のように呼び出します。 -[UITableView registerNib:forCellReuseIdentifier:] .
  • テーブルビューは、コントローラにセルを要求します。
  • おそらく -[UITableView dequeueReusableCellWithIdentifier:]
  • 指定された再利用識別子を持つセルを要求すると、そのセルにnibが登録されているかどうかをチェックする。登録されている場合は、そのセルのインスタンスを生成する。これは以下のステップで構成される。

    1. セルの nib で定義されている、セルのクラスを調べます。コール [[CellClass alloc] initWithCoder:] .
    2. -initWithCoder: メソッドを経由して、サブビューを追加し、nib で定義されたプロパティを設定します。( IBOutlet は、おそらくここでもフックされるのでしょうが、私はそれをテストしていません。 -awakeFromNib )
  • セルを好きなように構成することができます。

ここで重要なのは、以下のような区別があることです。 クラス のセルと 視覚的外観 を指定します。同じクラスのプロトタイプセルを2つ作成しても、そのサブビューのレイアウトは全く異なるものになります。実際、もしデフォルトの UITableViewCell のスタイルでは、まさにこのようなことが起こっているのです。例えば、"Default" スタイルと "Subtitle" スタイルは、両方とも、同じ UITableViewCell クラスがあります。

これは重要なことです : その クラス とは一対一の相関はありません。 ビュー階層 . ビューの階層は、この特定のコントローラに登録されたプロトタイプのセルの中身によって完全に決定されます。

また、このセルの再利用識別子は、グローバルなセル処分場に登録されたものではないことに注意してください。再利用識別子は、1つの UITableView のインスタンスです。


この情報をもとに、上記の試行で何が起こったかを見てみましょう。

<ブロッククオート

Controller #1 で、プロトタイプのセルを追加し、クラスを私の UITableViewCellのサブクラスを作成し、再利用IDを設定し、ラベルを追加し、配線します。 をクラスのアウトレットに追加しました。コントローラ #2 では、空の プロトタイプセルを作成し、前回と同じクラスと再利用idに設定します。このとき でセルを表示しても、ラベルは表示されません。 コントローラ#2。Controller #1では正常に動作します。

これは予想通りです。どちらのセルも同じクラスを持っていますが、コントローラ#2 のセルに渡されるビュー階層にはサブビューが全くありません。つまり、空のセルができあがったわけですが、これはまさにプロトタイプに書いたとおりのものです。

各セルの種類を別の NIB で設計し、その NIB にワイヤリングする。 適切なセルクラス ストーリーボードで、空のプロトタイプのセルを追加しました。 で、そのクラスと再利用IDを、私のセルクラスを参照するように設定しました。で コントローラの viewDidLoad メソッドに、これらの NIB ファイルを登録しました。 再利用ID 表示されたとき、両方のコントローラのセルは のプロトタイプを作成しました。

これも予想通りです。再利用識別子はストーリーボードのシーンやニブ間で共有されるものではないので、これらの異なるセルがすべて同じ再利用識別子を持つということは無意味なことでした。テーブルビューから戻ってくるセルは、ストーリーボードのそのシーンにあるプロトタイプのセルと一致する外観になります。

この解決策は惜しかったですね。ご指摘の通り、プログラム的に -[UITableView registerNib:forCellReuseIdentifier:] を渡す。 UINib を指定すると、そのセルと同じセルが返ってきます。(これは、プロトタイプがnibをオーバーライドしているのではなく、単にテーブルビューにnibを登録していなかったので、ストーリーボードに埋め込まれたnibを見たままになっていたのです)。残念ながら、この方法には欠陥があります。ストーリーボードのセグメンテーションをスタンドアロン nib のセルにフックする方法がないのです。

<ブロッククオート

両方のコントローラでプロトタイプを空にし、クラスと再利用IDを設定しました。 を自分のセルクラスに追加しました。セルのUIはすべてコードで構築しました。セル は、すべてのコントローラで完全に動作します。

当然です。願わくば、これが当然のことであってほしい。


だから、うまくいかなかったんですね。セルをスタンドアローンのペン先でデザインして、複数のストーリーボードのシーンで使用することはできますが、現在そのセルにストーリーボードのセグをフックすることはできません。しかし、これを読む過程で何かを学んでいただければ幸いです。