UITableViewController子控制器的使用方法

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

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

UITableViewController的使用

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

但是,我们经常会遇到这样一个问题,table view controller 只限于管理一个全屏展示的table view。大多数情况下,我们想达到的效果就是这样,但是如果不是呢,我们就只能使用通常的控制器,其实还有其他的方法来达到使用table view controller 的目的。

UITableViewController的特性

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

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

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

UITableViewController的限制

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

如果你是用代码或 .xib 文件来定义的界面,那么迁移到一个标准 view controller 将会非常简单。但是如果你使用了 storyboards,那么这个过程要多包含几个步骤。除非重新创建,否则你并不能在 storyboards 中将 table view controller 改成一个标准的 view controller。这意味着你必须将所有内容拷贝到新的 view controller,然后再重新连接一遍。

最后,你需要把迁移后丢失的 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

时间: 2024-10-05 14:29:37

UITableViewController子控制器的使用方法的相关文章

iOS开发项目-02添加子控制器以及项目分层

iOS开发项目-02添加子控制器以及项目分层 一.添加子控制器 1.设置根控制器(自定义) 说明:分析新浪微博应用,观察其整体建构层次.而系统的控制器不能满足项目开发的需求,这里把项目中原有的控制器删除. 自己定义一个TabBarViewController类.让这个类作为window窗口的根控制器. YYAppDelegate.m文件代码: 1 #import "YYAppDelegate.h" 2 #import "YYTabBarViewController.h&quo

iOS开发项目篇—02添加子控制器以及项目分层

iOS开发项目篇—02添加子控制器以及项目分层 一.添加子控制器 1.设置根控制器(自定义) 说明:分析新浪微博应用,观察其整体建构层次.而系统的控制器不能满足项目开发的需求,这里把项目中原有的控制器删除. 自己定义一个TabBarViewController类.让这个类作为window窗口的根控制器. YYAppDelegate.m文件代码: 1 #import "YYAppDelegate.h" 2 #import "YYTabBarViewController.h&qu

02---按钮的设置 控制器拥有导航栏包装一层导航控制器 添加子控制器 UIBarButtonItem导航按钮 设置导航栏UINavigationBar主题 设置状态栏样式

一.按钮的设置 1.设置背景图片 [btn setBackgroundImage:image forState:UIControlStateNormal]; 2.内部UIImageView 1> 设置内部UIImageView的图片 [btn setImage:image forState:UIControlStateNormal]; // 不能写成btn.imageView.image = image; 2> 调整内部图片的内容模式 self.imageView.contentMode =

UINavigationController的子控制器

?UINavigationController以栈的形式保存子控制器 @property(nonatomic,copy) NSArray *viewControllers; @property(nonatomic,readonly) NSArray *childViewControllers; ?使用push方法能将某个控制器压入栈 - (void)pushViewController:(UIViewController *)viewController animated:(BOOL)anima

iOS不得姐项目--精华模块上拉下拉的注意事项,日期显示,重构子控制器,计算cell的高度(只计算一次),图片帖子的显示

一.上拉下拉注意事项 使用MJRefresh中的上拉控件自动设置透明 当请求下页数据通过page的时候,注意的是上拉加载更多数据失败的问题,下拉加载数据失败了,页数应该还原.或者是请求成功的时候再将页数修改 二.帖子中的日期显示问题(操作日期的两个类的使用) 期望达到的效果:如图 <1>NSDate -- 需要通过NSDateFormatter(日期格式类)将日期转换成相同的格式,才能相互运算,计算出来的时间间隔是以秒数来呈现的. <2>NSCalendar(日历类) -- 通过当

iOS 获取Interface Builder上的子控制器的两种方式

原创Blog,转载请注明出处 blog.csdn.net/hello_hwc 准备工作 Storyboard上为一个ViewController拖拽两个子控制器,并且设置两个segue的identifier分别为childvc1,childvc2 效果 方式一,根据segue的identifier来判断获得 #import "ViewController.h" #import "ChildViewController1.h" #import "ChildV

子控制器 和 父控制器

1.添加子控制器很简单 分两步 一个是 view 一个是 controller 1 [self addChildViewController:tableCTR]; 2 [self.view addSubview:tableCTR.view]; 最后不要忘了加一行 [tableCTR didMoveToParentViewController:self]; 理由:addChildViewController回调用[child willMoveToParentViewController:self]

JQuery this和$(this)的区别及获取$(this)子元素对象的方法

1.JQuery this和$(this)的区别 相信很多刚接触JQuery的人,很多都会对$(this)和this的区别模糊不清,那么这两者有什么区别呢? 首先来看看JQuery中的  $()  这个符号,实际上这个符号在JQuery中相当于JQuery(),即$(this)=jquery();也就是说,这样可以返回一个jquery对象.那么,当你在网页中alert($('#id'));时,会弹出一个[object Object ],这个object对象,也就是jquery对象了. 那么,我们

控制器,行为方法,参数三者的描述者小结

Model的绑定是在Action方法绑定参数时发生的,这个绑定的参数过程要用到的元数据来自于控制器,行为方法和参数的描述者ContrllerDescriptor,ActionDescriptor和ParameterDescriptor.下面也是先来一幅类图,在蒋老师的图上再加了一些书中提到的一些类 主要由三个Descriptor分为上下两部分,下面则是蒋老师原来的那幅图,是各个Descriptor之间的关系,上部是我另外加上去的,是各个Descriptor在使用过程中会用到的一些Info类和At