表视图是一个非常万能的iOS应用程序构建模块。因此,有很多与表视图直接或间接相关的代码,包括提供数据、更新表视图、控制其行为和选择做出的反应,这仅仅是几个例子。在这篇文章里,我们将会介绍一些整洁而结构良好的代码。
UITableViewController VS UIViewControler
苹果提供了UITableViewController作为表视图的专用视图控制器。Table view controllers实现了一些非常有用的特性来帮助你避免写重复的代码。另一方面,Table view controllers仅限于管理一个全屏显示的表视图。然而,在大多数情况下,这就可以满足你的需要了。如果不满足的话,我们将会在下面讲解解决它的方法。
Table View Controllers的特性
Table View Controllers将会在它第一次显示的时候帮你加载表视图的数据。更具体地说,它可以帮助切换表视图的编辑模式,对键盘的通知做出反应,比如滚动刷新和清除选项这类的小功能。重要的是,你可以自定义子类来重写这些可以被称为万能的视图时间方法来实现这些特性。
Table View Controllers有一个独特的卖点超越了标准视图控制器的独特卖点,它支持苹果的z“下拉更新”的功能目前,这是唯一通过使用一个表控制器来控制刷新记录的方法。还有一些其他的方法来使它生效,但是在下一次iOS中的更新却不是那么的容易
所有的这些原理提供了大量的表视图控制器的接口像苹果已经定义的那样,如果你APP符合这些标准,坚持使用表视图控制器是一个避免重写模版代码的好办法。
Table View控制器的限制
表视图控制器的视图属性总是被设定在一个表视图上。如果你以后决定想在屏幕上显示除了视图表以外的东西(比如地图),假如你不想依赖于笨拙的补丁那你就有的惨了。
如果你已经定义在代码里定义了接口或者在使用.xib文件,那么转换到一个标准的视图控制器就会相当容易了。如果你使用脚本的话这个转换过程会涉及到更多一些的步骤。用脚本,你需要通过重新创建来把一个表视图控制器转变为一个标准的表视图控制器。这就意味这你必须把所有的内容复制到这个新的试图控制器中然后再重新建立。最后,你需要重新把转变过程中丢失的表视图控制器的功能添加一遍。大部分都是viewWillAppear或viewDidAppear里简单的单行语句。切换编辑状态需要一个点击表视图的编辑属性方法来执行。大部分的工作在于重新创建键盘支持。
在你继续走这个路线之前,这里有一个关注点分离附加好处的简单替代方法。
子视图控制器
并非为了完全摆脱表视图管理器,你也可以将其作为一个子视图控制器添加到另一个视图控制器(见本文关于视图管理器的控制)。然后表视图管理器只需要继续管理这个表视图而父视图管理器可以处理任何额外你需要的界面元素。
1 2 3 4 5 6 7 8 9 10 11 12 |
- (void)addPhotoDetailsTableView { DetailsViewController *details = [[DetailsViewController alloc] init]; details.photo = self.photo; details.delegate = self; [self addChildViewController:details]; CGRect frame = self.view.bounds; frame.origin.y = 110; details.view.frame = frame; [self.view addSubview:details.view]; [details didMoveToParentViewController:self]; } |
如果你选择这个解决方法的话,你需要建立一个子视图和父视图之间的通信通道。例如,为了能够push另一个视图进来,父视图需要知道table view的cell被选中了。鉴于这个使用场景,最干净的方法就是为table view控制器定义一个代理协议,可以在父视图中实现这个协议。
如果你要使用这个解决方法,你必须创建一个从子类到父类的通信通道。例如,如果用户选择了一个表视图的单元格,父视图控制器需要接收到消息来推动另一个视图控制器。根据实例,通常最简洁的方法是为这个表视图控制器定义一个委托协议,然后你在父视图管理器中实现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
@protocol DetailsViewControllerDelegate - (void)didSelectPhotoAttributeWithKey:(NSString *)key; @end @interface PhotoViewController () <DetailsViewControllerDelegate> @end @implementation PhotoViewController // ... - (void)didSelectPhotoAttributeWithKey:(NSString *)key { DetailViewController *controller = [[DetailViewController alloc] init]; controller.key = key; [self.navigationController pushViewController:controller animated:YES]; } @end |
正如你看的那样,这种结构会在视图控制器之间的通信中伴随一些其他的额外开销来换取干净的关注点分离和更好的重用性.根据具体的用例,最终使事情比必需要更简单或者更复杂,这是你需要考虑和决定的。
分离关注点
当处理表视图时有各种不同的任务关于模型,控制器和视图的跨越边界问题。为了防止视图控制器成为存放这些任务的地方,我们会视图讲这些任务单独的放在更合适的地方。这有助于代码的可读性,维护性和测试性。
在轻视图控制器的文章里讲述了详细的概念和扩展技术。如何把我们的数据源和模型逻辑引入。在表视图的环境下,我们将专门看看如何分离视图控制器和视图的关注点的问题。
桥接模型对象和单元之间的差距
在某种程度上,我们必须交出想要在视图层显示的数据。由于我们想要维持一个模型和视图之间清晰的分离点,经常把这个任务放到表视图的数据来源里。
1 2 3 4 5 6 7 8 9 |
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { PhotoCell *cell = [tableView dequeueReusableCellWithIdentifier:@"PhotoCell"]; Photo *photo = [self itemAtIndexPath:indexPath]; cell.photoTitleLabel.text = photo.name; NSString* date = [self.dateFormatter stringFromDate:photo.creationDate]; cell.photoDateLabel.text = date; } |
这个代码将数据源和cell的设计逻辑绑定在了一起。我们最好将这个在cell的类别类里重构一下。
1 2 3 4 5 6 7 8 9 10 |
@implementation PhotoCell (ConfigureForPhoto) - (void)configureForPhoto:(Photo *)photo { self.photoTitleLabel.text = photo.name; NSString* date = [self.dateFormatter stringFromDate:photo.creationDate]; self.photoDateLabel.text = date; } 代码,包括提供数据、更新表视图、控制其行为和选择做出的反应,这仅仅是几个例子。在这篇文章里,我们将会介绍一些整洁而结构良好的代码。
UITableViewController VS UIViewControler苹果提供了UITableViewController作为表视图的专用视图控制器。Table view controllers实现了一些非常有用的特性来帮助你避免写重复的代码。另一方面,Table view controllers仅限于管理一个全屏显示的表视图。然而,在大多数情况下,这就可以满足你的需要了。如果不满足的话,我们将会在下面讲解解决它的方法。
Table View Controllers的特性Table View Controllers将会在它第一次显示的时候帮你加载表视图的数据。更具体地说,它可以帮助切换表视图的编辑模式,对键盘的通知做出反应,比如滚动刷新和清除选项这类的小功能。重要的是,你可以自定义子类来重写这些可以被称为万能的视图时间方法来实现这些特性。 Table View Controllers有一个独特的卖点超越了标准视图控制器的独特卖点,它支持苹果的z“下拉更新”的功能目前,这是唯一通过使用一个表控制器来控制刷新记录的方法。还有一些其他的方法来使它生效,但是在下一次iOS中的更新却不是那么的容易 所有的这些原理提供了大量的表视图控制器的接口像苹果已经定义的那样,如果你APP符合这些标准,坚持使用表视图控制器是一个避免重写模版代码的好办法。
Table View控制器的限制表视图控制器的视图属性总是被设定在一个表视图上。如果你以后决定想在屏幕上显示除了视图表以外的东西(比如地图),假如你不想依赖于笨拙的补丁那你就有的惨了。 如果你已经定义在代码里定义了接口或者在使用.xib文件,那么转换到一个标准的视图控制器就会相当容易了。如果你使用脚本的话这个转换过程会涉及到更多一些的步骤。用脚本,你需要通过重新创建来把一个表视图控制器转变为一个标准的表视图控制器。这就意味这你必须把所有的内容复制到这个新的试图控制器中然后再重新建立。最后,你需要重新把转变过程中丢失的表视图控制器的功能添加一遍。大部分都是viewWillAppear或viewDidAppear里简单的单行语句。切换编辑状态需要一个点击表视图的编辑属性方法来执行。大部分的工作在于重新创建键盘支持。 在你继续走这个路线之前,这里有一个关注点分离附加好处的简单替代方法。
子视图控制器并非为了完全摆脱表视图管理器,你也可以将其作为一个子视图控制器添加到另一个视图控制器(见本文关于视图管理器的控制)。然后表视图管理器只需要继续管理这个表视图而父视图管理器可以处理任何额外你需要的界面元素。
如果你选择这个解决方法的话,你需要建立一个子视图和父视图之间的通信通道。例如,为了能够push另一个视图进来,父视图需要知道table view的cell被选中了。鉴于这个使用场景,最干净的方法就是为table view控制器定义一个代理协议,可以在父视图中实现这个协议。 如果你要使用这个解决方法,你必须创建一个从子类到父类的通信通道。例如,如果用户选择了一个表视图的单元格,父视图控制器需要接收到消息来推动另一个视图控制器。根据实例,通常最简洁的方法是为这个表视图控制器定义一个委托协议,然后你在父视图管理器中实现。
正如你看的那样,这种结构会在视图控制器之间的通信中伴随一些其他的额外开销来换取干净的关注点分离和更好的重用性.根据具体的用例,最终使事情比必需要更简单或者更复杂,这是你需要考虑和决定的。
分离关注点当处理表视图时有各种不同的任务关于模型,控制器和视图的跨越边界问题。为了防止视图控制器成为存放这些任务的地方,我们会视图讲这些任务单独的放在更合适的地方。这有助于代码的可读性,维护性和测试性。 在轻视图控制器的文章里讲述了详细的概念和扩展技术。如何把我们的数据源和模型逻辑引入。在表视图的环境下,我们将专门看看如何分离视图控制器和视图的关注点的问题。
桥接模型对象和单元之间的差距在某种程度上,我们必须交出想要在视图层显示的数据。由于我们想要维持一个模型和视图之间清晰的分离点,经常把这个任务放到表视图的数据来源里。
这个代码将数据源和cell的设计逻辑绑定在了一起。我们最好将这个在cell的类别类里重构一下。
|