故事板(Storyboard) 、 iPad编程 、 App和VC的生命周期

1 创建动态TableView

1.1 问题

动态表视图就是显示多少分区,多少行以及每一行的显示内容都是根据数据源来决定。之前我们学过用xib展示动态表视图,本案例将学习如何使用Storyboard展示动态表视图,如图-1所示:

图-1

1.2 方案

首先创建一个SingleViewApplication项目,Xcode会自动帮我们创建好一个TRViewController类,并且自动带有Storyboard文件。将自动创建的TRViewController类删除,新建一个TRTableViewController类,继承至UITableViewController。

将Storyboard中自动生成的场景删除,从对象库拖拽一个表视图控制器对象,并被NavigationController包含。将TRTableViewController类和Storyboard中的表视图控制器进行关联。

然后将Storyboard中的Cell标识标记为“My Cell”,然后在TRTableViewController.m中回答三问,实现协议方法。

在cellForRowIndexPath方法中通过dequeueReusableCellWithIdentifier: forIndexPath:获取到的cell对象不会为空,Storyboard会自动帮助我们判断。

1.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:创建一个表视图控制器项目

创建一个SingleViewApplication项目,将自动创建的TRViewController类删除,新建一个TRTableViewController类,继承至UITableViewController。

再将Storyboard中自动生成的场景删除,从对象库拖拽一个表视图控制器对象,并被NavigationController包含。将TRTableViewController类和Storyboard中的表视图控制器进行关联,如图-2所示:

图-2

最后选中Storyboard中的表视图控制器,在右边栏的检查器四种将表视图设置为动态,如图-3所示:

图-3

步骤二:标记Cell,回答三问

选中Storyboard中TableView的Cell,在右边栏的检查器四中,将Identifier标识设置为“My Cell”,如图-4所示:

图-4

在TRTableViewController.m文件中回答表视图的三问,cellForRowAtIndexPath协议方法中通过dequeueReusableCellWithIdentifier: forIndexPath:获取到的cell对象,不用再判断是否为空,因为Storyboard会自动帮我们进行判断,如果为空会自动创建一个cell对象,代码如下所示:

  1. -(NSInteger)tableView:(UITableView *)tableView
  2. numberOfRowsInSection:(NSInteger)section
  3. {
  4. return 10;
  5. }
  6. -(UITableViewCell *)tableView:(UITableView *)tableView
  7. cellForRowAtIndexPath:(NSIndexPath *)indexPath
  8. {
  9. UITableViewCell *cell = [tableViewdequeueReusableCellWithIdentifier:@"My Cell" forIndexPath:indexPath];
  10. cell.textLabel.text = @"Hello TableView.";
  11. return cell;
  12. }

1.4 完整代码

本案例中,TRTableViewController.m文件中的完整代码如下所示:

  1. #import "TRTableViewController.h"
  2. @implementation TRTableViewController
  3. - (NSInteger)tableView:(UITableView *)tableViewnumberOfRowsInSection:(NSInteger)section
  4. {
  5. return 10;
  6. }
  7. - (UITableViewCell *)tableView:(UITableView *)tableViewcellForRowAtIndexPath:(NSIndexPath *)indexPath
  8. {
  9. UITableViewCell *cell = [tableViewdequeueReusableCellWithIdentifier:@"My Cell" forIndexPath:indexPath];
  10. cell.textLabel.text = @"Hello TableView.";
  11. return cell;
  12. }
  13. @end

2 将xib中的自定义Cell案例移植到Storyboard

2.1 问题

本案例在Storyboard中自定义Cell,将网易新闻界面移植到Storyboard中,如图-5所示:

图-5

2.2 方案

首先创建一个SingleViewApplication项目,Xcode会自动帮我们创建好一个TRViewController类,并且自动带有Storyboard文件。将自动创建的TRViewController类删除,新建一个TRTableViewController类,继承至UITableViewController。

将Storyboard中自动生成的场景删除,从对象库拖拽一个表视图控制器对象,并被NavigationController包含。将TRNewsTableViewController类和Storyboard中的表视图控制器进行关联。

其次创建一个TRNewsCell类继承至UITableViewCell,将Storyboard中的Cell与TRNewsCell绑定,并将cell的标识标记为“News Cell”。在cell的ContentView上拖放所需控件,给自定义Cell的界面添加视图,并将每个控件关联成TRNewsCell的输出口属性。

