XCode TableViewController 详见 Objective-C
XCode TableViewController to detail in Objective-C
我有一个带有 4 个选项卡的 TabBarController,其中 3 个是 table 视图。我试图为每个 table 视图单元格添加详细信息,但我认为情节提要效率不高,因为我有 50 多个详细信息页面。我对所有这一切都很陌生,并且我试图找出如何 link 每个选项卡的详细信息几个小时。我的 table 视图从第二个视图控制器开始。
这里是 SecondViewController.m:
#import "SecondViewController.h"
@implementation SecondViewController
{
NSArray *tableData;
}
@synthesize tableData;
#pragma mark - View lifecycle
- (void)viewDidLoad
{
tableData = [NSArray arrayWithObjects:@"Carter", @"Greene", @"Hancock", @"Hawkins", @"Johnson", @"Sullivan", @"Unicoi", @"Washington", nil];
[super viewDidLoad];
}
#pragma mark - TableView Data Source methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection: (NSInteger)section
{
return [tableData count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyCell"];
if (cell == nil)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"MyCell"];
}
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.textLabel.text = [tableData objectAtIndex:indexPath.row];
return cell;
}
@end
这里是SecondViewController.h:
#import <UIKit/UIKit.h>
@interface SecondViewController : UIViewController <UITableViewDelegate,
UITableViewDataSource>
@property(nonatomic, retain) NSArray *tableData;
@end
如果这有帮助,这是我的故事板。
如果有人可以帮助我以最轻松的方式向每个 table 视图单元格单独添加详细信息,我将不胜感激。谢谢!
如果使用故事板,过程相当简单。
首先,我建议将原型 "table view cell" 拖到您的 table 视图中。然后,您可以 control- 从该原型单元格拖动到目标场景,以在单元格和下一个场景之间添加转场:
确保 select 该原型单元并设置其故事板标识符(我使用 "Cell")。您将需要引用该故事板标识符,如下面的代码示例所示。我还在 IB 的那个单元格原型中配置了外观相关的东西(比如披露指示器),所以我不必担心在代码中这样做,我可以看到 UI 在 IB 中的样子。
现在您可以转到 table 视图控制器并 (a) 简化 cellForRowAtIndexPath
(因为在使用单元格原型时不需要有关 if (cell == nil) ...
的逻辑);还要实现一个 prepareForSegue
将数据传递到目标场景:
// SecondViewController.m
#import "SecondViewController.h"
#import "DetailsViewController.h"
@interface SecondViewController ()
@property (nonatomic, strong) NSArray *tableData;
@end
@implementation SecondViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.tableData = @[@"Carter", @"Greene", @"Hancock", @"Hawkins", @"Johnson", @"Sullivan", @"Unicoi", @"Washington"];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.destinationViewController isKindOfClass:[DetailsViewController class]]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
NSString *name = self.tableData[indexPath.row];
[(DetailsViewController *)segue.destinationViewController setName:name];
}
}
- (IBAction)unwindToTableView:(UIStoryboardSegue *)segue {
// this is intentionally blank; but needed if we want to unwind back here
}
#pragma mark - Table view data source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.tableData.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
cell.textLabel.text = self.tableData[indexPath.row];
return cell;
}
@end
显然,这假设您创建了一个 DetailsViewController
并将其指定为目标场景的基础 class,然后为要传递给该目标场景的任何值创建属性:
// DetailsViewController.h
#import <UIKit/UIKit.h>
@interface DetailsViewController : UIViewController
@property (nonatomic, copy) NSString *name;
@end
然后此目标场景将采用传递给它的 name
值并填写 UILabel
:
// DetailsViewController.m
#import "DetailsViewController.h"
@interface DetailsViewController ()
@property (weak, nonatomic) IBOutlet UILabel *nameLabel;
@end
@implementation DetailsViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.nameLabel.text = self.name;
}
@end
坦率地说,毫无疑问,任何 UITableView
教程都会更清楚地描述这个过程,包括对 "cell prototypes" 的讨论(您的代码示例表明您使用的是早于单元原型的旧教程)。
我认为代码和故事板的关系如下:
- 代码实现应用程序的功能。
- Storyboard包含很多场景,这些场景实现了用户界面,包括数据呈现、数据输入、数据输出。
- 代码从这些场景中读取数据,并将结果输出到场景中。
- 代码是内部逻辑功能实体和用户界面呈现的故事板。
我有一个带有 4 个选项卡的 TabBarController,其中 3 个是 table 视图。我试图为每个 table 视图单元格添加详细信息,但我认为情节提要效率不高,因为我有 50 多个详细信息页面。我对所有这一切都很陌生,并且我试图找出如何 link 每个选项卡的详细信息几个小时。我的 table 视图从第二个视图控制器开始。 这里是 SecondViewController.m:
#import "SecondViewController.h"
@implementation SecondViewController
{
NSArray *tableData;
}
@synthesize tableData;
#pragma mark - View lifecycle
- (void)viewDidLoad
{
tableData = [NSArray arrayWithObjects:@"Carter", @"Greene", @"Hancock", @"Hawkins", @"Johnson", @"Sullivan", @"Unicoi", @"Washington", nil];
[super viewDidLoad];
}
#pragma mark - TableView Data Source methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection: (NSInteger)section
{
return [tableData count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyCell"];
if (cell == nil)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"MyCell"];
}
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.textLabel.text = [tableData objectAtIndex:indexPath.row];
return cell;
}
@end
这里是SecondViewController.h:
#import <UIKit/UIKit.h>
@interface SecondViewController : UIViewController <UITableViewDelegate,
UITableViewDataSource>
@property(nonatomic, retain) NSArray *tableData;
@end
如果这有帮助,这是我的故事板。
如果有人可以帮助我以最轻松的方式向每个 table 视图单元格单独添加详细信息,我将不胜感激。谢谢!
如果使用故事板,过程相当简单。
首先,我建议将原型 "table view cell" 拖到您的 table 视图中。然后,您可以 control- 从该原型单元格拖动到目标场景,以在单元格和下一个场景之间添加转场:
确保 select 该原型单元并设置其故事板标识符(我使用 "Cell")。您将需要引用该故事板标识符,如下面的代码示例所示。我还在 IB 的那个单元格原型中配置了外观相关的东西(比如披露指示器),所以我不必担心在代码中这样做,我可以看到 UI 在 IB 中的样子。
现在您可以转到 table 视图控制器并 (a) 简化 cellForRowAtIndexPath
(因为在使用单元格原型时不需要有关 if (cell == nil) ...
的逻辑);还要实现一个 prepareForSegue
将数据传递到目标场景:
// SecondViewController.m
#import "SecondViewController.h"
#import "DetailsViewController.h"
@interface SecondViewController ()
@property (nonatomic, strong) NSArray *tableData;
@end
@implementation SecondViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.tableData = @[@"Carter", @"Greene", @"Hancock", @"Hawkins", @"Johnson", @"Sullivan", @"Unicoi", @"Washington"];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.destinationViewController isKindOfClass:[DetailsViewController class]]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
NSString *name = self.tableData[indexPath.row];
[(DetailsViewController *)segue.destinationViewController setName:name];
}
}
- (IBAction)unwindToTableView:(UIStoryboardSegue *)segue {
// this is intentionally blank; but needed if we want to unwind back here
}
#pragma mark - Table view data source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.tableData.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
cell.textLabel.text = self.tableData[indexPath.row];
return cell;
}
@end
显然,这假设您创建了一个 DetailsViewController
并将其指定为目标场景的基础 class,然后为要传递给该目标场景的任何值创建属性:
// DetailsViewController.h
#import <UIKit/UIKit.h>
@interface DetailsViewController : UIViewController
@property (nonatomic, copy) NSString *name;
@end
然后此目标场景将采用传递给它的 name
值并填写 UILabel
:
// DetailsViewController.m
#import "DetailsViewController.h"
@interface DetailsViewController ()
@property (weak, nonatomic) IBOutlet UILabel *nameLabel;
@end
@implementation DetailsViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.nameLabel.text = self.name;
}
@end
坦率地说,毫无疑问,任何 UITableView
教程都会更清楚地描述这个过程,包括对 "cell prototypes" 的讨论(您的代码示例表明您使用的是早于单元原型的旧教程)。
我认为代码和故事板的关系如下:
- 代码实现应用程序的功能。
- Storyboard包含很多场景,这些场景实现了用户界面,包括数据呈现、数据输入、数据输出。
- 代码从这些场景中读取数据,并将结果输出到场景中。
- 代码是内部逻辑功能实体和用户界面呈现的故事板。