UITableViewController子控制器的使用方法

http://www.tuicool.com/articles/JbiMvumswift

在上一篇文章中 咱们讲了经过整合tableview的代理,来达到代码复用,减小控制器代码量的效果,今天咱们接着来说另外的一些方法来减轻控制器代码量,整合封装,提升代码的可读性。less

UITableViewController的使用

TableView在iOS应用程序中是很是通用的组件,Apple为咱们提供了tableview专属的view controller类UITableViewController。Table view controller实现了一些很是有用的特性,来避免一遍又一遍的写那些死板的代码!ui

可是,咱们常常会遇到这样一个问题,table view controller 只限于管理一个全屏展现的table view。大多数状况下,咱们想达到的效果就是这样,可是若是不是呢,咱们就只能使用一般的控制器,其实还有其余的方法来达到使用table view controller 的目的。atom

UITableViewController的特性

Table view controllers 会在第一次显示 table view 的时候帮你加载其数据。另外,它还会帮你切换 table view 的编辑模式、响应键盘通知、以及一些小任务,好比闪现侧边的滑动提示条和清除选中时的背景色。为了让这些特性生效,当你在子类中覆写相似 viewWillAppear: 或者 viewDidAppear: 等事件方法时,须要调用 super 版本。spa

Table view controllers 相对于标准 view controllers 的一个特别的好处是它支持 Apple 实现的“下拉刷新”。目前,文档中惟一的使用 UIRefreshControl 的方式就是经过 table view controller ,虽然经过努力在其余地方也能让它工做(例如直接将UIRefreshControl直接addSubView到tableview),但极可能在下一次 iOS 更新的时候就不行了。代理

这些要素加一块儿,为咱们提供了大部分 Apple 所定义的标准 table view 交互行为,若是你的应用刚好符合这些标准,那么直接使用 table view controllers 来避免写那些死板的代码是个很好的方法。orm

UITableViewController的限制

Table view controllers 的 view 属性永远都是一个 table view。若是你稍后决定在 table view 旁边显示一些东西(好比一个地图,一个小的按钮),若是不依赖于那些奇怪的 hacks,估计就没什么办法了。对象

若是你是用代码或 .xib 文件来定义的界面,那么迁移到一个标准 view controller 将会很是简单。可是若是你使用了 storyboards,那么这个过程要多包含几个步骤。除非从新建立,不然你并不能在 storyboards 中将 table view controller 改为一个标准的 view controller。这意味着你必须将全部内容拷贝到新的 view controller,而后再从新链接一遍。blog

最后,你须要把迁移后丢失的 table view controller 的特性给补回来。大多数都是 viewWillAppear: 或 viewDidAppear: 中简单的一条语句。切换编辑模式须要实现一个 action 方法,用来切换 table view 的 editing 属性。大多数工做来自从新建立对键盘的支持。事件

在选择这条路以前,其实还有一个更轻松的选择,它能够经过分离咱们须要关心的功能(关注点分离),让你得到额外的好处:

使用 Child View Controllers

和彻底抛弃 table view controller 不一样,你还能够将它做为 child view controller 添加到其余 view controller 中。这样,parent view controller 在管理其余的你须要的新加的界面元素的同时,table view controller 还能够继续管理它的 table view。

咱们来看代码:

我有一个UITableViewController

@interface MyTableViewController () @end @implementation MyTableViewController - (void)viewDidLoad { [super viewDidLoad]; [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cell"]; self.refreshControl = [[UIRefreshControl alloc] initWithFrame:CGRectMake(0, 0, 20, 20)]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; } #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return 10; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath]; cell.textLabel.text = [NSString stringWithFormat:@"%ld",(long)indexPath.row]; return cell; } 

我想要使用这个UITableViewController来管理个人tableview

而后 我还有一个view controller,在这个view controller中 我既要包含这个table view 还要有其余的view 用上面的加自controller来实现

@implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; [self addMyTableViewController]; [self addOtherView]; } //添加zicontroller - (void)addMyTableViewController{ MyTableViewController *vc = [[MyTableViewController alloc] init]; [self addChildViewController:vc]; CGRect frame = self.view.bounds; frame.size.height = 300; vc.view.frame = frame; [self.view addSubview:vc.view]; [vc didMoveToParentViewController:self]; } - (void)addOtherView{ UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(20, 400, 100, 30)]; btn.backgroundColor = [UIColor redColor]; [self.view addSubview:btn]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; } 

若是咱们使用了这种方法,那么咱们就须要在子controller 和 父 controller之间创建起通讯渠道,由于,若是点击了cell,在父类中我须要知道,虽然这样看起来是额外的开销,可是咱们的代码变得很是清晰,复用性也更高

咱们怎样创建起通讯呢,固然最简单的就是使用delegate,这个就比较简单的了

#import <UIKit/UIKit.h> @protocol MyTableViewControllerDelegate <NSObject> - (void)didSelectCell; @end @interface MyTableViewController : UITableViewController @property (nonatomic, weak) id<MyTableViewControllerDelegate> delegate; @end 

传递点击事件

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ [tableView deselectRowAtIndexPath:indexPath animated:YES]; if ([self.delegate respondsToSelector:@selector(didSelectCell)]) { [self.delegate didSelectCell]; } } 

在父controller中捕获点击事件

MyTableViewController *vc = [[MyTableViewController alloc] init]; vc.delegate = self; 
-(void)didSelectCell{ NSLog(@"点击"); } 

在cell内部控制cell的状态

若是咱们想自定义cell内部的状态,在点击cell的时候 自定义高亮样式 咱们知道有这样的delegate方法,让咱们在view controller中操做,可是咱们要讲的就是减小view controller的代码

首先咱们来看看在view controller 中 怎样来改变

- (void)tableView:(UITableView *)tableView didHighlightRowAtIndexPath:(NSIndexPath *)indexPath { //高亮时 } - (void)tableView:(UITableView *)tableView didUnhighlightRowAtIndexPath:(NSIndexPath *)indexPath { //非高亮 } 

View 的实现细节和 delegate 的实现交织在一块儿了。咱们应该把这些细节移到 cell 自身中去。

-(void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated{ [super setHighlighted:highlighted animated:animated]; if (highlighted) { //高亮时改变cell的状态 }else{ //非高亮时改变 } } 

总结

Table view controllers(以及其余的 controller 对象!)应该在 model 和 view 对象之间扮演协调者和调解者的角色。它不该该关心明显属于 view 层或 model 层的任务。你应该始终记住这点,这样 delegate 和 data source 方法会变得更小巧,最多包含一些简单的样板代码。

这不只减小了 table view controllers 那样的大小和复杂性,并且还把业务逻辑和 view 的逻辑放到了更合适的地方。Controller 层的里里外外的实现细节都被封装成了简单的 API,最终,它变得更加容易理解,也更利于团队协做。

参考:

https://www.objccn.io/issue-1-2/

欢迎你们关注个人公众号,我会按期分享一些我在项目中遇到问题的解决办法和一些iOS实用的技巧,现阶段主要是整理出一些基础的知识记录下来

 

http://ppsheep.com/2016/12/14/UITableViewController%E5%AD%90%E6%8E%A7%E5%88%B6%E5%99%A8%E7%9A%84%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%95/?utm_source=tuicool&utm_medium=referral

相关文章
相关标签/搜索