然后创建一个TRNews继承至NSObject,用于保存新闻的相关数据,本案例TRNews提供一组模拟新闻数据。

最后在TRTableViewController.m中回答三问,实现协议方法给表视图加载数据。

2.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:创建一个表视图控制器项目

创建一个SingleViewApplication项目,将自动创建的TRViewController类删除,新建一个TRNewsTableViewController类,继承至UITableViewController。

再将Storyboard中自动生成的场景删除,从对象库拖拽一个表视图控制器对象,并被NavigationController包含,并将导航栏的标题设置为“News“。

最后将TRNewsTableViewController类和Storyboard中的表视图控制器进行关联。

步骤二:自定义Cell

创建一个TRNewsCell类继承至UITableViewCell,在右边栏的检查器三中将Storyboard中的Cell与TRNewsCell绑定,如图-6所示:

图-6

然后将cell的标识标记为“News Cell”。在cell的ContentView上拖放所需控件,给自定义Cell的界面添加视图,本案例拖放一个ImageView用来显示新闻图片、拖放三个Label分别用来显示新闻标题、新闻内容和新闻评论数目,如图-7所示:

图-7

最后将Cell上的每个控件关联成TRNewsCell的输出口属性,代码如下所示:

  1. @interfaceTRNewsCell : UITableViewCell
  2. @property (weak, nonatomic) IBOutletUILabel *newsTitleLabel;
  3. @property (weak, nonatomic) IBOutletUILabel *newsDetailLabel;
  4. @property (weak, nonatomic) IBOutletUILabel *countLabel;
  5. @property (weak, nonatomic) IBOutletUIImageView *newsImageView;
  6. @end

步骤三:给表视图加载数据

创建一个TRNews继承至NSObject,用于保存新闻的相关数据,它有四个属性分别是NSString类型的title用于保存新闻的标题、NSString类型的detail用于保存新闻的详细内容、float类型的count用于保存新闻的评论数以及NSString类型的imageName用于保存新闻的图片名称,代码如下所示:

  1. @interfaceTRNews : NSObject
  2. @property (strong, nonatomic) NSString *title;
  3. @property (strong, nonatomic) NSString *detail;
  4. @property (nonatomic) float count;
  5. @property (strong, nonatomic) NSString *imageName;
  6. @end

本案例中TRNews还提供一个静态方法,用生成一组模拟新闻数据,代码如下所示:

  1. + (NSArray *)demoData
  2. {
  3. TRNews *n1 = [[TRNewsalloc]init];
  4. n1.title = @"苹果正式发布iPhone6/Plus";
  5. n1.detail = @"分别为4.7英寸和5.5英寸屏,均在9月19日正式开售。";
  6. n1.count = 5.5;
  7. n1.imageName = @"Apple Tree.ico";
  8. TRNews *n2 = [[TRNewsalloc]init];
  9. n2.title = @"首发地有香港无大陆";
  10. n2.detail = @"美国、加拿大、日本等首批上市,在美国才199美元,也就是1200人民币。";
  11. n2.count = 6;
  12. n2.imageName = @"Bliss.ico";
  13. TRNews *n3 = [[TRNewsalloc]init];
  14. n3.title = @"教师节快乐";
  15. n3.detail = @"老师我好想你,你教我的东西现在都还给你了,什么时候把学费还给我啊。";
  16. n3.count = 10;
  17. n3.imageName = @"Campfire.ico";
  18. TRNews *n4 = [[TRNewsalloc]init];
  19. n4.title = @"苹果正式发布iPhone6/Plus";
  20. n4.detail = @"分别为4.7英寸和5.5英寸屏,均在9月19日正式开售。";
  21. n4.count = 5.5;
  22. n4.imageName = @"City Night.ico";
  23. return @[n1, n2, n3, n4];
  24. }

最后在TRTableViewController.m中回答三问,实现协议方法给表视图加载数据,代码如下所示:

  1. -(NSInteger)tableView:(UITableView *)tableView
  2. numberOfRowsInSection:(NSInteger)section
  3. {
  4. returnself.news.count;
  5. }
  6. -(UITableViewCell *)tableView:(UITableView *)tableView
  7. cellForRowAtIndexPath:(NSIndexPath *)indexPath
  8. {
  9. TRNewsCell *cell = [tableViewdequeueReusableCellWithIdentifier:@"News Cell" forIndexPath:indexPath];
  10. TRNews *news = self.news[indexPath.row];
  11. cell.newsTitleLabel.text = news.title;
  12. cell.newsDetailLabel.text = news.detail;
  13. cell.countLabel.text = [NSStringstringWithFormat:@"%g万", news.count];
  14. cell.newsImageView.image = [UIImageimageNamed:news.imageName];
  15. return cell;
  16. }

