SplitViewController的简单使用
最终效果图:


主控制器 BeyondViewController
继承自UISplitViewController<喎�"http://www.2cto.com/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+PC9wPgo8cHJlIGNsYXNzPQ=="brush:java;">// // BeyondViewController.h // 27_SplitViewCtroller // // Created by beyond on 14-8-31. // Copyright (c) 2014年 com.beyond. All rights reserved. // 主控制器,继承自UISplitViewController,左边master控制器是:FoodTypeListCtrl,右边的从控制器是FoodListCtrl #import @interface BeyondViewController : UISplitViewController @end
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
//// BeyondViewController.m// 27_SplitViewCtroller//// Created by beyond on 14-8-31.// Copyright (c) 2014年 com.beyond. All rights reserved.// 主控制器,继承自UISplitViewController,左边master控制器是:FoodTypeListCtrl,右边的从控制器是FoodListCtrl#import "BeyondViewController.h"// 菜系 列表 控制器#import "FoodTypeListController.h"// 菜列表 控制器#import "FoodListController.h"// 菜系 列表 控制器 定义的协议,目的是:点击了菜系 列表 中的某一行时,告诉代理(即菜列表控制器) 要展示哪一种菜系下面的所有菜#import "FoodTypeListCtrlDelegate.h"@interface BeyondViewController () <foodtypelistctrldelegate>@end@implementation BeyondViewController// 重要~~~主控制器充当中间人,先得到FoodTypeListController,并且成为它的代理,得到菜系 列表 的某一行被点击时 对应的菜系对象// 然后再在FoodTypeListController的代理方法中,得到FoodListController,并将菜系 进一步传递给FoodListController- (void)viewDidLoad{ [super viewDidLoad]; // 1.先得到Master控制器,即导航控制器,再从导航控制器中得到 FoodTypeListController,并且成为它的代理 UINavigationController *foodTypeListNav = [self.childViewControllers firstObject]; FoodTypeListController *foodTypeListCtrl = [foodTypeListNav.childViewControllers firstObject]; foodTypeListCtrl.delegate = self; // 让foodListCtrl成为主控制器的代理,仅仅是监听Master控制器的出现和隐藏,并在foodListCtrl的左按钮上显示相应的提示文字(点击该文字可以展开被隐藏的Master控制器) UINavigationController *foodListNav = [self.childViewControllers lastObject]; FoodListController<uisplitviewcontrollerdelegate> *foodListCtrl = [foodListNav.childViewControllers firstObject]; self.delegate = foodListCtrl;}// 2. 然后再在FoodTypeListController的代理方法中,得到FoodListController,并将菜系 进一步传递给FoodListController- (void)foodTypeListController:(FoodTypeListController *)foodTypesVc didSelectedFoodType:(FoodType *)type{ UINavigationController *foodListNavi = [self.childViewControllers lastObject]; FoodListController *foodListCtrl = [foodListNavi.childViewControllers firstObject]; foodListCtrl.foodType = type; [foodListNavi popToRootViewControllerAnimated:YES];}@end</uisplitviewcontrollerdelegate></foodtypelistctrldelegate> |
SplitViewCtrl的Master主控制器,
继承自表格控制器
FoodTypeListController 【菜系列表】及其代理
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
//// FoodTypeListController.h// 27_SplitViewCtroller//// Created by beyond on 14-8-31.// Copyright (c) 2014年 com.beyond. All rights reserved.// SplitViewCtrl的Master主控制器,继承自表格控制器 【菜系列表】#import <uikit uikit.h="">@protocol FoodTypeListCtrlDelegate;@interface FoodTypeListController : UITableViewController// 成员:代理,当点击了某一行时,告诉代理 即点击了哪一种菜系,从而,右边的控制器展示相应的菜名列表@property (weak, nonatomic) id<foodtypelistctrldelegate> delegate;@end</foodtypelistctrldelegate></uikit> |
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
//// FoodTypeListController.m// 27_SplitViewCtroller//// Created by beyond on 14-8-31.// Copyright (c) 2014年 com.beyond. All rights reserved.//#import "FoodTypeListController.h"#import "FoodType.h"#import "FoodTypeListCtrlDelegate.h"@interface FoodTypeListController ()// 成员:数组,保存着从plist中加载的所有的从字典一一转成对象的FoodType@property (strong, nonatomic) NSArray *foodTypesArr;@end@implementation FoodTypeListController// getter访问时才加载,懒加载- (NSArray *)foodTypesArr{ if (_foodTypesArr == nil) { // 经典,一句话将参数所对应的Plist文件中的字典数组,转成 该类的对象数组 _foodTypesArr = [FoodType objArrFromPlistName:@"food_types.plist"]; } return _foodTypesArr;}- (void)viewDidLoad{ [super viewDidLoad]; self.title = @"菜系"; // 默认选择第0行,调用自己的方法,给其传递数据模型 [self.tableView selectRowAtIndexPath:kIndexPathZero animated:YES scrollPosition:UITableViewScrollPositionTop]; // 让第0行,显示选中状态,需配合覆盖掉系统默认的方法:viewWillAppear [self tableView:self.tableView didSelectRowAtIndexPath:kIndexPathZero];}// 取消系统默认的一些 事件,让第0行,显示选中状态- (void)viewWillAppear:(BOOL)animated{ // do nothing...}#pragma mark - 数据源方法// 多少行- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ return self.foodTypesArr.count;}// 每行显示的cell- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ static NSString *ID = @"FoodType"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID]; } // 模型数组中取出对应行的模型 FoodType *type = self.foodTypesArr[indexPath.row]; // 设置独一无二的内容 cell.textLabel.text = type.name; // 返回cell return cell;}#pragma mark - 代理方法- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ // 如果 代理(就是右边的从控制器)需要,才告知 当前选择了哪一个菜系 if ([self.delegate respondsToSelector:@selector(foodTypeListController:didSelectedFoodType:)]) { FoodType *type = self.foodTypesArr[indexPath.row]; [self.delegate foodTypeListController:self didSelectedFoodType:type]; }}@end |
定义好的协议
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
//// FoodTypeListCtrlDelegate.h// 27_SplitViewCtroller//// Created by beyond on 14-8-31.// Copyright (c) 2014年 com.beyond. All rights reserved.//#import <foundation foundation.h="">@class FoodType;@protocol FoodTypeListCtrlDelegate <nsobject>@optional// 当点击了某一行时,告诉代理 即点击了哪一种菜系,从而,右边的控制器展示相应的菜名列表- (void)foodTypeListController:(FoodTypeListController *)ctrl didSelectedFoodType:(FoodType *)foodType;@end</nsobject></foundation> |
FoodListController
SplitViewCtrl的从控制器,继承自表格控制器
展示的是某一菜系下所有的菜【菜的列表】
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
//// FoodListController.h// 27_SplitViewCtroller//// Created by beyond on 14-8-31.// Copyright (c) 2014年 com.beyond. All rights reserved.// SplitViewCtrl的从控制器,继承自表格控制器 某一菜系下所有的【菜的列表】// 点击左边菜系列表控制器中的某一行时,本控制器将展示该菜系下的所有菜#import <uikit uikit.h="">@class FoodType;@interface FoodListController : UITableViewController// 数据源,根据传入的菜系,通过它的idstr,拼凑出新的plist名称,加载,转成Food模型对象数组@property (strong, nonatomic) FoodType *foodType;@end</uikit> |
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
//// FoodListController.m// 27_SplitViewCtroller//// Created by beyond on 14-8-31.// Copyright (c) 2014年 com.beyond. All rights reserved.//#import "FoodListController.h"#import "FoodDetailController.h"#import "Food.h"#import "FoodCell.h"#import "FoodType.h"// 成为UISplitViewControllerDelegate的代理,目的是监听其显示和隐藏方法,从而控制leftBarButtonItem的显示和隐藏@interface FoodListController ()<uisplitviewcontrollerdelegate>@property (strong, nonatomic) NSArray *foodsArr;@end@implementation FoodListController- (void)viewDidLoad{ [super viewDidLoad]; }// 重要~~~拦截setterFoodType方法,设置标题,从对应的Plist加载数据,并转成对象数组,刷新表格- (void)setFoodType:(FoodType *)foodType{ _foodType = foodType; NSString *filename = [NSString stringWithFormat:@"type_%@_foods.plist", foodType.idstr]; // 经典,一句话将参数所对应的Plist文件中的字典数组,转成 该类的对象数组 self.foodsArr = [Food objArrFromPlistName:filename]; self.title = foodType.name; if (self.isViewLoaded) { // 默认让tableView 滚动到第 0 行 [self.tableView scrollToRowAtIndexPath:kIndexPathZero atScrollPosition:UITableViewScrollPositionTop animated:YES]; // 刷新表格 [self.tableView reloadData]; }}#pragma mark - SplitViewCtrl的代理方法// 即将显示 Master主控制器- (void)splitViewController:(UISplitViewController *)svc willShowViewController:(UIViewController *)aViewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem{ self.navigationItem.leftBarButtonItem = nil;}// 即将隐藏 Master主控制器- (void)splitViewController:(UISplitViewController *)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)pc{ barButtonItem.title = @"菜系"; self.navigationItem.leftBarButtonItem = barButtonItem;}#pragma mark - 数据源方法// 多少行- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ return self.foodsArr.count;}// 高度封装了FoodCell,控制器知道得很少- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ FoodCell *cell = [FoodCell cellWithTableView:tableView]; cell.food = self.foodsArr[indexPath.row]; return cell;}#pragma mark - 代理方法// cell 行高- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ return 100;}// 选中某一行- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ // 点击那行 对应的模型 Food *food = self.foodsArr[indexPath.row]; FoodDetailController *detailVc = [[FoodDetailController alloc] init]; // 传递数据模型,内部会拦截 detailVc.food = food; [self.navigationController pushViewController:detailVc animated:YES];}@end</uisplitviewcontrollerdelegate> |
WebView展示某一道 菜 的详情
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
//// FoodDetailController.h// 27_SplitViewCtroller//// Created by beyond on 14-8-31.// Copyright (c) 2014年 com.beyond. All rights reserved.// 点击菜列表控制中的某一行,来到这,显示该道菜的详细信息,直接用webView展示#import <uikit uikit.h="">@class Food;@interface FoodDetailController : UIViewController// 数据源,要显示哪道菜@property (strong, nonatomic) Food *food;@end</uikit> |
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
//// FoodDetailController.m// 27_SplitViewCtroller//// Created by beyond on 14-8-31.// Copyright (c) 2014年 com.beyond. All rights reserved.// 点击一行,来到这,显示该道菜的详细信息,直接用webView展示#import "FoodDetailController.h"#import "Food.h"@interface FoodDetailController ()@property (weak, nonatomic) UIWebView *webView;@end@implementation FoodDetailController// 让weibView就是控制器的view- (void)loadView{ UIWebView *webView = [[UIWebView alloc] init]; // bounds就是屏幕的全部区域,applicationFrame就是app显示的区域,不包含状态栏 webView.frame = [UIScreen mainScreen].applicationFrame; // 随着屏幕的旋转,宽高自动伸缩 webView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; self.view = webView; // 成员变量,记住,目的是 避免强转 self.webView = webView;}- (void)viewDidLoad{ [super viewDidLoad]; // 导航栏标题 self.title = self.food.name; // 重点~~~拼接本地url,注意:如果在沙盒创建真实的文件夹,那么加载文件时,要加上文件夹名 NSString *fileName = [NSString stringWithFormat:@"Html/food/%@.html", self.food.idstr]; NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:fileName withExtension:nil]]; [self.webView loadRequest:request];}@end |
模型Model
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
//// Food.h// 27_SplitViewCtroller//// Created by beyond on 14-8-31.// Copyright (c) 2014年 com.beyond. All rights reserved.// 模型:一种菜肴 Food 对应plist文件里面的一个字典#import <foundation foundation.h="">@interface Food : NSObject// 必须与plist文件中 字典的key 一模一样// id@property (copy, nonatomic) NSString *idstr;// 菜名@property (copy, nonatomic) NSString *name;// 小图标url@property (copy, nonatomic) NSString *imageUrl;// 网页的url@property (copy, nonatomic) NSString *url;// 本道菜预计耗时多长@property (copy, nonatomic) NSString *time;// 制作难度多大@property (copy, nonatomic) NSString *diff;@end</foundation> |
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
//// FoodType.h// 27_SplitViewCtroller//// Created by beyond on 14-8-31.// Copyright (c) 2014年 com.beyond. All rights reserved.// 模型:一种菜系 FoodType 对应plist文件里面的一个字典#import <foundation foundation.h="">@interface FoodType : NSObject// ID@property (copy, nonatomic) NSString *idstr;// 菜系 名称:如粤菜 川菜 家常菜@property (copy, nonatomic) NSString *name;@end</foundation> |
封装的一个Cell View
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
//// FoodCell.h// 27_SplitViewCtroller//// Created by beyond on 14-8-31.// Copyright (c) 2014年 com.beyond. All rights reserved.// 自定义cell,一个cell 展示一个food模型里面的数据,传入tableView实例化cell的目的是封装得最彻底,让控制器作最少的事,知道得最少#import <uikit uikit.h="">@class Food;@interface FoodCell : UITableViewCell// 数据源模型,提供数据给内部的子控件们显示,内部会拦截setter方法@property (strong, nonatomic) Food *food;// 传入tableView实例化cell的目的是封装得最彻底,让控制器作最少的事,知道得最少+ (instancetype)cellWithTableView:(UITableView *)tableView;@end</uikit> |
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
//// FoodCell.m// 27_SplitViewCtroller//// Created by beyond on 14-8-31.// Copyright (c) 2014年 com.beyond. All rights reserved.//#import "FoodCell.h"#import "Food.h"#import "UIImageView+WebCache.h"@interface FoodCell()@property (weak, nonatomic) IBOutlet UIImageView *iconView;@property (weak, nonatomic) IBOutlet UILabel *nameLabel;@property (weak, nonatomic) IBOutlet UILabel *descLabel;@end@implementation FoodCell// 传入tableView实例化cell的目的是封装得最彻底,让控制器作最少的事,知道得最少+ (instancetype)cellWithTableView:(UITableView *)tableView{ // cellID必须和xib中的一模一样 static NSString *cellID = @"FoodCell"; FoodCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID]; if (cell == nil) { // 从xib创建 cell = [[[NSBundle mainBundle] loadNibNamed:cellID owner:nil options:nil] lastObject]; // 右边是箭头 cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; } return cell;}// 数据源模型,提供数据给内部的子控件们显示,内部会拦截setter方法- (void)setFood:(Food *)food{ _food = food; // 小图标 [self.iconView setImageWithURL:[NSURL URLWithString:food.imageUrl] placeholderImage:[UIImage imageNamed:@"timeline_image_placeholder"]]; // 菜名 self.nameLabel.text = food.name; // 子标题 self.descLabel.text = [NSString stringWithFormat:@"难度:%@ 时长:%@", food.diff, food.time]; }@end |
XIB


浙公网安备 33010602011771号