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对象,代码如下所示:
- -(NSInteger)tableView:(UITableView *)tableView
- numberOfRowsInSection:(NSInteger)section
- {
- return 10;
- }
- -(UITableViewCell *)tableView:(UITableView *)tableView
- cellForRowAtIndexPath:(NSIndexPath *)indexPath
- {
- UITableViewCell *cell = [tableViewdequeueReusableCellWithIdentifier:@"My Cell" forIndexPath:indexPath];
- cell.textLabel.text = @"Hello TableView.";
- return cell;
- }
1.4 完整代码
本案例中,TRTableViewController.m文件中的完整代码如下所示:
- #import "TRTableViewController.h"
- @implementation TRTableViewController
- - (NSInteger)tableView:(UITableView *)tableViewnumberOfRowsInSection:(NSInteger)section
- {
- return 10;
- }
- - (UITableViewCell *)tableView:(UITableView *)tableViewcellForRowAtIndexPath:(NSIndexPath *)indexPath
- {
- UITableViewCell *cell = [tableViewdequeueReusableCellWithIdentifier:@"My Cell" forIndexPath:indexPath];
- cell.textLabel.text = @"Hello TableView.";
- return cell;
- }
- @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的输出口属性,代码如下所示:
- @interfaceTRNewsCell : UITableViewCell
- @property (weak, nonatomic) IBOutletUILabel *newsTitleLabel;
- @property (weak, nonatomic) IBOutletUILabel *newsDetailLabel;
- @property (weak, nonatomic) IBOutletUILabel *countLabel;
- @property (weak, nonatomic) IBOutletUIImageView *newsImageView;
- @end
步骤三:给表视图加载数据
创建一个TRNews继承至NSObject,用于保存新闻的相关数据,它有四个属性分别是NSString类型的title用于保存新闻的标题、NSString类型的detail用于保存新闻的详细内容、float类型的count用于保存新闻的评论数以及NSString类型的imageName用于保存新闻的图片名称,代码如下所示:
- @interfaceTRNews : NSObject
- @property (strong, nonatomic) NSString *title;
- @property (strong, nonatomic) NSString *detail;
- @property (nonatomic) float count;
- @property (strong, nonatomic) NSString *imageName;
- @end
本案例中TRNews还提供一个静态方法,用生成一组模拟新闻数据,代码如下所示:
- + (NSArray *)demoData
- {
- TRNews *n1 = [[TRNewsalloc]init];
- n1.title = @"苹果正式发布iPhone6/Plus";
- n1.detail = @"分别为4.7英寸和5.5英寸屏,均在9月19日正式开售。";
- n1.count = 5.5;
- n1.imageName = @"Apple Tree.ico";
- TRNews *n2 = [[TRNewsalloc]init];
- n2.title = @"首发地有香港无大陆";
- n2.detail = @"美国、加拿大、日本等首批上市,在美国才199美元,也就是1200人民币。";
- n2.count = 6;
- n2.imageName = @"Bliss.ico";
- TRNews *n3 = [[TRNewsalloc]init];
- n3.title = @"教师节快乐";
- n3.detail = @"老师我好想你,你教我的东西现在都还给你了,什么时候把学费还给我啊。";
- n3.count = 10;
- n3.imageName = @"Campfire.ico";
- TRNews *n4 = [[TRNewsalloc]init];
- n4.title = @"苹果正式发布iPhone6/Plus";
- n4.detail = @"分别为4.7英寸和5.5英寸屏,均在9月19日正式开售。";
- n4.count = 5.5;
- n4.imageName = @"City Night.ico";
- return @[n1, n2, n3, n4];
- }
最后在TRTableViewController.m中回答三问,实现协议方法给表视图加载数据,代码如下所示:
- -(NSInteger)tableView:(UITableView *)tableView
- numberOfRowsInSection:(NSInteger)section
- {
- returnself.news.count;
- }
- -(UITableViewCell *)tableView:(UITableView *)tableView
- cellForRowAtIndexPath:(NSIndexPath *)indexPath
- {
- TRNewsCell *cell = [tableViewdequeueReusableCellWithIdentifier:@"News Cell" forIndexPath:indexPath];
- TRNews *news = self.news[indexPath.row];
- cell.newsTitleLabel.text = news.title;
- cell.newsDetailLabel.text = news.detail;
- cell.countLabel.text = [NSStringstringWithFormat:@"%g万", news.count];
- cell.newsImageView.image = [UIImageimageNamed:news.imageName];
- return cell;
- }
2.4 完整代码
本案例中,TRNewsTableViewController.m文件中的完整代码如下所示:
- #import "TRNewsTableViewController.h"
- #import "TRNews.h"
- #import "TRNewsCell.h"
- @interface TRNewsTableViewController ()
- @property (nonatomic, strong) NSArray *news;
- @end
- @implementation TRNewsTableViewController
- - (void)viewDidLoad
- {
- [superviewDidLoad];
- self.news = [TRNewsdemoData];
- }
- #pragma mark - Table view data source
- -(NSInteger)tableView:(UITableView *)tableView
- numberOfRowsInSection:(NSInteger)section
- {
- returnself.news.count;
- }
- -(UITableViewCell *)tableView:(UITableView *)tableView
- cellForRowAtIndexPath:(NSIndexPath *)indexPath
- {
- TRNewsCell *cell = [tableViewdequeueReusableCellWithIdentifier:@"News Cell" forIndexPath:indexPath];
- TRNews *news = self.news[indexPath.row];
- cell.newsTitleLabel.text = news.title;
- cell.newsDetailLabel.text = news.detail;
- cell.countLabel.text = [NSStringstringWithFormat:@"%g万", news.count];
- cell.newsImageView.image = [UIImageimageNamed:news.imageName];
- return cell;
- }
- @end
本案例中,TRNewsCell.h文件中的完整代码如下所示:
- #import <UIKit/UIKit.h>
- @interfaceTRNewsCell : UITableViewCell
- @property (weak, nonatomic) IBOutletUILabel *newsTitleLabel;
- @property (weak, nonatomic) IBOutletUILabel *newsDetailLabel;
- @property (weak, nonatomic) IBOutletUILabel *countLabel;
- @property (weak, nonatomic) IBOutletUIImageView *newsImageView;
- @end
本案例中,TRNews.h文件中的完整代码如下所示:
- #import <Foundation/Foundation.h>
- @interfaceTRNews : NSObject
- @property (strong, nonatomic) NSString *title;
- @property (strong, nonatomic) NSString *detail;
- @property (nonatomic) float count;
- @property (strong, nonatomic) NSString *imageName;
- + (NSArray *)demoData;
- @end
本案例中,TRNews.m文件中的完整代码如下所示:
- #import "TRNews.h"
- @implementation TRNews
- + (NSArray *)demoData
- {
- TRNews *n1 = [[TRNewsalloc]init];
- n1.title = @"苹果正式发布iPhone6/Plus";
- n1.detail = @"分别为4.7英寸和5.5英寸屏,均在9月19日正式开售。";
- n1.count = 5.5;
- n1.imageName = @"Apple Tree.ico";
- TRNews *n2 = [[TRNewsalloc]init];
- n2.title = @"首发地有香港无大陆";
- n2.detail = @"美国、加拿大、日本等首批上市,在美国才199美元,也就是1200人民币。";
- n2.count = 6;
- n2.imageName = @"Bliss.ico";
- TRNews *n3 = [[TRNewsalloc]init];
- n3.title = @"教师节快乐";
- n3.detail = @"老师我好想你,你教我的东西现在都还给你了,什么时候把学费还给我啊。";
- n3.count = 10;
- n3.imageName = @"Campfire.ico";
- TRNews *n4 = [[TRNewsalloc]init];
- n4.title = @"苹果正式发布iPhone6/Plus";
- n4.detail = @"分别为4.7英寸和5.5英寸屏,均在9月19日正式开售。";
- n4.count = 5.5;
- n4.imageName = @"City Night.ico";
- return @[n1, n2, n3, n4];
- }
- @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文件中实现表视图控制器的三问,给表视图加载数据,代码如下所示:
- -(NSInteger)tableView:(UITableView *)tableView
- numberOfRowsInSection:(NSInteger)section {
- return 2;
- }
- -(UITableViewCell *)tableView:(UITableView *)tableView
- cellForRowAtIndexPath:(NSIndexPath *)indexPath {
- UITableViewCell *cell = [tableViewdequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
- if (indexPath.row==0) {
- cell.textLabel.text = @"Yellow Color";
- }else {
- cell.textLabel.text = @"Blue Color";
- }
- return cell;
- }
最后通过实现协议方法didSelectRowAtIndexPath:完成修改右边界面的背景颜色功能,该方法中通过splitViewController.viewControllers属性获取到TRDetailViewController对象,由TRDetailViewController对象调用自己的更新界面方法来改变视图的背景颜色,代码如下所示:
- -(void)tableView:(UITableView *)tableViewdidSelectRowAtIndexPath:(NSIndexPath *)indexPath {
- //self.splitViewController.viewControllers属性获取到TRDetailViewController对象
- TRDetailViewController *vc = (TRDetailViewController*)[self.splitViewController.viewControllers lastObject];
- [vcupdateViewWithIndexPath:indexPath];
- }
步骤三:实现TRDetailViewController中的更新界面方法
首先在Storyboard的DetailViewController场景中拖放一个Label控件,并将其关联成TRDetailViewController的私有属性label,代码如下所示:
- @interfaceTRDetailViewController ()
- @property (weak, nonatomic) IBOutletUILabel *label;
- @end
然后在TRDetailViewController类中公开声明并实现更新界面方法updateViewWithIndexPath:,该方法中通过indexPath参数修改背景颜色和label的显示内容,代码如下所示:
- -(void)updateViewWithIndexPath:(NSIndexPath*)indexPath {
- if (indexPath.row==0) {
- [self.viewsetBackgroundColor:[UIColoryellowColor]];
- self.label.text = @"YellowColor";
- }else {
- [self.viewsetBackgroundColor:[UIColorblueColor]];
- self.label.text = @"BlueColor";
- }
- }
4.4 完整代码
本案例中,TRMasterViewController.m文件中的完整代码如下所示:
- #import "TRMasterViewController.h"
- #import "TRDetailViewController.h"
- @implementation TRMasterViewController
- -(NSInteger)tableView:(UITableView *)tableView
- numberOfRowsInSection:(NSInteger)section {
- return 2;
- }
- -(UITableViewCell *)tableView:(UITableView *)tableView
- cellForRowAtIndexPath:(NSIndexPath *)indexPath {
- UITableViewCell *cell = [tableViewdequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
- if (indexPath.row==0) {
- cell.textLabel.text = @"Yellow Color";
- }else {
- cell.textLabel.text = @"Blue Color";
- }
- return cell;
- }
- -(void)tableView:(UITableView *)tableView
- didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
- TRDetailViewController *vc = (TRDetailViewController*)[self.splitViewController.viewControllers lastObject];
- [vcupdateViewWithIndexPath:indexPath];
- }
- @end
本案例中,TRDetailViewController.h文件中的完整代码如下所示:
- #import <UIKit/UIKit.h>
- @interfaceTRDetailViewController : UIViewController
- -(void)updateViewWithIndexPath:(NSIndexPath*)indexPath;
- @end
本案例中,TRDetailViewController.m文件中的完整代码如下所示:
- #import "TRDetailViewController.h"
- #import "TRMasterViewController.h"
- @interface TRDetailViewController ()
- @property (weak, nonatomic) IBOutletUILabel *label;
- @end
- @implementation TRDetailViewController
- -(void)updateViewWithIndexPath:(NSIndexPath*)indexPath {
- if (indexPath.row==0) {
- [self.viewsetBackgroundColor:[UIColoryellowColor]];
- self.label.text = @"YellowColor";
- }else {
- [self.viewsetBackgroundColor:[UIColorblueColor]];
- self.label.text = @"BlueColor";
- }
- }
- @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类中回答表视图的三问给表视图加载数据,本案例中该表视图展示的是颜色选项,代码如下所示:
- -(NSInteger)tableView:(UITableView *)tableView
- numberOfRowsInSection:(NSInteger)section {
- returnself.data.count;
- }
- -(UITableViewCell *)tableView:(UITableView *)tableView
- cellForRowAtIndexPath:(NSIndexPath *)indexPath {
- UITableViewCell *cell = [tableViewdequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
- cell.textLabel.text = self.data[indexPath.row];
- return cell;
- }
- -(void)tableView:(UITableView *)tableViewdidSelectRowAtIndexPath:(NSIndexPath *)indexPath {
- UITableViewCell *cell = [tableViewcellForRowAtIndexPath:indexPath];
- [cellsetAccessoryType:UITableViewCellAccessoryCheckmark];
- for (inti = 0; i<self.data.count; i++) {
- NSIndexPath *indexPath2 = [NSIndexPathindexPathForRow:iinSection:indexPath.section];
- UITableViewCell *cell2 = [tableView cellForRowAtIndexPath:indexPath2];
- if (cell2!=cell) {
- [cell2setAccessoryType:UITableViewCellAccessoryNone];
- }
- }
- }
最后将导航栏右边按钮关联成TRViewController的方法showPopover:,在该方法使用代码的方式创建另一个按钮的popover视图,并且弹出popover视图,代码如下所示:
- - (IBAction)showPopover:(UIBarButtonItem *)sender {
- TRTableViewController *tvc = [self.storyboardinstantiateViewControllerWithIdentifier:@"popoverController"];
- //创建POPover视图
- if (self.poc==nil) {
- self.poc = [[UIPopoverControlleralloc]initWithContentViewController:tvc];
- [self.pocsetPopoverContentSize:CGSizeMake(320, 220)];
- }
- //显示popover视图
- [self.pocpresentPopoverFromBarButtonItem:senderpermittedArrowDirections:UIPopoverArrowDirectionUpanimated:YES];
- }
最后完成效果如图-28所示:
图-28
5.4 完整代码
本案例中,TRViewController.m文件中的完整代码如下所示:
- #import "TRViewController.h"
- #import "TRTableViewController.h"
- @interface TRViewController ()
- @property (nonatomic,strong)UIPopoverController *poc;
- @end
- @implementation TRViewController
- - (IBAction)showPopover:(UIBarButtonItem *)sender {
- TRTableViewController *tvc = [self.storyboardinstantiateViewControllerWithIdentifier:@"popoverController"];
- if (self.poc==nil) {
- self.poc = [[UIPopoverControlleralloc]initWithContentViewController:tvc];
- [self.pocsetPopoverContentSize:CGSizeMake(320, 220)];
- }
- [self.pocpresentPopoverFromBarButtonItem:senderpermittedArrowDirections:UIPopoverArrowDirectionUpanimated:YES];
- }
- @end
本案例中,TRTableViewController.m文件中的完整代码如下所示:
- #import "TRTableViewController.h"
- @interface TRTableViewController ()
- @property (nonatomic,strong)NSArray *data;
- @end
- @implementation TRTableViewController
- -(NSArray *)data {
- if (!_data) {
- _data = @[@"Red",@"blue",@"Yellow",@"Pink",@"Purple",@"Gray",@"Black",@"Green"];
- }
- return _data;
- }
- - (NSInteger)tableView:(UITableView *)tableViewnumberOfRowsInSection:(NSInteger)section {
- returnself.data.count;
- }
- - (UITableViewCell *)tableView:(UITableView *)tableViewcellForRowAtIndexPath:(NSIndexPath *)indexPath {
- UITableViewCell *cell = [tableViewdequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
- cell.textLabel.text = self.data[indexPath.row];
- return cell;
- }
- -(void)tableView:(UITableView *)tableViewdidSelectRowAtIndexPath:(NSIndexPath *)indexPath {
- UITableViewCell *cell = [tableViewcellForRowAtIndexPath:indexPath];
- [cellsetAccessoryType:UITableViewCellAccessoryCheckmark];
- for (inti = 0; i<self.data.count; i++) {
- NSIndexPath *indexPath2 = [NSIndexPathindexPathForRow:iinSection:indexPath.section];
- UITableViewCell *cell2 = [tableView cellForRowAtIndexPath:indexPath2];
- if (cell2!=cell) {
- [cell2setAccessoryType:UITableViewCellAccessoryNone];
- }
- }
- }
- @end