如何在 .xib 文件上创建的 UIViewController 中设置 UITableView
Posted
技术标签:
【中文标题】如何在 .xib 文件上创建的 UIViewController 中设置 UITableView【英文标题】:How to set up UITableView within a UIViewController created on a .xib file 【发布时间】:2012-07-13 06:57:23 【问题描述】:我有这样的课:
@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】:这个线程上的几个技巧帮助我创建了这个。我将提供一些更完整的代码文件以帮助其他人:
步骤 1. 将 UITableView 拖到 Storyboard 或 XIB 中的 View Controller 上。在我的示例中,我使用的是故事板。
第 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 步:转到您的 Storyboard 或 XIB 并选择您的 UITableView 并将 datasource 和 delegate 出口拖到您的 DefaultViewController 上以将它们连接起来.您还需要将 UITableView 的 Reference Outlet 连接到您在头文件中创建的 IBOutlet tableView 对象。
完成后,您应该能够运行它,并且示例数据将就位。
我希望这与该线程上的其他技巧一起能够帮助其他人在 ViewController 上从头开始设置 UITableView。
【讨论】:
【参考方案2】:如果您在 IB 中配置了 tableView,您不应该也以编程方式创建一个,您应该创建 @property (nonatomic, retain) IBOutlet UITableView *tableView;
并将其连接到您在 IB 中配置的 tableView。
尝试在tableView的- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
下设置断点
委托方法,看看这个方法是否被调用。
来自 Apple UITableView 文档:
UITableView 对象必须具有充当数据源的对象 以及充当委托的对象;通常这些对象是 应用程序委托,或者更常见的是自定义 UITableViewController 对象。数据源必须采用 UITableViewDataSource 协议和委托必须采用 UITableViewDelegate 协议。数据源提供信息 UITableView 需要建表和管理数据模型 当插入、删除或重新排序表的行时。代表 提供表格使用的单元格并执行其他任务,例如 管理附件视图和选择。
如您所见,如果您没有为 tableView 设置数据源,tableView 将不知道如何显示以及显示什么,所以什么都不会发生。
您可以通过调用 tableView.dataSource = self;
或在 IB 中从您的 tableView 拖动到文件所有者(即您的 viewController 必须实现 UITableViewDataSource
协议)来设置一个
UITableViewDataSource
协议中有两种方法是您的数据源必须实现的:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
和
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
如果您不实施这些方法,您将收到编译器警告。
如果您实现UITableViewDelegate
协议,您可以更好地控制 tableView 的外观 - 例如行/页眉/页脚高度、选择等等......
来自 Apple UITableView 文档:
UITableView 覆盖 UIView 的 layoutSubviews 方法,以便它 仅当您创建 UITableView 的新实例时调用 reloadData 或 当您分配新的数据源时。重新加载表格视图清除 当前状态,包括当前选择。但是,如果你 显式调用 reloadData,它会清除此状态和任何后续 直接或间接调用 layoutSubviews 不会触发重新加载。
在创建 tableView 或分配新数据源时(或者当您明确调用它时......)时会调用 ReloadData。
这是 tableView 需要知道要显示什么的时候(多少节?,多少行?,以及要显示哪个单元格?) - 所以这是 numberOfRowsInSextion
方法调用的时候。
【讨论】:
谢谢!这有帮助!我只是注释掉了创建和显示行。何时调用 numberOfRowsInSextion 方法?当你第一次调用 tableView??因为如果我不添加“tableView.dataSource = self;”和“tableView.delegate = self;”行不显示任何内容。 这是一个很好的答案,帮助很大!谢谢!这必须是我读过的关于 tableview 以及它们需要工作的最佳解释之一!做得好!再次感谢 +1,如果可以的话 +10 :)【参考方案3】:就像 Eyal 所说,您不应该以编程方式在 Interface Builder 中创建 UITableView。相反,只需在 Interface Builder 中创建一个并将其委托和数据源属性分配给 IB 中的 File's Owner 会容易得多。
完成此操作后,您无需以编程方式创建一个,也无需为 tableview 使用 @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,其中包含您以编程方式输入的三个数据条目。
如果您有任何问题或疑问,请发表评论。 :)
希望这会有所帮助。
【讨论】:
这段代码中究竟在哪里调用了“numberOfRowsInSection”?因为如果我执行类似的代码并在这个方法中添加一个 NSLog 语句,它永远不会被执行。 在填充表格视图时调用它。您需要确保 .h 文件具有以上是关于如何在 .xib 文件上创建的 UIViewController 中设置 UITableView的主要内容,如果未能解决你的问题,请参考以下文章
如何在多个 .xib 文件之间执行展开转场(不使用情节提要)
如何通过同一个 ViewController(在故事板上创建)在两个视图(在 xib 上创建)之间切换?