2.4 完整代码

本案例中,TRNewsTableViewController.m文件中的完整代码如下所示:

  1. #import "TRNewsTableViewController.h"
  2. #import "TRNews.h"
  3. #import "TRNewsCell.h"
  4. @interface TRNewsTableViewController ()
  5. @property (nonatomic, strong) NSArray *news;
  6. @end
  7. @implementation TRNewsTableViewController
  8. - (void)viewDidLoad
  9. {
  10. [superviewDidLoad];
  11. self.news = [TRNewsdemoData];
  12. }
  13. #pragma mark - Table view data source
  14. -(NSInteger)tableView:(UITableView *)tableView
  15. numberOfRowsInSection:(NSInteger)section
  16. {
  17. returnself.news.count;
  18. }
  19. -(UITableViewCell *)tableView:(UITableView *)tableView
  20. cellForRowAtIndexPath:(NSIndexPath *)indexPath
  21. {
  22. TRNewsCell *cell = [tableViewdequeueReusableCellWithIdentifier:@"News Cell" forIndexPath:indexPath];
  23. TRNews *news = self.news[indexPath.row];
  24. cell.newsTitleLabel.text = news.title;
  25. cell.newsDetailLabel.text = news.detail;
  26. cell.countLabel.text = [NSStringstringWithFormat:@"%g万", news.count];
  27. cell.newsImageView.image = [UIImageimageNamed:news.imageName];
  28. return cell;
  29. }
  30. @end

本案例中,TRNewsCell.h文件中的完整代码如下所示:

  1. #import <UIKit/UIKit.h>
  2. @interfaceTRNewsCell : UITableViewCell
  3. @property (weak, nonatomic) IBOutletUILabel *newsTitleLabel;
  4. @property (weak, nonatomic) IBOutletUILabel *newsDetailLabel;
  5. @property (weak, nonatomic) IBOutletUILabel *countLabel;
  6. @property (weak, nonatomic) IBOutletUIImageView *newsImageView;
  7. @end

本案例中,TRNews.h文件中的完整代码如下所示:

  1. #import <Foundation/Foundation.h>
  2. @interfaceTRNews : NSObject
  3. @property (strong, nonatomic) NSString *title;
  4. @property (strong, nonatomic) NSString *detail;
  5. @property (nonatomic) float count;
  6. @property (strong, nonatomic) NSString *imageName;
  7. + (NSArray *)demoData;
  8. @end

本案例中,TRNews.m文件中的完整代码如下所示:

  1. #import "TRNews.h"
  2. @implementation TRNews
  3. + (NSArray *)demoData
  4. {
  5. TRNews *n1 = [[TRNewsalloc]init];
  6. n1.title = @"苹果正式发布iPhone6/Plus";
  7. n1.detail = @"分别为4.7英寸和5.5英寸屏,均在9月19日正式开售。";
  8. n1.count = 5.5;
  9. n1.imageName = @"Apple Tree.ico";
  10. TRNews *n2 = [[TRNewsalloc]init];
  11. n2.title = @"首发地有香港无大陆";
  12. n2.detail = @"美国、加拿大、日本等首批上市,在美国才199美元,也就是1200人民币。";
  13. n2.count = 6;
  14. n2.imageName = @"Bliss.ico";
  15. TRNews *n3 = [[TRNewsalloc]init];
  16. n3.title = @"教师节快乐";
  17. n3.detail = @"老师我好想你,你教我的东西现在都还给你了,什么时候把学费还给我啊。";
  18. n3.count = 10;
  19. n3.imageName = @"Campfire.ico";
  20. TRNews *n4 = [[TRNewsalloc]init];
  21. n4.title = @"苹果正式发布iPhone6/Plus";
  22. n4.detail = @"分别为4.7英寸和5.5英寸屏,均在9月19日正式开售。";
  23. n4.count = 5.5;
  24. n4.imageName = @"City Night.ico";
  25. return @[n1, n2, n3, n4];
  26. }
  27. @end

3 创建一个Universal项目

3.1 问题

我们在编程时如果希望一套代码兼容iPhone和iPad两个平台,那么在创建项目时Devices选项框就应该选择Universal,表示该程序兼容iPhone和iPad两个平台。本案例演示如何创建一个Universal项目,管理两个设备界面,如图-8、图-9所示:

