转载自:
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“进来:
3 点击“Tab Bar Controller” 在“Attributes Inspector”中选择“Is Initial View Controller”:
然后可以看到“Tab Bar Controller” 的右边多了一个箭头
4 删除上边的“ View Controllers - Item 1”,托一个“Table View Controller“进来
5 点击“Table View Controller“,然后菜单栏选择Editor->Embed In->Navigation Controller,当然也可以从“Object Library”托一个“Navigation Controller”进来,功能一样:
6 重建“Table View Controller“到“Navigation Controller”的关系
7 接下来我们做一些调整
7.1 首先到最右边的“Table View“,点击头部修改名字为”Player“
7.2修改Tab bar的名称Item1为”Players“,Item2为”Gestures“
8 解决错误,这时我们会接受到这样一个提醒
解决方法为Style选择为”Subtitle“,Identifier为”PlayerCell“
之后错误消失
9 到此为止我们完成了Storyboard的大部分工作,下次会进行编码工作。如果以上没有错误,目前的结果应该是这样的:
二、
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