转载自:

http://www.cnblogs.com/buro79xxd/archive/2012/03/07/2383725.html

http://www.1000phone.net/thread-7712-1-1.html

http://www.1000phone.net/thread-7713-1-1.html

http://www.1000phone.net/thread-7714-1-1.html

不知道为什么原来的链接给的源码运行不了。我照着教程自己敲了一遍代码,然后做了一点点的改动。大致达到教程中说的效果。

一、

1 首先建立一个项目,随便起一个名字。

2 点击“MainStoryboard.storyboard”,从“Object Library”托一个”Tab Bar Controller“进来


屏幕快照 2012-03-07 下午1.54.12.png

3 点击“Tab Bar Controller” 在“Attributes Inspector”中选择“Is Initial View Controller”:

屏幕快照 2012-03-07 下午1.55.59.png

然后可以看到Tab Bar Controller” 的右边多了一个箭头

屏幕快照 2012-03-07 下午1.55.51.png

4 删除上边的“ View Controllers - Item 1”,托一个“Table View Controller“进来


屏幕快照 2012-03-07 下午2.05.51.png

5 点击“Table View Controller“,然后菜单栏选择Editor->Embed In->Navigation Controller,当然也可以从“Object Library”托一个“Navigation Controller”进来,功能一样:

屏幕快照 2012-03-07 下午2.06.28.png

6 重建“Table View Controller“到Navigation Controller”的关系

屏幕快照 2012-03-07 下午2.10.17.png


屏幕快照 2012-03-07 下午2.09.57.png

7 接下来我们做一些调整

7.1 首先到最右边的“Table View“,点击头部修改名字为”Player“
屏幕快照 2012-03-07 下午2.16.11.png

7.2修改Tab bar的名称Item1为”Players“,Item2为”Gestures“

屏幕快照 2012-03-07 下午2.21.51.png

8 解决错误,这时我们会接受到这样一个提醒


屏幕快照 2012-03-07 下午4.09.33.png

解决方法为Style选择为”Subtitle“,Identifier为”PlayerCell“


屏幕快照 2012-03-07 下午2.30.03.png

之后错误消失

9 到此为止我们完成了Storyboard的大部分工作,下次会进行编码工作。如果以上没有错误,目前的结果应该是这样的:

屏幕快照 2012-03-07 下午4.11.04.png

二、

1 建立文件“ PlayersViewController”记得选择”UITableViewController

 

2 选择“Table View Controller”设置“Identity Inspector”的Class为“PlayersViewController”

 

编辑“ PlayersViewController.h”,建立一个可修改的数组,这个将是我们今后存储Player数据的地方

#import <Foundation/Foundation.h>

@interface PlayersViewController : UITableViewController

@property (nonatomic, strong) NSMutableArray *players;

- (UIImage *)imageForRating:(int)rating;
@end

3 先放一放,建立一个基于“Objective-C class template”的Player文件,他的Subclass是“NSObject”

然后编辑“Player.h”和“Player.m”

//"Player.h"

#import <Foundation/Foundation.h>

@interface Player : NSObject

@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *game;
@property (nonatomic, assign) int rating;
@end

//"Player.m"

#import "Player.h"

@implementation Player
@synthesize name,game,rating;

@end

4 接下来在 PlayersViewController.m中作些动作

 

#pragma mark - view lifecycle
- (void)viewDidLoad
{
    [super viewDidLoad];
    self.players = [NSMutableArray arrayWithCapacity:20];
    
    Player *player = [[Player alloc] init];
    player.name = @"xxd";
    player.game = @"游泳";
    player.rating = 4;
    [players addObject:player];
    
    player = [[Player alloc] init];
    player.name = @"张三";
    player.game = @"足球";
    player.rating = 5;
    [players addObject:player];
    
    player = [[Player alloc] init];
    player.name = @"李四";
    player.game = @"篮球";
    player.rating = 2;
    [players addObject:player];
}

 

 

 

5 修改item1下的数据显示,修改“PlayersViewController.m”