图-8

图-9

3.2 方案

首先创建一个SingleViewApplication项目,在项目选择窗口中的Devices选项框中选择Universal,表示该项目兼容iPhone和iPad两个平台。

在Xcode5以前,Universal项目会提供两个Storyboard文件,分别正对iPhone和iPad。从Xcode6开始IOS为我们提供了更新更简便的方式——多尺寸设计功能。

选中Storyboard文件中的场景,在右边栏的检查器一中确认Use Size Classes选项是否被勾上,在Xcode6中AutoLayout和SizeClasses是配合使用的。

然后将Xcode切换成分屏界面,在右边界面增加一个iPad界面,这样就能同时操作iPhone和iPad两个界面了。

最后通过在左边的设计窗口的下方的wAny和hAny选项来操作iPhone和iPad的界面,wAny和hAny是Xcode6提供的多尺寸设计功能工具。

3.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:创建Universal项目

首先创建一个SingleViewApplication项目,在项目选择窗口中的Devices选项框中选择Universal,表示该项目兼容iPhone和iPad两个平台,如图-10所示:

图-10

选中Storyboard文件中的场景,在右边栏的检查器一中确认Use Size Classes选项是否被勾上,如图-11所示:

图-11

步骤二:切换分屏窗口,添加iPad界面

在Xcode5以前,Universal项目会提供两个Storyboard文件,分别正对iPhone和iPad。从Xcode6开始IOS不再提供两个Storyboard文件,而是提供了一个多尺寸设计功能。

现将窗口切换成分屏界面,在右边设计界面上选择preview,然后选择Main.storyboard(Preview),如图-12所示:

图-12

然后在右边设计界面的左下方,点击+号按钮,选择新增加一个iPad的画面,如图-13所示:

图-13

新增完成后,可以在右边的画面中发现多了一個iPad的界面,如图-14所示:

图-14

步骤三:通过wAny和hAny选项设置界面

在左边的设计窗口的下方,可以通过wAny和hAny选项来操作iPhone和iPad的界面,这是Xcode6提供的多尺寸设计功能,如图-15所示:

图-15

当下方的设计面板是停在wAny和hAny的时候,下方的文字会提示目前是“For all layouts”,表示此时拖拽一個控制到界面中,那么iPhone和iPad的UI Layout上都会同时新增这个控件。拖拽一个Label控件到界面上,可以看到iPad和iPhone界面上都有一个同样的Label,如图-16所示:

图-16

然后在iPhone界面添加一个Label,不需要在iPad界面上显示,此时就需要通过wAny和hAny工具调整界面,选择左边的两个方框会出现一行提示文字,提示Xcode只会将这个控件添加到符合尺寸的iDevice上,也就是iPhone,如图-17所示:

图-17

最后在iPad界面添加一个Label,不需要在iPhone界面上显示,此时同样需要通过wAny和hAny工具调整界面,选择所有方框会出现一行提示文字,提示Xcode只会将这个控件添加到iPad上,如图-18所示:

图-18

完成之后可以看到iPad和iPhone界面分别有一个不同显示内容的Label,如图-19所示:

图-19

4 完成iPad的界面变换

4.1 问题

UISplitViewController控制器是一个控制器的控制器,是在iPad上构建导航模式应用的基础,可以呈现屏幕分栏视图的效果。本案例使用UISplitViewController控制器完成一个iPad的界面,通过选择左边栏的颜色能够修改右边界面的背景颜色,如图-20、图-21所示:

图-20

图-21

4.2 方案

在创建好的项目中,将Storyboard文件中的场景删除,从对象库拖拽一个SplitViewController对象到界面中,系统提供的SplitViewController自带一个NavigationController(MastViewController)以及一个ViewController(DetailViewController),而NavigationController自带一个TableViewController作为根视图控制器,通常这个表视图控制器的作用类似导航栏。

其次创建两个类TRMasterViewController继承至UITableViewController,以及TRDetailViewController继承至UIViewController。这两个类分别和Storyboard中的MasterViewController和DetailViewController进行绑定。

然后在TRMasterViewController.m文件中实现表视图控制器的三问,给表视图加载数据。再通过实现协议方法didSelectRowAtIndexPath:完成修改右边界面的背景颜色功能,该方法中通过splitViewController.viewControllers属性获取到TRDetailViewController对象,由TRDetailViewController对象调用自己的更新界面方法来改变视图的背景颜色。

