zoukankan      html  css  js  c++  java
  • 故事板(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
  • 相关阅读:
    why why why
    为什么又显示了呢?
    Hello
    兼容性问题
    前端性能优化
    ES6新增API
    详解面向对象、构造函数、原型与原型链
    post请求导出表单。
    vue在生产环境清除console.log
    js 延迟加载的几种方法
  • 原文地址:https://www.cnblogs.com/52190112cn/p/5049412.html
Copyright © 2011-2022 走看看