#import "PlayersViewController.h"
#import "Player.h"

@implementation PlayersViewController
@synthesize players;


#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableViewUITableView *)tableView
{
  return 1;
}

- (NSInteger)tableViewUITableView *)tableView numberOfRowsInSectionNSInteger)section
{
  return [self.players count];
}

- (UITableViewCell *)tableViewUITableView *)tableView cellForRowAtIndexPathNSIndexPath *)indexPath
{
  UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier"PlayerCell"];
  Player *player = [self.players objectAtIndex:indexPath.row];
  cell.textLabel.text = player.game;
  cell.detailTextLabel.text = player.game;
  return cell;
}

目前显示结果应该是这样的

 

6 下面来看看我们能在“Prototype Cells”中做些什么

设置Table View高为55

托一个UiImageView到Cell上,然后设置Cell行高;同理,再拖进两个Label,像subtitle格式的cell那样放置,并修改detailLabel的字体大小为14,字体颜色为Gray。

打开MainStoryBoard.storyboard,选中table view cell中的image view,在大小检查器中修改Autosizing属性,是它能够跟随上级view的边缘。 
 
为labels设置同样的属性。 

设置出右边的箭头

设置ImageView的宽度

最后测试别较好的大小是:x = 199,Y = 13, Width = 81, Height = 28

然后我们配置Cell,基于“Objective-C class template”建立一个PlayerCell文件,他的Subclass是“NSObject”

//" PlayerCell.h"

#import <Foundation/Foundation.h>

@interface PlayerCell : UITableViewCell

@property (nonatomic, strong) IBOutlet UILabel *nameLabel;
@property (nonatomic, strong) IBOutlet UILabel *gameLabel;
@property (nonatomic, strong) IBOutlet UIImageView *ratingImageView;
@end

//"PlayerCell.m"

#import "PlayerCell.h"

@implementation PlayerCell

@synthesize nameLabel,gameLabel;
@synthesize ratingImageView;

@end

 

点击MainStoryboard.storyboard,点击 prototype cell修改他的Class为“ PlayerCell”

将两个Label和imageView分别和nameLabel和gameLabel,ratingImageView连接。

然后在“PlayersViewController.m”中添加

#import "PlayerCell.h"

在“PlayersViewController.m”中修改

- (UITableViewCell *)tableViewUITableView *)tableView cellForRowAtIndexPathNSIndexPath *)indexPath
{
  PlayerCell *cell =(PlayerCell *)[tableView dequeueReusableCellWithIdentifier"PlayerCell"];
  Player *player =[self.players objectAtIndex:indexPath.row];
  cell.nameLabel.text = player.name;
  cell.gameLabel.text = player.game;
  cell.ratingImageView.image =[self imageForRating:player.rating];
  return cell;
}

随后在“PlayersViewController.h”中添加

-(UIImage *)imageForRatingint)rating;

在“PlayersViewController.h”中添加

 

-(UIImage *)imageForRatingint)rating
{
  switch(rating)
  {
    case1:return[UIImage imageNamed"1StarSmall.png"];
    case2:return[UIImage imageNamed"2StarsSmall.png"];
    case3:return[UIImage imageNamed"3StarsSmall.png"];
    case4:return[UIImage imageNamed"4StarsSmall.png"];
    case5:return[UIImage imageNamed"5StarsSmall.png"];
  }
  return nil;
}

运行看看什么模样

7 增加删除功能,在“ PlayersViewController.m”添加下边代码

用手指轻扫一行单元格,会出现一个删除键

-(void)tableViewUITableView *)tableView commitEditingStyleUITableViewCellEditingStyle)editingStyle forRowAtIndexPathNSIndexPath*)indexPath
{
  if(editingStyle == UITableViewCellEditingStyleDelete)
  {
    [self.players removeObjectAtIndex:indexPath.row];
    [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]withRowAnimation:UITableViewRowAnimationFade];
  }
}

三、