最后在Storyboard的DetailViewController场景中拖放一个Label控件,并将其关联成TRDetailViewController的私有属性label。

在TRDetailViewController类中公开声明并实现更新界面方法updateViewWithIndexPath:,该方法中通过indexPath参数修改背景颜色和label的显示内容。

4.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:在Storyboard中创建SplitViewController场景

在创建好的项目中,将Storyboard文件中的场景删除,从对象库拖拽一个SplitViewController对象到界面中,如图-22所示:

图-22

可以从Storyboard界面中看到SplitViewController自带一个NavigationController(MastViewController)以及一个ViewController(DetailViewController),而NavigationController自带一个TableViewController作为根视图控制器,通常这个表视图控制器的作用类似导航栏,如图-23所示:

图-23

步骤二:创建视图控制器,完成界面绑定

创建两个类TRMasterViewController继承至UITableViewController,以及TRDetailViewController继承至UIViewController。

TRMasterViewController和TRDetailViewController这两个类分别和Storyboard中的MasterViewController和DetailViewController场景进行绑定。

然后在TRMasterViewController.m文件中实现表视图控制器的三问,给表视图加载数据,代码如下所示:

  1. -(NSInteger)tableView:(UITableView *)tableView
  2. numberOfRowsInSection:(NSInteger)section {
  3. return 2;
  4. }
  5. -(UITableViewCell *)tableView:(UITableView *)tableView
  6. cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  7. UITableViewCell *cell = [tableViewdequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
  8. if (indexPath.row==0) {
  9. cell.textLabel.text = @"Yellow Color";
  10. }else {
  11. cell.textLabel.text = @"Blue Color";
  12. }
  13. return cell;
  14. }

最后通过实现协议方法didSelectRowAtIndexPath:完成修改右边界面的背景颜色功能,该方法中通过splitViewController.viewControllers属性获取到TRDetailViewController对象,由TRDetailViewController对象调用自己的更新界面方法来改变视图的背景颜色,代码如下所示:

  1. -(void)tableView:(UITableView *)tableViewdidSelectRowAtIndexPath:(NSIndexPath *)indexPath {
  2. //self.splitViewController.viewControllers属性获取到TRDetailViewController对象
  3. TRDetailViewController *vc = (TRDetailViewController*)[self.splitViewController.viewControllers lastObject];
  4. [vcupdateViewWithIndexPath:indexPath];
  5. }

步骤三:实现TRDetailViewController中的更新界面方法

首先在Storyboard的DetailViewController场景中拖放一个Label控件,并将其关联成TRDetailViewController的私有属性label,代码如下所示:

  1. @interfaceTRDetailViewController ()
  2. @property (weak, nonatomic) IBOutletUILabel *label;
  3. @end

然后在TRDetailViewController类中公开声明并实现更新界面方法updateViewWithIndexPath:,该方法中通过indexPath参数修改背景颜色和label的显示内容,代码如下所示:

  1. -(void)updateViewWithIndexPath:(NSIndexPath*)indexPath {
  2. if (indexPath.row==0) {
  3. [self.viewsetBackgroundColor:[UIColoryellowColor]];
  4. self.label.text = @"YellowColor";
  5. }else {
  6. [self.viewsetBackgroundColor:[UIColorblueColor]];
  7. self.label.text = @"BlueColor";
  8. }
  9. }

4.4 完整代码

本案例中,TRMasterViewController.m文件中的完整代码如下所示:

  1. #import "TRMasterViewController.h"
  2. #import "TRDetailViewController.h"
  3. @implementation TRMasterViewController
  4. -(NSInteger)tableView:(UITableView *)tableView
  5. numberOfRowsInSection:(NSInteger)section {
  6. return 2;
  7. }
  8. -(UITableViewCell *)tableView:(UITableView *)tableView
  9. cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  10. UITableViewCell *cell = [tableViewdequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
  11. if (indexPath.row==0) {
  12. cell.textLabel.text = @"Yellow Color";
  13. }else {
  14. cell.textLabel.text = @"Blue Color";
  15. }
  16. return cell;
  17. }
  18. -(void)tableView:(UITableView *)tableView
  19. didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
  20. TRDetailViewController *vc = (TRDetailViewController*)[self.splitViewController.viewControllers lastObject];
  21. [vcupdateViewWithIndexPath:indexPath];
  22. }
  23. @end

