Проблема UITableView при использовании отдельного делегата / источника данных
Общее Описание:
начать с того, что работает, у меня есть UITableView
который был помещен в Xcode-генерируемый вид с помощью Interface Builder. Владелец файла представления устанавливается в созданный Xcode подкласс UIViewController
. К этому подклассу я добавил рабочие реализации numberOfSectionsInTableView: tableView:numberOfRowsInSection:
и tableView:cellForRowAtIndexPath:
и вид таблицы dataSource
и delegate
подключаются к этому классу через владельца файла в Interface Builder.
выше конфигурация работает без проблем. Проблема возникает, когда я хочу переместить это представление таблицы dataSource
и delegate
-реализации в отдельный класс, скорее всего, потому что в представлении есть другие элементы управления, кроме табличного представления, и я хотел бы переместить код, связанный с табличным представлением, в свой собственный класс. Для этого я пытаюсь сделать следующее:
- создать новый подкласс
UITableViewController
в Xcode - переместить известные хорошие реализации
numberOfSectionsInTableView:
,tableView:numberOfRowsInSection:
иtableView:cellForRowAtIndexPath:
к новому подклассу - перетащите a
UITableViewController
на верхний уровень существующей XIB в InterfaceBuilder, удалитеUIView
/UITableView
, которые автоматически создаются для этогоUITableViewController
, а затем выберитеUITableViewController
'S класс, чтобы соответствовать новому подклассу - удалить ранее работающего
UITableView
С имеющейсяdataSource
иdelegate
соединения и подключить их к новомуUITableViewController
когда закончите, у меня нет работает UITableView
. Я в конечном итоге с одним из трех результатов, которые, казалось бы, может произойти в случайном порядке:
- когда
UITableView
загружается, я получаю сообщение об ошибке выполнения, указывающее, что я отправляюtableView:cellForRowAtIndexPath:
к объекту, который не распознает его - когда
UITableView
загружается, проект врывается в отладчик без ошибок - ошибки нет, но
UITableView
не появляется
с отладки и создания базового проекта воспроизвести эту проблему, я обычно вижу 3-й вариант выше (нет ошибки, но нет видимого представления таблицы). Я добавил некоторые вызовы NSLog и обнаружил, что хотя numberOfSectionsInTableView:
и numberOfRowsInSection:
как назвали, cellForRowAtIndexPath:
нет. Я убежден, что мне не хватает чего-то очень простого и надеялся, что ответ может быть очевиден для кого-то с большим опытом, чем у меня. Если это не окажется простым ответом, я был бы рад обновить какой-то код или пример проекта. Спасибо время!
выполните шаги для воспроизведения:
- создайте новую ОС iPhone, приложение на основе просмотра в Xcode и назовите его
TableTest
- открыть
TableTestViewController.xib
в Interface Builder и перетащите aUITableView
на предоставленную видовую поверхность. - подключить
UITableView
' sdataSource
иdelegate
-выходы для владельца файла, который уже должен представлять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;
}
стройте и идите, и вы должны увидеть слово
Hello
явиться вUITableView
теперь, чтобы попытаться переместить этот
UITableView
логика выходит в отдельный класс, сначала создайте новый файл в Xcode, выбравUITableViewController
подкласс и вызов классаTableTestTableViewController
- удалите приведенный выше фрагмент кода из
TableTestViewController.m
иTableTestTableViewController.m
, замена значения по умолчанию реализация этих трех методов с нашими. - вернуться в Interface Builder в том же
TableTestViewController.xib
-файл, перетащитеUITableViewController
в Главное окно IB и удалить новыйUITableView
объект, который автоматически вышел с ним - установите класс для этого нового
UITableViewController
доTableTestTableViewController
- удалить
dataSource
иdelegate
привязки из существующих, ранее работающихUITableView
и снова те же две привязки к новомуTableTestTableViewController
мы создан. - Сохранить изменения, построить и идти, и если вы получаете результаты, которые я получаю, обратите внимание на
UITableView
не работает
устранение:
С некоторыми более устранения неполадок и некоторой помощи от форумы разработчиков iPhone, я уже описывал решение! Главное UIViewController
подкласс проекта нуждается в выходе, указывающем на UITableViewController
экземпляра. Чтобы сделать это, просто добавьте следующее к основному заголовок представления (TableTestViewController.h
):
#import "TableTestTableViewController.h"
и
IBOutlet TableTestTableViewController *myTableViewController;
затем в Interface Builder подключите новую розетку от владельца файла к TableTestTableViewController
в главном окне IB. В части пользовательского интерфейса XIB не требуется никаких изменений. Просто наличие этой розетки на месте, даже если никакой пользовательский код напрямую не использует ее, полностью решает проблему. Спасибо тем, кто помог и кредит идет к BaldEagle на форумах разработчиков iPhone для поиска решения.
4 ответа:
я последовал вашим шагам, воссоздал проект и столкнулся с той же проблемой. В основном вы почти там. Есть 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;
и подключите это в Построителе интерфейса к
TableTestTableViewController
экземпляра.с вышеизложенным это отлично работало на моей машине.
также я думаю, что было бы хорошо указать мотивацию всех (вместо того, чтобы просто использовать
UITableViewController
со своимUITableView
). В моем случае это было использовать другие взгляды, что простоUITableView
на том же экране полно контента. Так что я могу добавитьUILabels
илиUIImages
подUIView
и показатьUITableView
под ними или над ними.
Я просто провел много часов, вытаскивая волосы, пытаясь понять, почему a
UITableView
не будет отображаться, когда, когда я был встроен в отдельный наконечник вместо основного наконечника. Я, наконец, нашел ваше обсуждение выше и понял, что это было потому, что мойUITableViewController
не сохраняется! По-видимому, делегат и свойства источника данныхUITableView
не отмечены "сохранить", и поэтому мой наконечник загружался, но контроллер был брошен... И благодаря чудесам objective-c я получил нет сообщения об ошибках вообще от этого... Я до сих пор не понимаю, почему он не разбился. Я знаю, что раньше видел "сообщение, отправленное в выпущенный xxx"... почему не даешь мне?!?Я думаю, что большинство разработчиков предполагают, что структура, которую они строят в построителе интерфейса, будет проходить в некотором более широком контексте (перо) и не подлежит выпуску. Думаю, я знаю, почему они это делают.. так что iPhone может упасть и перезагрузить части наконечника на низкой памяти. Но человек, это было трудно понять.
может кто-нибудь сказать мне, где я должен был прочитать об этом поведении в документах?
также-о подключении вида. Во-первых, если вы перетащите его из UI builder, вы увидите, что они подключают свойство view (которое является
IBOutlet
) в виде таблицы. Не обязательно выставлятьtableView
, что, кажется, получить набор внутри. На самом деле это даже не кажется необходимым, чтобы установить представление, если вы не хотитеviewDidLoad
уведомление. Я только что разорвал связь просмотра между моимuitableview
иuitableviewcontroller
(только делегат и набор источников данных), и это, по-видимому, работает нормально.
да по какой-то причине (пожалуйста, перезвоните, если кто-нибудь знает, почему...)
tableView
свойстваUITableViewController
не отображается какIBOutlet
даже если это общественная собственность. Поэтому, когда вы используете Interface Builder, вы не можете видеть это свойство для подключения к другомуUITableView
. Так что в вашем подклассе, вы можете создатьtableView
свойство помечено какIBOutlet
и подключить.все это кажется мне хаки и обходной путь, но это, кажется, единственный способ отделить
UITableViewController's
UITableView
и поместите его где-нибудь еще в иерархии пользовательского интерфейса. Я столкнулся с той же проблемой, когда пытался создать представление, где есть вещи, отличные отUITableView
и именно так я решил эту проблему... Это правильный подход???
Я смог сделать эту работу. Я построил действительно хороший приборную панель с 4 TableViews и webview с видео. Ключ имеет отдельные контроллеры tableView и IBOutlets к другим контроллерам tableview, определенным в контроллере представления. В UIB вам просто нужно подключить другие контроллеры tableview к владельцу файла контроллера вида. Затем подключите таблицы к соответствующим контроллерам представления для источника данных и делегата.