1 首先我们在PlayerDetailViewController对应的table view controller 的navigation Bar上添加一个Bar Button Item,将其类型改为 Add

2 随后托一个“Table View Controller”,然后配置它

然后embed in Navigation Controller

 

从左上角的加号按钮 Control+Drog 到新的“Navigation Controller”上然后选择Modal

 

把这个Segue的Identifier设置成“AddPlayer”

3 建立新的“PlayerDetailsViewController”subclass是”UITableViewController“

 

然后绑定到”Table View Controller“上去,增加两个”Bar Button Items“,然后链接Done 和 Cancel 的 outlet到PlayerDetailViewController.h上

 

4 现在用Delegate写按钮

修改“PlayerDetailsViewController.h”

#import <UIKit/UIKit.h>

@class Player;
@class PlayerDetailViewController;

@protocol PlayerDetailViewControllerDelegate
        
- (void)playerDetailViewController:(PlayerDetailViewController *)detailViewController didAddPlayer:(Player *)player;
- (void)playerDetailViewControllerDidCancel:(PlayerDetailViewController *)controller;

@end

@interface PlayerDetailViewController : UITableViewController

@property (nonatomic, weak) id delegate;
@property (strong, nonatomic) IBOutlet UITextField *nameTextField;
@property (strong, nonatomic) IBOutlet UILabel *detailLabel;

- (IBAction)done:(id)sender;
- (IBAction)cancel:(id)sender;

@end

 

看看上边都干了些什么

1 Class

2 建立Procotol PlayerDetailsViewControllerDelegate

3 创建delegate

在“PlayerDetailsViewController.m”中写按钮事件

@synthesize delegate;
-(IBAction)cancel(id)sender
{
[self.delegate playerDetailsViewControllerDidCancel:self];
}

-(IBAction)done(id)sender
{
[self.delegate playerDetailsViewControllerDidDone:self];
}

 

然后在“PlayerViewController.h”添加

#import "PlayerDetailsViewController.h"

@interface PlayersViewController : UITableViewController

 

在“PlayerViewController.m”添加

 

#import "PlayerDetailsViewController.h"

@interface PlayersViewController : UITableViewController

注意这里的“ [self dismissViewControllerAnimated:YES completion:nil];”是iOS 5里用来代替“ dismissModalViewControllerAnimated”的。

在“PlayerViewController.m”写AddPlayer Segue

- (void)playerDetailsViewControllerDidCancel(PlayerDetailsViewController *)controller
{
[self dismissViewControllerAnimated:YES completion:nil];
}

- (void)playerDetailsViewControllerDidDone(PlayerDetailsViewController *)controller
{
[self dismissViewControllerAnimated:YES completion:nil];
}

 

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.identifier isEqualToString:@"AddPlayer"]) {
        UINavigationController *nvc = [segue destinationViewController];
        PlayerDetailViewController *pdvc = [nvc.viewControllers objectAtIndex:0];
        pdvc.delegate = self;
    }
}
@end

 

如果不加入上边这段Segue代码,那么AddPlayer页是可以打开的,但是无法通过点击按钮关闭的。

5 点击“MainStoryboard.storyboard”编辑“Add Player”页

将tableview的section增加为2,每个section的row为1,向section 1的cell里边拖一个“Text Field”然后去掉边框,把“Text Field”拖到cell一样大小,将其header的title改为"Name",section2 的header的title改为”Game",拖两个label分别放在左右两边,左边的为“类别", 右边的为“Detail",将此cell的accessory button改为disclosure indicator。

 

拖动name的“Text Field”和Game的Label到“PlayerDetailViewController.h”,然后分别填写“nameTextField”和detailLabel,选择Connect,之后xcode会建立一条语句,也同时会在“PlayerDetailViewController.m”中建立synthesized和viewDidUnload,非常方便。在

 

@property (strong, nonatomic) IBOutlet UITextField *nameTextField;
@property (strong, nonatomic) IBOutlet UILabel *detailLabel;