本案例中,TRDetailViewController.h文件中的完整代码如下所示:

  1. #import <UIKit/UIKit.h>
  2. @interfaceTRDetailViewController : UIViewController
  3. -(void)updateViewWithIndexPath:(NSIndexPath*)indexPath;
  4. @end

本案例中,TRDetailViewController.m文件中的完整代码如下所示:

  1. #import "TRDetailViewController.h"
  2. #import "TRMasterViewController.h"
  3. @interface TRDetailViewController ()
  4. @property (weak, nonatomic) IBOutletUILabel *label;
  5. @end
  6. @implementation TRDetailViewController
  7. -(void)updateViewWithIndexPath:(NSIndexPath*)indexPath {
  8. if (indexPath.row==0) {
  9. [self.viewsetBackgroundColor:[UIColoryellowColor]];
  10. self.label.text = @"YellowColor";
  11. }else {
  12. [self.viewsetBackgroundColor:[UIColorblueColor]];
  13. self.label.text = @"BlueColor";
  14. }
  15. }
  16. @end

5 使用内嵌视图显示内容

5.1 问题

UIPopoverController是iPad应用特有的类,不能再iPhone上使用,负责控制Popover视图。Popover视图是一种临时视图,它可以漂浮在视图表面,本案例使用PopoverController实现一个简易的文档菜单,如图-24所示:

图-24

5.2 方案

首先Stroyboard文件中的场景嵌入NavigationController,在导航栏的左右两边分别拖放一个BarButtonItem,用于弹出Popover视图。

其次从对象库拖拽一个TableViewController控件的Stroyboard文件中,将表视图设置为静态视图,在Stroyboard中拖放好每个cell需要显示的控件和内容。

选中导航栏左边的按钮往表视图控制器上拉线,释放鼠标在弹出的窗口中选择popover presentation即完成popover视图的创建。

然后在Storyboard中再拖放一个TableViewController,此表视图设置为动态表视图,作为导航栏右边按钮弹出的popover视图。

另创建一个表视图控制类TRTableViewController,和刚才拖放的动态表视图控制器类进行绑定。在TRTableViewController类中回答表视图的三问给表视图加载数据,本案例中该表视图展示的是颜色选项。

最后将导航栏右边按钮关联成TRViewController的方法showPopover:,在该方法使用代码的方式创建另一个按钮的popover视图,并且弹出popover视图。

5.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:在Storyboard中创建popover视图

首先将Stroyboard文件中的场景嵌入NavigationController,在导航栏的左右两边分别拖放一个BarButtonItem,用于弹出Popover视图,如图-25所示:

图-25

其次从对象库拖拽一个TableViewController控件的Stroyboard文件中,将表视图设置为静态视图,在Stroyboard中拖放好每个cell需要显示的控件和内容,如图-26所示:

图-26

选中导航栏左边的按钮往表视图控制器上拉线,释放鼠标在弹出的窗口中选择popover presentation即完成popover视图的创建,如图-27所示:

图-27

步骤二:使用代码创建popover视图

首先在Storyboard中另外再拖放一个TableViewController,将此表视图设置为动态表视图,作为导航栏右边按钮弹出的popover视图,并设置一个标识“popoverController”。

然后创建一个表视图控制类TRTableViewController,和刚才拖放的动态表视图控制器类进行绑定。在TRTableViewController类中回答表视图的三问给表视图加载数据,本案例中该表视图展示的是颜色选项,代码如下所示:

  1. -(NSInteger)tableView:(UITableView *)tableView
  2. numberOfRowsInSection:(NSInteger)section {
  3. returnself.data.count;
  4. }
  5. -(UITableViewCell *)tableView:(UITableView *)tableView
  6. cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  7. UITableViewCell *cell = [tableViewdequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
  8. cell.textLabel.text = self.data[indexPath.row];
  9. return cell;
  10. }
  11. -(void)tableView:(UITableView *)tableViewdidSelectRowAtIndexPath:(NSIndexPath *)indexPath {
  12. UITableViewCell *cell = [tableViewcellForRowAtIndexPath:indexPath];
  13. [cellsetAccessoryType:UITableViewCellAccessoryCheckmark];
  14. for (inti = 0; i<self.data.count; i++) {
  15. NSIndexPath *indexPath2 = [NSIndexPathindexPathForRow:iinSection:indexPath.section];
  16. UITableViewCell *cell2 = [tableView cellForRowAtIndexPath:indexPath2];
  17. if (cell2!=cell) {
  18. [cell2setAccessoryType:UITableViewCellAccessoryNone];
  19. }
  20. }
  21. }

