概要:
動作するものから始めるために、Interface Builderを使用してXcodeで生成されたビューに配置されたUITableView
があります。ビューのファイル所有者は、Xcodeが生成したUIViewController
のサブクラスに設定されます。このサブクラスにnumberOfSectionsInTableView: tableView:numberOfRowsInSection:
とtableView:cellForRowAtIndexPath:
の実装を追加しました。TableViewのdataSource
とdelegate
は、Interface BuilderのFile Ownerを介してこのクラスに接続されています。
上記の構成は問題なく機能します。このテーブルビューのdataSource
およびdelegate
- implementationsを別のクラスに移動したい場合に問題が発生します。これは、おそらくテーブルビュー以外にビューに他のコントロールがあり、テーブルビュー関連のコードを移動したいためです。独自のクラスに。これを達成するために、私は次を試みます:
UITableViewController
の新しいサブクラスを作成しますnumberOfSectionsInTableView:
、tableView:numberOfRowsInSection:
、およびtableView:cellForRowAtIndexPath:
の既知の実装を新しいサブクラスに移動しますUITableViewController
をInterfaceBuilderのexistingXIBの最上位にドラッグし、このUIView
に対して自動的に作成されるUITableView
/UITableViewController
を削除し、UITableViewController
のクラスを新しいサブクラスに一致するように設定しますUITableView
の既存のdataSource
およびdelegate
接続を削除し、それらを新しいUITableViewController
に接続します完了すると、UITableView
が機能しません。ランダムに発生する可能性のある3つの結果のいずれかになります。
UITableView
がロードされると、tableView:cellForRowAtIndexPath:
を認識していないオブジェクトに送信していることを示すランタイムエラーが表示されます。UITableView
がロードされると、プロジェクトはエラーなしでデバッガーにブレークインしますUITableView
は表示されませんデバッグを行い、この問題を再現するために基本的なプロジェクトを作成した場合、通常、上記の3番目のオプションが表示されます(エラーは表示されませんが、テーブルビューは表示されません)。 NSLog呼び出しをいくつか追加したところ、numberOfSectionsInTableView:
とnumberOfRowsInSection:
の両方が呼び出されていますが、cellForRowAtIndexPath:
は呼び出されていません。私は本当にシンプルなものを見逃していると確信しており、私よりも多くの経験を持つ人には答えが明らかであることを望んでいた。これが簡単な答えにならない場合は、いくつかのコードまたはサンプルプロジェクトで更新したいと思います。御時間ありがとうございます!
完全な再現手順:
TableTest
と呼びますTableTestViewController.xib
を開き、UITableView
を提供されたビューサーフェスにドラッグします。UITableView
のdataSource
およびdelegate
- outletsをFile's Ownerに接続します。これは、既にTableTestViewController
- classを表しているはずです。変更を保存しますTableTestViewController.m:
に追加します- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
NSLog(@"Returning num sections");
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSLog(@"Returning num rows");
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(@"Trying to return cell");
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}
cell.text = @"Hello";
NSLog(@"Returning cell");
return cell;
}
ビルドして実行すると、Hello
にWord UITableView
が表示されるはずです。
このUITableView
のロジックを別のクラスに移動するには、まずXcodeで新しいファイルを作成し、UITableViewController
サブクラスを選択して、クラスTableTestTableViewController
を呼び出します
TableTestViewController.m
から削除してTableTestTableViewController.m
に配置し、これら3つのメソッドのデフォルトの実装を当社のものに置き換えます。TableTestViewController.xib
-ファイル内のInterface Builderに戻り、UITableViewController
をメインIBウィンドウにドラッグし、自動的に付属する新しいUITableView
オブジェクトを削除しますUITableViewController
のクラスをTableTestTableViewController
に設定しますdataSource
からdelegate
およびUITableView
バインディングを削除し、作成した新しいTableTestTableViewController
に同じ2つのバインディングを再接続します。UITableView
が適切に機能しなくなっていることに注意してください。解決策:さらにトラブルシューティングと iPhone開発者フォーラム からの支援を受けて、解決策を文書化しました!プロジェクトのメインUIViewController
サブクラスには、UITableViewController
インスタンスを指すアウトレットが必要です。これを実現するには、次をプライマリビューのヘッダー(TableTestViewController.h
)に追加するだけです。
#import "TableTestTableViewController.h"
そして
IBOutlet TableTestTableViewController *myTableViewController;
次に、Interface Builderで、File's Ownerの新しいアウトレットをメインIBウィンドウのTableTestTableViewController
に接続します。 XIBのUI部分を変更する必要はありません。このアウトレットを配置するだけで、ユーザーコードが直接使用しない場合でも、問題は完全に解決します。支援してくれた人たちに感謝し、解決策を見つけるためにiPhone開発者フォーラムのBaldEagleにクレジットを提供します。
私はあなたの手順に従い、プロジェクトを再作成し、同じ問題に遭遇しました。基本的にあなたはほとんどそこにいます。欠けているものが2つあります(修正後は動作します)。
tableView
のTableTestTableViewController
を画面にあるUITableView
に接続する必要があります。 IBOutlet
ではないので前に言ったように、tableView
プロパティをオーバーライドして、IBOutlet
にすることができます:
@interface TableTestTableViewController : UITableViewController {
UITableView *tableView;
}
@property (nonatomic, retain) IBOutlet UITableView *tableView;
次に、TableTestTableViewController
への参照を追加し、TableTestViewController
に保持します。そうしないと、TableTestTableViewController
が解放される可能性があり(ペン先に何もぶら下がっていない状態でロードした後)、そのために不安定な結果、クラッシュ、または何も表示されません。追加するには:
@interface TableTestViewController : UIViewController {
TableTestTableViewController *tableViewController;
}
@property (nonatomic, retain) IBOutlet TableTestTableViewController *tableViewController;
それをInterface BuilderでTableTestTableViewController
インスタンスに接続します。
上記で、これは私のマシンでうまくいきました。
また、(すべてのUITableViewController
でUITableView
を使用する代わりに)このすべての背後にある動機を述べることは良いと思います。私の場合、同じ画面いっぱいのコンテンツでUITableView
だけを使用する他のビューを使用することでした。したがって、UILabels
の下に他のUIImages
またはUIView
を追加し、それらの下または上にUITableView
を表示できます。
何らかの理由ではい(誰かが理由を知っているならチャイムしてください...)tableView
のUITableViewController
プロパティは、パブリックプロパティであってもIBOutlet
として公開されません。したがって、Interface Builderを使用する場合、他のUITableView
に接続するためのプロパティは表示されません。そのため、サブクラスで、tableView
としてマークされたIBOutlet
プロパティを作成し、それを接続できます。
これはすべてハックであり、回避策のようですが、UITableViewController's
UITableView
を分離してUI階層の別の場所に配置する唯一の方法のようです。 UITableView
以外のものがあるビューをデザインしようとしたときに同じ問題に遭遇しました。それが解決方法でした...これは正しいアプローチですか?
この作品を作ることができました。 4つのTableViewとビデオ付きのWebビューを備えた、本当にすてきなダッシュボードを作成しました。重要なのは、個別のtableViewコントローラーと、View Controllerで定義されている他のTableViewコントローラーへのIBOutletsを持つことです。 UIBでは、他のTableView ControllerをView Controllerのファイル所有者に接続するだけです。次に、テーブルをデータソースとデリゲートの対応するView Controllerに接続します。