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
  • 相关阅读:
    archlinux .bash_history
    Ubuntu环境下挂载新硬盘
    软碟通 UltraISO U启替代品 Win32DiskImager 无设备 无盘符 无u盘 无优盘 解决方案 之diskpart
    delphi Integer overflow
    MSBuild Tools offline
    delphi synedit免费的拼写检查器dll
    git 自定义命令行
    lua编译
    gcc ar
    Windows Subsystem for Linux (WSL)挂载移动硬盘U盘 卸载 c d 盘
  • 原文地址:https://www.cnblogs.com/52190112cn/p/5049412.html
Copyright © 2011-2022 走看看