最后将导航栏右边按钮关联成TRViewController的方法showPopover:,在该方法使用代码的方式创建另一个按钮的popover视图,并且弹出popover视图,代码如下所示:

  1. - (IBAction)showPopover:(UIBarButtonItem *)sender {
  2. TRTableViewController *tvc = [self.storyboardinstantiateViewControllerWithIdentifier:@"popoverController"];
  3. //创建POPover视图
  4. if (self.poc==nil) {
  5. self.poc = [[UIPopoverControlleralloc]initWithContentViewController:tvc];
  6. [self.pocsetPopoverContentSize:CGSizeMake(320, 220)];
  7. }
  8. //显示popover视图
  9. [self.pocpresentPopoverFromBarButtonItem:senderpermittedArrowDirections:UIPopoverArrowDirectionUpanimated:YES];
  10. }

最后完成效果如图-28所示:

图-28

5.4 完整代码

本案例中,TRViewController.m文件中的完整代码如下所示:

  1. #import "TRViewController.h"
  2. #import "TRTableViewController.h"
  3. @interface TRViewController ()
  4. @property (nonatomic,strong)UIPopoverController *poc;
  5. @end
  6. @implementation TRViewController
  7. - (IBAction)showPopover:(UIBarButtonItem *)sender {
  8. TRTableViewController *tvc = [self.storyboardinstantiateViewControllerWithIdentifier:@"popoverController"];
  9. if (self.poc==nil) {
  10. self.poc = [[UIPopoverControlleralloc]initWithContentViewController:tvc];
  11. [self.pocsetPopoverContentSize:CGSizeMake(320, 220)];
  12. }
  13. [self.pocpresentPopoverFromBarButtonItem:senderpermittedArrowDirections:UIPopoverArrowDirectionUpanimated:YES];
  14. }
  15. @end

