Как настроить UITableView в UIViewController, созданный в файле .xib
У меня есть класс вроде этого:
@interface ExerciseLogDetails : UIViewController<UIActionSheetDelegate, UITableViewDelegate, UITableViewDataSource> {
где я пытаюсь отобразить некоторые элементы, за которыми следует UITextView. Элемент UITextView создается в Interface Builder. При выполнении этого кода:
- (void)viewDidLoad {
self.tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
tableView.dataSource = self;
tableView.delegate = self;
[self.view addSubview:self.tableView];
}
показывает таблица, но не та, которую я настроил в Interface Builder. Он полностью пуст и неформатирован. Как я могу получить доступ к своей таблице и прогрмировать ее данными?
Спасибо!
Ответы
Ответ 1
Если вы настроили tableView в IB, вы также не должны создавать его программно, вы должны создать @property (nonatomic, retain) IBOutlet UITableView *tableView;
и подключить его к tableView, настроенному в IB.
Попробуйте установить точку останова в таблице tableView
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
делегата, чтобы узнать, вызван ли этот метод.
Из документов Apple UITableView:
Объект UITableView должен иметь объект, который действует как источник данных и объект, который выступает в качестве делегата; обычно эти объекты либо делегат приложения, либо, чаще, пользовательский Объект UITableViewController. Источник данных должен принять Протокол UITableViewDataSource и делегат должны принять UITableViewDelegate протокол. Источник данных предоставляет информацию что UITableView должен создавать таблицы и управлять моделью данных когда строки таблицы вставляются, удаляются или переупорядочиваются. Делегат предоставляет ячейки, используемые таблицами, и выполняет другие задачи, такие как управление видами аксессуаров и выборами.
Как вы можете видеть, если u не задает dataSource для вашего TableView, tableView не будет знать, как и что отображать, поэтому ничего не произойдет.
Вы можете установить его, вызвав tableView.dataSource = self;
или перетащить IB из вашего TableView в владельца файла (это ваш контроллер контроля, который должен реализовать протокол UITableViewDataSource
)
В протоколе UITableViewDataSource
есть два метода, которые реализует ваш файл данных :
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
и
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
Если u не будет реализовывать эти методы, u получит предупреждения компилятора.
У вас может быть больше контроля над тем, как будет выглядеть tableView, если вы реализуете протокол UITableViewDelegate
- например, высоту, выбор столбца/верхнего колонтитула/столбца, выбор и многое другое...
Из документов Apple UITableView:
UITableView переопределяет метод layoutSubviews UIView, чтобы он вызывает reloadData только при создании нового экземпляра UITableView или когда вы назначаете новый источник данных. Перезагрузка просмотра таблицы очищается текущее состояние, включая текущий выбор. Однако, если вы явным образом вызываю reloadData, он очищает это состояние и любые последующие прямой или косвенный вызов layoutSubviews не вызывает перезагрузку.
ReloadData вызывается, когда создается tableView или когда вы назначаете новый источник данных (или когда вы это явно называете).
Это когда tableView должен знать, что отображать (сколько разделов?, Сколько строк?, и какая ячейка отображается?). Так вот, когда вызывается метод numberOfRowsInSextion
.
Ответ 2
Несколько советов по этой теме помогли мне создать это. Я собираюсь предложить еще несколько полных файлов кода, чтобы помочь другим:
Шаг 1. Перетащите свой UITableView на контроллер просмотра либо в раскадровки, либо в XIB. В моем примере я использую рассказ.
Шаг 2. Откройте ваш ViewController (в моем случае его просто DefaultViewController) и добавьте два делегата для UITableView: UITableViewDelegate и UITableViewDataSource. Также добавьте простой источник данных для населения и UITableView IBOutlet.
DefaultViewController.h
#import <UIKit/UIKit.h>
@interface DetailViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
@property (strong, nonatomic) IBOutlet UITableView *tableView;
@property (strong, nonatomic) NSMutableArray *newsArray;
@end
Шаг 3. Откройте файл реализации (DefaultViewController.m) и добавьте следующее:
#import "DetailViewController.h"
@interface DetailViewController ()
- (void)configureView;
@end
@implementation DetailViewController
@synthesize newsArray;
@synthesize tableView;
#pragma mark - Managing the detail item
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self configureView];
}
- (void)configureView
{
// Update the user interface for the detail item.
self.newsArray = [[NSMutableArray alloc] initWithObjects:@"Hello World",@"Goodbye World", nil];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark UITableViewDelegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// typically you need know which item the user has selected.
// this method allows you to keep track of the selection
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView
editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewCellEditingStyleDelete;
}
// This will tell your UITableView how many rows you wish to have in each section.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.newsArray count];
}
// This will tell your UITableView what data to put in which cells in your table.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifer = @"CellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifer];
// Using a cell identifier will allow your app to reuse cells as they come and go from the screen.
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifer];
}
// Deciding which data to put into this particular cell.
// If it the first row, the data input will be "Data1" from the array.
NSUInteger row = [indexPath row];
cell.textLabel.text = [self.newsArray objectAtIndex:row];
return cell;
}
@end
Шаг 4. Перейдите на свои раскадровки или XIB и выберите свой UITableView и перетащите выходные данные datasource и делегировать на свой DefaultViewController, чтобы связать их, Также вам нужно подключить Referencing Outlet для UITableView к вашему объекту IBOutlet tableView, созданному в вашем файле заголовка.
Как только это будет завершено, вы сможете запустить его, и образцы данных будут на месте.
Я надеюсь, что это вместе с другими советами в этом потоке поможет другим настроить UITableView с нуля на ViewController.
Ответ 3
Как сказал Эяль, вы не должны создавать UITableView программно и в Interface Builder. Вместо этого гораздо проще просто создать его в Interface Builder и назначить ему полномочия делегирования и datasource для File Owner в IB.
Как только вы это сделали, вам не нужно создавать программно, и нет необходимости в @property для просмотра таблицы.
Вместо этого вы могли бы иметь, что ваши файлы классов UIViewController выглядят следующим образом:
// YourViewController.h
#import <UIKit/UIKit.h>
@interface YourViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
@property (strong, nonatomic) NSArray *yourData;
@end
Где NSArray будет содержать ваши данные, которые вы будете вводить в таблицу программно. Вы можете использовать другие классы данных также как NSDictionary в зависимости от того, какие данные у вас есть и как вы хотите, чтобы он сидел в таблице.
// YourViewController.m
#import "YourViewController.h"
@implementation YourViewController
@synthesize yourData;
- (void)viewDidLoad
{
[super viewDidLoad];
// Here you are creating some data to go in your table by inputting it as an array.
// I just used some basic strings as an example.
NSArray *array = [[NSArray alloc] initWithObjects:@"Data1", @"Data2", @"Data3", nil];
// Copying the array you just created to your data array for use in your table.
self.yourData = array;
}
- (void)viewDidUnload
{
[super viewDidUnload];
self.yourData = nil;
}
#pragma mark Table View Data Source Methods
// This will tell your UITableView how many rows you wish to have in each section.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.yourData count];
}
// This will tell your UITableView what data to put in which cells in your table.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifer = @"CellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifer];
// Using a cell identifier will allow your app to reuse cells as they come and go from the screen.
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifer];
}
// Deciding which data to put into this particular cell.
// If it the first row, the data input will be "Data1" from the array.
NSUInteger row = [indexPath row];
cell.textLabel.text = [yourData objectAtIndex:row];
return cell;
}
@end
Это должно просто создать простой UITableView с тремя вводами данных, которые вы ввели программно.
Если у вас есть какие-либо проблемы или вопросы, просто отправьте комментарий.:)
Надеюсь, что это поможет.