Storyboards Tutorial 04
设计好后运行发现没有任何变化,是空白的。这是因为你的tableview相关的delegate方法还在。所以首先要屏蔽或者删除在PlayerDetailsViewController.m 如下的操作
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
#warning Potentially incomplete method implementation.
// Return the number of sections.
return 0;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
#warning Incomplete method implementation.
// Return the number of rows in the section.
return 0;
}
然后再次运行正常了!
但是你会发现因为之前你拖拉textfield的时候有margin,会出现用户点击边缘一点的地方,keyboard不会出现。这就会误导用户以为有问题。所以需要添加如下的方法,目的就是当用户点击第一个section时候就激活nametextfield。
把cell的属性Selection Style 设置为none,否则用户点击这个textfield的时候还会出现高亮的效果。
The Add Player Screen at Work
当用户选择完成后,需要新创建一个Player对象来保存。PlayerDetailsViewController.m中
#import "Player.h"
- (IBAction)done:(id)sender
{
Player *player = [[Player alloc] init];
player.name = self.nameTextField.text;
player.game = @"Chess";
player.rating = 1;
[self.delegate playerDetailsViewController:self didAddPlayer:player];
}
PlayerDetailsViewController.h中
@class Player;
@protocol PlayerDetailsViewControllerDelegate <NSObject>
- (void)playerDetailsViewControllerDidCancel:(PlayerDetailsViewController *)controller;
- (void)playerDetailsViewController:(PlayerDetailsViewController *)controller didAddPlayer:(Player *)player;
@end
PlayersViewController.m中
- (void)playerDetailsViewController:(PlayerDetailsViewController *)controller didAddPlayer:(Player *)player
{
[self.players addObject:player];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:([self.players count] - 1) inSection:0];
[self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
[self dismissViewControllerAnimated:YES completion:nil];
}
这样每次选择完成就会新插入一条记录,还有动画效果。
注意: storybord不会实例化所有的view controllers,只会实例化初始view controller。其他的view controller直到你segue到他们的时候才会实例化。当你关闭这些view controllers后他们就马上销毁了。所以只有当前激活可用的view controller会保留在内存中。
你可以使用如下的代码测试一个view controller的周期
注意: static cells只能嵌入到UITableViewController
中使用。尽管程序会允许你将这个static cells嵌入到UIViewController
中的一个table view对象中去。当运行时就会保存了。
xcode 甚至会在你编译中就报错,“Illegal Configuration: Static table views are only valid when embedded in UITableViewController instances”. Prototype cells类型的cells却是只有在一个常用的UIViewController嵌入的table view中正常使用。
The Game Picker Screen
拖拉一个新的uitable view controller,然后使用ctrl + drag的方式连接到上一个game cell,segue 选择push 。然欧segue 的identifier设置为PickGame。在新建的table view中双击navigation bar将显示修改为Choose Game.将cell的类型修改为Basic。设置重用标识符号GameCell。
创建新的文件GamePickerViewController继承自UITableViewController.并且将uitableview的class设置为GamePickerViewController
。
GamePickerViewController.m:中
然后添加新的代理来传送数据
在GamePickerViewController.h中
在GamePickerViewController.m中添加
PlayerDetailsViewController.h中
#import "GamePickerViewController.h"
@interface PlayerDetailsViewController : UITableViewController <GamePickerViewControllerDelegate>
PlayerDetailsViewController.m中
@implementation PlayerDetailsViewController
{
NSString *_game;
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
if ((self = [super initWithCoder:aDecoder])) {
NSLog(@"init PlayerDetailsViewController");
_game = @"Chess";
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.detailLabel.text = _game;
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:@"PickGame"]) {
GamePickerViewController *gamePickerViewController = segue.destinationViewController;
gamePickerViewController.delegate = self;
gamePickerViewController.game = _game;
}
}
- (void)gamePickerViewController:(GamePickerViewController *)controller didSelectGame:(NSString *)game
{
_game = game;
self.detailLabel.text = _game;
[self.navigationController popViewControllerAnimated:YES];
}
- (IBAction)done:(id)sender
{
Player *player = [[Player alloc] init];
player.name = self.nameTextField.text;
player.game = _game; // only this line is changed
player.rating = 1;
[self.delegate playerDetailsViewController:self didAddPlayer:player];
}