本案例中,TRTableViewController.m文件中的完整代码如下所示:

  1. #import "TRTableViewController.h"
  2. @interface TRTableViewController ()
  3. @property (nonatomic,strong)NSArray *data;
  4. @end
  5. @implementation TRTableViewController
  6. -(NSArray *)data {
  7. if (!_data) {
  8. _data = @[@"Red",@"blue",@"Yellow",@"Pink",@"Purple",@"Gray",@"Black",@"Green"];
  9. }
  10. return _data;
  11. }
  12. - (NSInteger)tableView:(UITableView *)tableViewnumberOfRowsInSection:(NSInteger)section {
  13. returnself.data.count;
  14. }
  15. - (UITableViewCell *)tableView:(UITableView *)tableViewcellForRowAtIndexPath:(NSIndexPath *)indexPath {
  16. UITableViewCell *cell = [tableViewdequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
  17. cell.textLabel.text = self.data[indexPath.row];
  18. return cell;
  19. }
  20. -(void)tableView:(UITableView *)tableViewdidSelectRowAtIndexPath:(NSIndexPath *)indexPath {
  21. UITableViewCell *cell = [tableViewcellForRowAtIndexPath:indexPath];
  22. [cellsetAccessoryType:UITableViewCellAccessoryCheckmark];
  23. for (inti = 0; i<self.data.count; i++) {
  24. NSIndexPath *indexPath2 = [NSIndexPathindexPathForRow:iinSection:indexPath.section];
  25. UITableViewCell *cell2 = [tableView cellForRowAtIndexPath:indexPath2];
  26. if (cell2!=cell) {
  27. [cell2setAccessoryType:UITableViewCellAccessoryNone];
  28. }
  29. }
  30. }
  31. @end
时间: 2024-10-10 18:03:08

故事板(Storyboard) 、 iPad编程 、 App和VC的生命周期的相关文章

使用storyboard创建导航控制器以及控制器的生命周期

使用storyboard创建导航控制器以及控制器的生命周期 一.基本过程 新建一个项目,系统默认的主控制器继承自UIViewController,把主控制器两个文件删掉. 在storyboard中,默认的控制器是View Controller,而我们需要的是导航控制器,那么就把系统的给删掉,拖一个导航控制器进来,导航控制器中默认的第一个子控制器是一个tableview controller,这里不需要,把它删掉,重新拖三个View Controller到界面上进行连线,简单的设置就可以了.  

iOS开发UI篇—使用storyboard创建导航控制器以及控制器的生命周期

一.基本过程 新建一个项目,系统默认的主控制器继承自UIViewController,把主控制器两个文件删掉. 在storyboard中,默认的控制器是View Controller,而我们需要的是导航控制器,那么就把系统的给删掉,拖一个导航控制器进来,导航控制器中默认的第一个子控制器是一个tableview controller,这里不需要,把它删掉,重新拖三个View Controller到界面上进行连线,简单的设置就可以了.           按钮连线,按住ctrl,右边界面选择push

IOS开发storyboard篇~~使用storyboard创建导航控制器以及控制器的生命周期

一.基本过程 新建一个带storyboard的项目,系统默认的主控制器继承自UIViewController,把主控制器两个文件删掉. 在storyboard中,默认的控制器是View Controller,而我们需要的是导航控制器,那么就把系统的给删掉,拖一个导航控制器进来,导航控制器中默认的第一个子控制器是一个tableview controller,这里不需要,把它删掉,重新拖三个View Controller到界面上进行连线,简单的设置就可以了.(tableview controller

DOTA与面向对象的编程思想(3)——英雄的生命周期

很明显,昨天的文章阅读量同比下降了25%.估计大家可能都是被我的文章名字给糊弄过来的,然而看起来并没有什么营养,因此就没多大兴趣了.我很理解,因为我本是对此的胡思乱想,加上自圆其说,正确性尚有待考究,营养更不要提了. 上一篇的同学评论让我去看看<面向对象的游戏开发>,这带给了我一个思考,就是我写这个东西的有没有必要.考虑必要性有很多原因,针对不同的方面,我总结两个原因.1.面向读者,是否开卷有益,能否给读者带来什么启发或者一点点进步.2.对于我,能否给我带来再编程方面的进步.对于第一个,我想应

APP(应用)生命周期

状态更改通知: 1. 委托方法:- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 通知: UIApplicationDidFinishLaunchingNotification 加载完成 程序启动 2.委托方法:- (void)applicationWillResignActive:(UIApplication *)applica

app 和控制器 的生命周期

UIApplication代理对象生命周期函数详解- (void)applicationWillResignActive:(UIApplication *)application说明:当应用程序将要入非活动状态执行,在此期间,应用 程序不接收消息或事件,比如来电话了 - (void)applicationDidBecomeActive:(UIApplication *)application说明:当应用程序入活动状态执行,这个刚好跟上面那个方 法相反 - (void)applicationDid

iOS基础 02 StoryBoard 故事板文件

iOS基础 02 StoryBoard 故事板文件 目录: 1. 故事板的导航特点 2. 故事板中的Scene和Segue 3. 本文最后 在上篇HelloWorld工程中有一个Main.storyboard文件,它被称为“故事板”(storyboard)文件. 它可以描述应用中有哪些界面,界面有哪些控件以及它们的事件. 此外,故事板还能描述界面之间是如何导航的. 1. 故事板的导航特点 在包含多个视图控制器的情况下,采用故事板管理比较方便,而且故事板还可以描述界面之间的导航关系. 下面我们举例

(译)Getting Started——1.2.4 Tutorial:Storyboard(故事板)

该教程是基于你在前面的课程中构建的项目上进行的.学完本教程后,你将使用你前面学到的视图.视图控制器.动作.导航的内容,还会为应用创建一些关键的用户界面,并在场景中添加行为 以下就是本节课的内容: 1. 使用storyboard来定义应用内容和流程 2. 管理多个视图控制器 3. 在用户界面上,给元素添加动作 完成本节教程后,你的应用应该如下所示: 创建第二个场景 到现在为止,你所操作的只是一个由视图控制器管理的单场景,它就是一个可以把事件添加到待办事件列表的页面,即添加事件的场景.现在,是时候创

IOS开发系列--TableView、多个TableViewCell、自定义Cell、Cell上画画(故事板+代码方式),ios7tableview索引

在此之前,我们已经创建了一个通过简单的表视图应用程序并显示预定义的图像.在本教程中,我们将继续努力,使应用程序变得更好,: >不同的行显示不同的图像 - 上个教程,我们的所有行显示相同的缩略图.那么不同的食物显示不同的图片不是更好么? >自定义视图单元-我们将展示我们自己的视图来替代默认表单元格样式 显示不同缩略图 在我们更改代码之前,让我们回顾显示缩略图的代码. 最后,我们增加了一个行代码指示UITableView每一行显示"creme_brelee.jpg"这张图片.显