Общее описание:
Чтобы начать с того, что работает, у меня есть UITableView, который был помещен в Xcode-сгенерированное представление с помощью Interface Builder. Владелец файла вида настроен на подкласс, созданный Xcode, UIViewController. В этот подкласс я добавил рабочие реализации numberOfSectionsInTableView: tableView:numberOfRowsInSection: и tableView:cellForRowAtIndexPath:, а Table View dataSource и delegate подключены к этому классу через File Owner в Interface Builder.
Вышеупомянутая конфигурация работает без проблем. Проблема возникает, когда я хочу переместить этот вид таблицы dataSource и delegate -изменения в отдельный класс, скорее всего, потому что в представлении помимо представления таблицы есть другие элементы управления, и я бы хотел переместить представление таблицы связанный код с его собственным классом. Для этого попробуйте следующее:
- Создайте новый подкласс
UITableViewControllerв Xcode - Переместите известные хорошие реализации
numberOfSectionsInTableView:,tableView:numberOfRowsInSection:иtableView:cellForRowAtIndexPath:в новый подкласс - Перетащите
UITableViewControllerна верхний уровень существующего XIB в InterfaceBuilder, удалитеUIView/UITableView, которые автоматически создаются для этогоUITableViewController, затем установите классUITableViewControllerв соответствие с новым подклассом - Удалите ранее работающие
UITableViewсуществующиеdataSourceиdelegateсоединения и подключите их к новомуUITableViewController
Когда закончите, у меня нет рабочего UITableView. Я получаю один из трех результатов, которые могут казаться случайными:
- Когда загружается
UITableView, я получаю ошибку времени выполнения, указывающую, что я отправляюtableView:cellForRowAtIndexPath:объекту, который его не распознает. - Когда загружается
UITableView, проект разбивается на отладчик без ошибок - Ошибка отсутствует, но
UITableViewне отображается
С некоторой отладкой и созданием базового проекта, чтобы воспроизвести эту проблему, я обычно вижу третий вариант выше (нет ошибки, но нет видимого вида таблицы). Я добавил некоторые вызовы NSLog и обнаружил, что хотя numberOfSectionsInTableView: и numberOfRowsInSection: оба вызываются, cellForRowAtIndexPath: нет. Я убежден, что я пропустил что-то очень простое и надеялся, что ответ может быть очевидным для кого-то, у кого больше опыта, чем у меня. Если это не будет легким ответом, я был бы рад обновить код или образец проекта. Спасибо за ваше время!
Полные шаги для воспроизведения:
- Создайте новую iPhone OS, приложение на основе View в Xcode и назовите ее
TableTest - Откройте
TableTestViewController.xibв Interface Builder и перетащитеUITableViewна предоставленную поверхность. - Подключите
UITableViewdataSourceиdelegate-outlets к файловому владельцу, который уже должен представлять классTableTestViewController. Сохраните изменения. - Вернитесь в Xcode, добавьте следующий код в
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;
}
-
Build и Go, и вы должны увидеть слово
HelloвUITableView -
Теперь, чтобы попытаться переместить эту логику
UITableViewв отдельный класс, сначала создайте новый файл в Xcode, выбрав подклассUITableViewControllerи вызовите классTableTestTableViewController - Удалите приведенный фрагмент кода из
TableTestViewController.mи поместите его вTableTestTableViewController.m, заменив стандартную реализацию этих трех методов на наш. - В интерфейсе Builder в том же файле
TableTestViewController.xibперетащитеUITableViewControllerв основное окно IB и удалите новыйUITableViewобъект, который автоматически появился с ним - Установите класс для этого нового
UITableViewControllerвTableTestTableViewController - Удалите привязки
dataSourceиdelegateиз существующего ранее работающегоUITableViewи повторно подключите те же самые два привязки к новомуTableTestTableViewController, который мы создали. - Сохраняйте изменения, стройте и идите, и если вы получаете результаты, которые я получаю, обратите внимание, что
UITableViewбольше не функционирует должным образом
Решение:
Еще несколько проблем с устранением неполадок и некоторая помощь от Форумы разработчиков iPhone, я документировал решение! Для основного подкласса UIViewController проекта требуется выход, указывающий на экземпляр UITableViewController. Для этого просто добавьте следующее в заголовок основного представления (TableTestViewController.h):
#import "TableTestTableViewController.h"
и
IBOutlet TableTestTableViewController *myTableViewController;
Затем в интерфейсе Builder подключите новую розетку от File Owner к TableTestTableViewController в главном окне IB. Никаких изменений не требуется в части пользовательского интерфейса XIB. Просто имея эту розетку на месте, даже если код пользователя не использует ее напрямую, она полностью устраняет проблему. Благодаря тем, кто помог, и кредитует BaldEagle на форумах разработчиков iPhone для поиска решения.