ios闲来一看iOS开发之控件iOS基础

记一次对 UITableView 的探索, 使用面向协议创建 C

2016-04-05  本文已影响1232人  小梁同学

tableView是 iOS 开发中最常用的组件之一, Apple 用很好的代理模式将其解耦, 但我们开发人员却将相应的 Controller 变得臃肿不堪复用

就我目前的水平能想到, 尽一切力量简化 Controller, 同时解耦的方法大约有以下几种:

  1. 将 tableView 的 delegate, dataSource 从 Controller 中分离
  2. 将 tableViewCell 封装, 不要将根据数据配置 cell 的操作写着 cellForRow: 等方法中, 尽量封装在 cell 中
    这只是我能想到的两点, 代码重构这东西, 不想数学答案, 有唯一的标准答案, 不同的程序员有不同的解耦封装方式, 所以以上两点及本片文章仅代表个人观点, 看官看个过场就好了, 如果您觉得我说的有道理, 那当然欢迎讨论

废话少说了, 如果最遵循了以上两点, 我们会发现, Controller 内容少了, 因为我们将 tableView的 delegate, dataSource 分离出来, 但是如果一个界面中的 cell 不尽相同, 用在 storyboard 中的表现形式就是, 要拖上好几种 cell 的样式才嫩满足页面的需求, 好了这个是有在 cellForRow: 中就会有大量的 if-else if -else 了, 好吧可以用 Switch 替换 , 同样如果每个不同的 cell有不同的点击事件, 那么在 didSelect方法中, 又会有大量的 if-else if -else, 这样的代码后期很难维护, 所以针对这个问题, 我要说下自己的想法了:

面向对象三大特征: 封装, 继承, 多态, 在这里我们看来要用多态了, 所有的 cell 都是 tableViewCell, 但具体的可能会有差异, 所以我们会尝试抽象共性, 在创建 cell 时就可以根据多态生成不同的 cell 了

细想, 起始 不同的cell在界面上提现就是界面上的不同, 在数据中就是数据的不同, 可以根据数据确定 cell, 看来数据要有抽象共性, 找出抽象共性后, 我们有两种办法可以实现多态, 1. 将共性放到基类中, 使用继承的方式 2. 使用接口; 设计模式告诉我们要面向接口编程, 而不是面向实现编程, 所以我在这里的基类相当于 java 中的抽象基类, 只有接口, 没有实现, 在这里我们使用接口吧

  1. 首先定义接口

     #import <UIKit/UIKit.h>
    
     @protocol TableViewCellProtocol <NSObject>
     @optional
     /**
      *  注册 Cell 的 ID
      *
      *  @return 注册 Cell 的 ID
      */
     - (NSString *)registerCellIdentifier;
     
     /**
      *  对应 cell 的类, 在通过 xib, 代码创建 cell 时, 需要先注册, 能用到注册 Cell的 ID, 和 cell 类这两个方法
      *
      *  @return 对应 cell 的类
      */
     - (Class)cellClass;
     
     /**
      *  点击 cell 时触发的操作
      */
     - (void)cellAction:(UITableView *)tableView;
     
     /**
      *  cell 所在的 IndexPath
      */
     - (NSIndexPath *)indexPath;
     
     @end
    
  2. 定义父 tableViewCell, 与接口建立联系

     #import <UIKit/UIKit.h>
     #import "TableViewCellProtocol.h"
     
     @interface ParentTableViewCell : UITableViewCell
     @property (nonatomic, strong) id<TableViewCellProtocol> data;
     @end
     
     #import "ParentTableViewCell.h"
    
     @implementation ParentTableViewCell
     
     @end
    
  3. 某个 cell 数据的设置

     - (NSString *)registerCellIdentifier {
         return @"AddressInfoCell";
     }
     
     - (Class)cellClass {
         return [AddressInfo class];
     }
     
     - (void)cellAction:(UITableView *)tableView {
        // TODO.. cellAction
     }       
    
  4. 某个子 Cell 设置数据

    - (void)setData:(id<TableViewCellProtocol>)data {
        [super setData:data];
        // 将 data 细化
        if (data && [data isKindOfClass:[AddressInfoModel class]]) {
            // TODO...
        }
    }
  1. dataSource, delegate 实现

     // 创建 Cell
     - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
         NSArray *subArr = self.datas[indexPath.section];
         id<TableViewCellProtocol> model = subArr[indexPath.row];
         ParentTableViewCell *cell = (ParentTableViewCell *)[tableView dequeueReusableCellWithIdentifier:[model registerCellIdentifier] forIndexPath:indexPath];
         cell.data = model;
         return cell;
     }
     
     // cell 操作
     - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
         [tableView deselectRowAtIndexPath:indexPath animated:YES];
         
         NSArray *subArr = self.datas[indexPath.section];
         id<TableViewCellProtocol> model = subArr[indexPath.row];
         if (model && [model respondsToSelector:@selector(cellAction:)]) {
             [model cellAction:tableView];
         }
     }
    

在 OC 中面向协议创建 Cell 这是我目前积累下来的, 如果以后有更好的方法, 会及时与大家分享, 我们的目标是写出可复用度高, 低耦合, 有美感的代码, 我相信写代码也像做艺术一样, 要肯想, 追求好的编码方式

还是前面说的, 本片文章仅代表个人观点, 看官看个过场就好了, 如果您觉得我说的有道理, 那当然欢迎讨论, 希望能在代码设计上更上一层楼

在 Swift 中面向协议成为一种必备的编程思想, 以后也会为大家代理关于 Swift 一些面向协议的内容

上一篇下一篇

猜你喜欢

热点阅读