由于table view controller 使用了static cells所以就不需要数据源(data source) ,那么我们可以把“PlayerDetailViewController.h”内从“#pragma mark - Table view data source”到 “#pragma mark - Table view delegate”的代码都删除掉。

6 然后在“PlayerDetailViewController.h”加入

-(void)tableViewUITableView *)tableView didSelectRowAtIndexPathNSIndexPath*)indexPath
{
  if(indexPath.section ==0)
  [self.nameTextField becomeFirstResponder];
}

 

- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.section == 1) {
        GamePickerViewController *gpvc = [[GamePickerViewController alloc] init];
        gpvc.delegate = self;
        gpvc.game = game;
        [self.navigationController pushViewController:gpvc animated:YES];
    }
}

 

以上代码很简单就是当我们进入”添加用户“页面,点击第一个文字输入框启动” nameTextField“然后弹出键盘。

7 现在我们要修改这个”Done“按钮的功能,刚才我们把它定义为和cacel,现在我们真正的赋予它功能,以下一共三步:

首先在PlayerDetailViewController.h”中修改

@class PlayerDetailsViewController;
@class Player;

@protocol PlayerDetailsViewControllerDelegate
- (void)playerDetailsViewControllerDidCancel(PlayerDetailsViewController *)controller;
- (void)playerDetailsViewController(PlayerDetailsViewController *)controller didAddPlayerPlayer *)player;
@end

 

然后在PlayerDetailViewController.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];
}

最后我们在“ PlayerViewController.m”中把Done按钮部分替换掉

#pragma mark - PlayerDetailsViewControllerDelegate
- (void)playerDetailsViewControllerDidCancel(PlayerDetailsViewController *)controller
{
  [self dismissViewControllerAnimated:YES completion:nil];
}

-(void)playerDetailsViewController(PlayerDetailsViewController *)controller
didAddPlayerPlayer *)player
{
  [self.players addObject:player];
  NSIndexPath*indexPath =[NSIndexPath indexPathForRow:[self.players count]-1 inSection:0];
  [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                withRowAnimation:UITableViewRowAnimationAutomatic];
  [self dismissViewControllerAnimated:YES completion:nil];
}

 

目前我们完成了,最后我们加入类型的选择就基本上完成了

四、

1 我们来建立最后一个TableViewController,用来控制类别的选择。托一个“Table View Controller”,从类别 Control+Drog 到新的“Navigation Controller”上,设置“Table View Controller”的cell 的 Style为Basic

在PlayerDetailViewController.m中添加以下代码

 

2 建立“ GamePickerViewController”,Class 是 Table View Controller

然后编辑 “GamePickerViewController.h”

#import <UIKit/UIKit.h>

@interface GamePickerViewController : UITableViewController {
  NSArray *games;
}
@end

 

“GamePickerViewController.m”

 

-(void)viewDidLoad
{
  [super viewDidLoad];
  games =[NSArray arrayWithObjects"游泳",@"篮球",@"足球",@"象棋",@"国际象棋",@"Dota",nil];
}
- (void)viewDidUnload
{
  [super viewDidUnload];
  games =nil;
}

-(NSInteger)numberOfSectionsInTableViewUITableView *)tableView
{
  return 1;
}
-(NSInteger)tableViewUITableView *)tableView numberOfRowsInSectionNSInteger)section
{
  return[games count];
}

-(UITableViewCell *)tableViewUITableView *)tableView cellForRowAtIndexPathNSIndexPath*)indexPath
{
  UITableViewCell *cell =[tableView dequeueReusableCellWithIdentifier"GameCell"];
  cell.textLabel.text =[games objectAtIndex:indexPath.row];
  return cell;
}

 

这里别忘了给Cell设置Identifier为“GameCell”

 

3 一切配置都完成了,我们开始写Delegate类似我们在Player View那里做的一样。

3.1 首先在“ GamePickerViewController.m”中修改为:

 

@class GamePickerViewController;

