如何在 .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 添加两个代理:UITableViewDelegateUITableViewDataSource。还为人口和 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 并将 datasourcedelegate 出口拖到您的 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 文件具有 位,并且界面构建器中的 UITableView 将其数据源和委托设置为文件所有者。否则它根本不会被调用。

以上是关于如何在 .xib 文件上创建的 UIViewController 中设置 UITableView的主要内容,如果未能解决你的问题,请参考以下文章

iPhone - 在滑动手势上加载 .xib 文件

如何在多个 .xib 文件之间执行展开转场(不使用情节提要)

如何通过同一个 ViewController(在故事板上创建)在两个视图(在 xib 上创建)之间切换?

如何在从 xib 获得的视图上设置 IBAction

如何使用两个 xib 文件创建一个 Objective-C 类(一个用于 iPhone,另一个用于 iPad)

我正在使用 xcode 9。如何在里面创建带有 xib 文件的框架?