ストーリーボードを使用して静的テーブルビューセル(静的コンテンツ)と動的テーブルビューセル(プロトタイプコンテンツ)を組み合わせる方法はありますか?
テーブルを動的として扱うことをお勧めしますが、常に必要なセルを上部に含めます。ストーリーボードにUITableViewController
を配置し、動的テーブルを使用するようにします。 UITableViewCell
プロトタイプを必要なだけテーブルに追加します。たとえば、静的セルごとに1つと、可変セルを表すために1つ。
UITableViewDataSource
クラス:
#define NUMBER_OF_STATIC_CELLS 3
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.dynamicModel count] + NUMBER_OF_STATIC_CELLS;
}
その後
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row < NUMBER_OF_STATIC_CELLS) {
// dequeue and configure my static cell for indexPath.row
NSString *cellIdentifier = ... // id for one of my static cells
} else {
// normal dynamic logic here
NSString *cellIdentifier = @"DynamicCellID"
// dequeue and configure for [self.myDynamicModel objectAtIndex:indexPath.row]
}
}
これのわずかな変形でしたが、問題がありました。私は実際には動的セルと静的セルを混合したかったのですが、グループは異なりました。つまり、グループ1には静的なセルのみがあり、グループ2には動的なセルがあります。
私は、実際に静的セル値をハードコーディングすることでこれを達成しました(プロトタイプセル識別子に基づいて)。動的セクションには、動的に入力される通常のコンテンツが含まれます。他の誰かが同じ問題を抱えている場合のいくつかのサンプルコードは次のとおりです:
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
if (section == 1){
return @"Dynamic Cells";
}
if (section == 0){
return @"Static Cells";
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (section == 0) {
return 1; //However many static cells you want
} else {
return [_yourArray count];
}
}
-(UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
if (indexPath.section == 0) {
NSString *cellIdentifier = @"staticCellType";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
cell.textLabel.text = @"some static content";
return cell;
} else if (indexPath.section == 1){
NSString *cellIdentifier = @"dynamicCellType";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
cell.textLabel.text = [_yourArray objectAtIndex:indexPath.row];
return cell;
}
return nil;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 2;
}
この問題に対する実際の答えは実際には誰も提供していないため(同じテーブルビューで静的セルとプロトタイプセルの両方を使用)、私はそれを理解できると思いました。それは可能です!
必要に応じて静的セルを作成します。動的セルを必要とするセクションで、標準のUITableViewCellタイプを使用していない場合は、別のNibでカスタムを作成する必要があります。それ以外の場合は、標準のものを使用できます。次に、以下のデリゲートを実装します。基本的に、これらのデリゲートのそれぞれについて、スーパーと呼ぶ静的なものについては、動的なものについては、値を返します。
まず、動的セクションを選択的に表示する必要がある場合は、numberOfSectionsInTableViewを実装する必要があります(それ以外の場合は、このデリゲートを省略できます)。
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
int staticSections = 1;
int dynamicSections = 1;
if (SOME_BOOLEAN) {
return staticSections + dynamicSections;
} else {
return staticSections;
}
}
次に、numberOfRowsInSectionを実装する必要があります。
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (section == 1) {
return A_COUNT;
} else {
return [super tableView:tableView numberOfRowsInSection:section];
}
}
次に、heightForRowAtIndexPathを実装する必要があります。
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 1) {
return 44.0f;
} else {
return [super tableView:tableView heightForRowAtIndexPath:indexPath];
}
}
次に、indentationLevelForRowAtIndexPath:
- (NSInteger)tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 1) {
return 1; // or manually set in IB (Storyboard)
} else {
return [super tableView:tableView indentationLevelForRowAtIndexPath:indexPath]; // or 0
}
}
最後に、cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 1) {
SomeObject *obj = self.someArray[indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"DynamicCell" forIndexPath:indexPath];
cell.textLabel.text = obj.textValue;
return cell;
} else {
return [super tableView:tableView cellForRowAtIndexPath:indexPath];
}
}
テーブルビューを静的テーブルのように見せることができますが、コードで定義することができます。デリゲートメソッドを使用して、セクション、セクションごとの数または行、ヘッダーなどを設定します。
残念ながら、静的テーブルビューmustはUITableViewControllerにあり、1つのテーブルビューしか許可しないため、これは不可能です。
必要なのは、さらに3つの動的UITableviewCellを作成し、静的コンテンツが必要な最初の3行に対して個別にロードすることです。
これを行う方法がわからない場合は、お知らせください。コードを探します。
同じView Controllerで1つのテーブルビューを静的に、もう1つを動的にすることはできないため、両方を動的にする必要があります。最初のテーブルビューでは、View Controllerの初期化時にコードでセルを構成し、セルを更新しません。
別のオプションとして、ステップ4のリンクと同様のビューの一部に動的テーブルビューを埋め込むことで同様の外観を実現し、残りのビューで必要なことをすべて実行して、静的セルで行う予定の設定を行うことができますスクロールビュー、ラベル、ボタンを使用する。
静的テーブルビューに動的コンテンツを含める1つの方法は、追加の行が必要なセルを複製することです。
テーブルビューの動的セクションでは、Interface Builderで1つ以上のセルをレイアウトします。実行時に、NSCoderを使用してアーカイブしてからアーカイブ解除することで、これらのクローンを作成できます。
これは機能しますが、動的プロトタイプテーブルビューから開始してそこから静的行を作成するよりも、必ずしもきれいではありません。
標準のテーブルビューセルでは失敗します。遅延作成されたテキストラベルは正しくレイアウトされません。したがって、UITableViewCellサブクラスを使用して、サブビューのアーカイブとアーカイブ解除を処理しました。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == kContactsSection) {
NSArray *contacts = self.contacts;
Contact *contact = [contacts objectAtIndex:indexPath.row];
NSString *name = contact.name;
NSString *role = contact.role;
if ([role length] == 0) {
NNContactDefaultTableViewCell *cell = (id)[tableView dequeueReusableCellWithIdentifier : @"contactDefault"];
if (cell == nil) {
NNContactDefaultTableViewCell *template = (id)[super tableView : tableView
cellForRowAtIndexPath :[NSIndexPath indexPathForRow:0 inSection:kContactsSection]];
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:template];
cell = [NSKeyedUnarchiver unarchiveObjectWithData:data];
}
cell.contactTextLabel.text = name;
return cell;
}
else {
NNContactDetailTableViewCell *cell = (id)[tableView dequeueReusableCellWithIdentifier : @"contactDetail"];
if (cell == nil) {
NNContactDetailTableViewCell *template = (id)[super tableView : tableView
cellForRowAtIndexPath :[NSIndexPath indexPathForRow:1 inSection:kContactsSection]];
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:template];
cell = [NSKeyedUnarchiver unarchiveObjectWithData:data];
}
cell.contactTextLabel.text = name;
cell.contactDetailTextLabel.text = role;
return cell;
}
}
return [super tableView:tableView cellForRowAtIndexPath:indexPath];
}
上記の例では、2つのセルタイプがあります。どちらもInterface Builderで静的テーブルビューの一部としてレイアウトされています。
1つのセクションで動的コンテンツを取得するには、次のメソッドもオーバーライドする必要があります。
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (section == kContactsSection) {
NSArray *contacts = self.contacts;
NSUInteger contactCount = [contacts count];
return contactCount;
}
return [super tableView:tableView numberOfRowsInSection:section];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSInteger section = indexPath.section;
NSInteger row = indexPath.row;
if (section == kContactsSection) {
return [super tableView:tableView heightForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:kContactsSection]];
}
return [super tableView:tableView heightForRowAtIndexPath:indexPath];
}
- (CGFloat)tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSInteger section = indexPath.section;
if (section == kContactsSection) {
CGFloat indentation = [super tableView:tableView indentationLevelForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:kContactsSection]];
return indentation;
}
CGFloat indentation = [super tableView:tableView indentationLevelForRowAtIndexPath:indexPath];
return indentation;
}
セルのようにスタイル設定されたボタン(静的セルごとに1つ)を作成して、UITableViewのtableHeaderViewまたはtableFooterViewに配置することもできます。結局のところ、これらのボタンは単なるビューです。
ボタンとセルで選択を行うためのロジックを追加して、通常のルックアンドフィールを維持する必要があります。
もちろん、これは、静的セルをテーブルの上部または下部にあるテーブルビューに挿入することを前提としています。