@protocol GamePickerViewControllerDelegate
-(void)gamePickerViewControllerGamePickerViewController *)controller didSelectGameNSString *)game;
@end
@interface GamePickerViewController : UITableViewController
@property (nonatomic,weak) id  delegate;
@property (nonatomic,strong) NSString *game;

@end

3.2 然后在“ GamePickerViewController.m”中添加和修改

@implementation GamePickerViewController
{
  NSArray*games;
  NSUInteger selectedIndex;
}
@synthesize delegate,game;

-(void)viewDidLoad
{
  [super viewDidLoad];
  games =[NSArray arrayWithObjects"游泳",@"篮球",@"足球",@"象棋",@"国际象棋",@"Dota",nil];
  selectedIndex =[games indexOfObject:self.game];
}
-(UITableViewCell *)tableViewUITableView *)tableView cellForRowAtIndexPathNSIndexPath*)indexPath
{
  UITableViewCell *cell =[tableView dequeueReusableCellWithIdentifier"GameCell"];
  cell.textLabel.text =[games objectAtIndex:indexPath.row];
  if(indexPath.row == selectedIndex)
    cell.accessoryType = UITableViewCellAccessoryCheckmark;
  else
    cell.accessoryType = UITableViewCellAccessoryNone;
  return cell;
}
#pragma mark - Table view delegate
-(void)tableViewUITableView *)tableView didSelectRowAtIndexPathNSIndexPath*)indexPath
{
  [tableView deselectRowAtIndexPath:indexPath animated:YES];
  if(selectedIndex != NSNotFound){
  UITableViewCell *cell =[tableView cellForRowAtIndexPath:
  [NSIndexPath indexPathForRow:selectedIndex inSection:0]];
  cell.accessoryType = UITableViewCellAccessoryNone;
  }
  selectedIndex = indexPath.row;
  UITableViewCell *cell =[tableView cellForRowAtIndexPath:indexPath];
  cell.accessoryType = UITableViewCellAccessoryCheckmark;
  NSString *theGame =[games objectAtIndex:indexPath.row];
  [self.delegate gamePickerViewController:self didSelectGame:theGame];
} 

 

3.3 回顾一下

 

3.3.1 可以看出Delegate中唯一的一个方法就是传递选择的类型

 

3.3.2 选择的类型,会在self.game中,那么它会在ViewDidLoad的时候加载

 

3.3.3 我们利用“ selectedIndex”会知道我们选择的类型是在self.game中的哪一个

 

3.3.4 在“cell.textLabel.text =[games objectAtIndex:indexPath.row];”这里我们给Text赋值

 

3.3.5 然后我们到了最后一步,当我们选择一个cell之后我们回退到上一个view并且把值传回去

 

4但是目前它是上边这样的,不能回退,所以最后一步我们就让它把值传回去

 

4.1 回到“PlayerDetailsViewController.h”改为

 

#import "GamePickerViewController.h"

@interface PlayerDetailsViewController : UITableViewController

 

4.2 在 PlayerDetailsViewController.h”中加入Segue部分内容,它是负责把值传递回去的

 

@implementation PlayerDetailsViewController
{
NSString*game;
}

 

4.3 在 PlayerDetailsViewController.h”中修改

 

-(id)initWithCoderNSCoder*)aDecoder
{
if((self =[super initWithCoder:aDecoder]))
{
NSLog(@"init PlayerDetailsViewController");
game =@"国际象棋";
}
return self;
}


- (void)viewDidLoad
{
[super viewDidLoad];
self.detailLabel.text = game;
}
#pragma mark - GamePickerViewControllerDelegate

- (void)gamePickerViewControllerGamePickerViewController *)controller didSelectGameNSString *)theGame
{
game = theGame;
self.detailLabel.text = game;

[self.navigationController popViewControllerAnimated:YES];
}


-(IBAction)doneid)sender
{
Player *player =[[Player alloc] init];
player.name = self.nameTextField.text;
player.game = game;
player.rating =1;
[self.delegate playerDetailsViewController:self didAddPlayer:player];
}

源码下载:StoryBoardSample.rar