写了太多tableView,发现每次都要实现TableView的两个代理太麻烦。我在swift层面做了一次封装。
我想要每个使用tableView的地方,都不在需要单独实现一份tableViewDataSource和TableViewDelegate.
下面是理想的使用实例:
class ViewController: UIViewController, MarkTableCallBacks {
    @IBOutlet weak var tableView: UITableView!
    private lazy var dd:MarkTableViewDD.Normal! = {
        let dd = MarkTableViewDD.Normal(callbackObj:self,
            headerHelper: NormalHeaderView(),
            footerHelper: NormalSectionHelper())
        return dd
    }()
    private lazy var singleDD:MarkTableViewDD.SingleSection! = {
        return MarkTableViewDD.SingleSection(callbackObj: self)
    }()
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        useSingle()
        //useSingle()
        tableView.reloadData()
    }
    func useNormal(){
        tableView.setDD(dd, cellProtocol:NormalCell())
        dd.sectionDatas = [
            ("单独指定每一个实物的创建的控制器", [1, 2, 3, 4]),
            ("bdfgdfg", [8, 5, 6]),
            ("cdfgdfg", [325, 88, 90]),
            ("ddfgdfg", [1, 2, 3, 4, 5, 9, 35]),
            ("edfgdf", [835, 5343, 6345]),
            ("fdfdfg", [3434325, 88322, 9033])
        ]
    }
    func useSingle(){
        tableView.setDD(singleDD, cellProtocol: NormalCell())
        
        singleDD.cellDatas = [1, 2, 3, 4]
    }
    //MARK:TemplateCallBacks
    func didSelect(indexPath: NSIndexPath) {
        var title = "选中了\(indexPath.section)-\(indexPath.row)"
        if indexPath.section == 0 {
            title = "普通Cell,跳转到SpecialSectionCell中\(dd.sectionDatas[indexPath.section].cellData![indexPath.row])"
            self.navigationController?.pushViewController(SpecialSectionCellVC(), animated: true)
        }
        let alert = UIAlertView(title: title, message:"", delegate: nil,
            cancelButtonTitle: "取消", otherButtonTitles: "确定")
        alert.show()
    }
    func doAction(action: String, model: AnyObject!, fromClass:AnyClass) {
        let title = "收到来自:\(fromClass)数据模型 \(model),事件名:\(action)"
        let alert = UIAlertView(title: title, message:"", delegate: nil,
            cancelButtonTitle: "取消", otherButtonTitles: "确定")
        alert.show()
    }
}
当然,我做了两个分支,这个实例已经代表了两种情况,一种是Normal,使用tableView时,既有Section又有Cell,并且是重复的多个Section的情况。
另一个分支是Single的情况,只有一个Section并且没有sectionHeader只有cell。

这里是更复杂的情况,每个Section和Cell都由对应的那个View自己定义并且通过代理返回给tableView:

class SpecialSectionCellVC: UIViewController, MarkTableCallBacks {
    @IBOutlet weak var tableView: UITableView!
    
    private lazy var dd:MarkTableViewDD.SpecialSctionSpecialCell! = {
        let dd = MarkTableViewDD.SpecialSctionSpecialCell(callbackObj:self)
        return dd
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        tableView.setDD(dd)
        tableView.registerClass(NormalCell.classForCoder(), forCellReuseIdentifier: NormalCell().identifier())
        //        tableView.registerClass(SpecialCell1.classForCoder(), forCellReuseIdentifier: SpecialCell1().identifier())
        tableView.registerNib(UINib(nibName: SpecialCell1().identifier(), bundle: nil),
            forCellReuseIdentifier:SpecialCell1().identifier())
        
        let data1:MarkTableViewDD.FullModelType = (
            sectionData:"这里是另外一项Section,有自己指定创建协议",
            headerHelper:NormalHeaderView(),
            footerHelper:NormalSectionHelper(),
            cellHelper:SpecialCell1(),
            ["上的飞机上的老费劲了深刻的风格",
                "粉红色的附件是对方讲课老师",
                "我一偶估计哦ID房间给大家发国际的风格  ",
                "收到fish地方hi地方看见你看看多少"]
        )
        let data2:MarkTableViewDD.FullModelType = (
            sectionData:"这里是第一个Sectin,和普通情况一样",
            headerHelper:NormalHeaderView(),
            footerHelper:NormalSectionHelper(),
            cellHelper:NormalCell(),
            [1, 2, 3, 4]
        )
        dd.sectionDatas = []
        dd.sectionDatas.append(data1)
        dd.sectionDatas.append(data2)
        tableView.reloadData()
    }
    
    //MARK:TemplateCallBacks
    func didSelect(indexPath: NSIndexPath) {
        let title = "选中了 \(dd.sectionDatas[indexPath.section].cellData![indexPath.row])"
        let alert = UIAlertView(title: title, message:"", delegate: nil,
            cancelButtonTitle: "取消", otherButtonTitles: "确定")
        alert.show()
    }
    func doAction(action: String, model: AnyObject!, fromClass:AnyClass) {
        let title = "收到来自:\(fromClass)数据模型 \(model),事件名:\(action)"
        let alert = UIAlertView(title: title, message:"", delegate: nil,
            cancelButtonTitle: "取消", otherButtonTitles: "确定")
        alert.show()
    }
    
}
这里是辅助的几个实现:
比如SpecialCell1

class SpecialCell1: UITableViewCell {
    typealias ModelType = String
    @IBOutlet weak var label: UILabel!
    
    private var actionDelegate: MarkTableCallBacks?
    var model:ModelType! {
        didSet{
            self.label.text = model
        }
    }
    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }
    
    override func setSelected(selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
        
        // Configure the view for the selected state
    }    
}

extension SpecialCell1:MarkCellProtocol{
    typealias CellType = SpecialCell1
    func heightForModel(model: Any!) -> CGFloat {
        return 100
    }
    func setupWithModel(model: Any!, cell: UITableViewCell, actionDelegate: MarkTableCallBacks?) {
        (cell as! CellType).model = model as! CellType.ModelType
        (cell as! CellType).actionDelegate = actionDelegate
    }
    func Class()->AnyClass{
        return CellType.classForCoder()
    }
    func identifier()->String{
        return "\(CellType.classForCoder())"
    }
}


以及另外的几个分类实现:
//MARK:NewCell

class NormalCell:UITableViewCell{
    typealias ModelType = Int
    var actionDelegate:MarkTableCallBacks? = nil
    var model:ModelType! {
        didSet{
            self.textLabel?.text = "这是数据\(model)"
            btn.setTitle("\(model)", forState: .Normal)
        }
    }
    
    override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        
        self.btn.addTarget(self, action: Selector("click"), forControlEvents: .TouchUpInside)
        self.addSubview(btn)
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    private lazy var btn:UIButton! = {
        let btn = UIButton(type: .Custom)
        btn.frame = CGRectMake(UIScreen.mainScreen().bounds.size.width-60, 10, 50, 40)
        btn.backgroundColor = UIColor.greenColor()
        return btn
    }()
    
    func click(){
        actionDelegate?.doAction!("click", model: self.model, fromClass:self.classForCoder)
    }
}

extension NormalCell:MarkCellProtocol{
    private typealias CellType = NormalCell
    func Class()->AnyClass{
        return CellType.classForCoder()
    }
    func heightForModel(model:Any!)->CGFloat{
        return 60
    }
    func identifier()->String{
        return "\(CellType.classForCoder())"
    }
    func setupWithModel(model:Any!, cell:UITableViewCell, actionDelegate:MarkTableCallBacks?){
        (cell as! CellType).model = model as! CellType.ModelType
        (cell as! CellType).actionDelegate = actionDelegate
    }
}

//MARK:MarkTableViewHeaderSectionProtocol
class NormalHeaderView:UIView{
    typealias ModelType = String
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        self.btn.addTarget(self, action: Selector("click"), forControlEvents: .TouchUpInside)
        self.addSubview(btn)
    }
    private var model:ModelType!
    private var actionDelegate:MarkTableCallBacks? = nil
    
    func setupModel(model:ModelType!, actionDelegate:MarkTableCallBacks!){
        self.model = model
        self.actionDelegate = actionDelegate
        btn.setTitle("\(model)", forState: .Normal)
    }
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    private var btn:UIButton! = {
        let btn = UIButton(type: .Custom)
        btn.frame = CGRectMake(0, 10, 320, 20)
        btn.backgroundColor = UIColor.blueColor()
        return btn
    }()
    
    func click(){
        actionDelegate?.doAction!("click", model: self.model, fromClass:self.classForCoder)
    }
}
extension NormalHeaderView: MarkTableViewHeaderSectionProtocol {
    func height() -> CGFloat {
        return 40;
    }
    func view(section:Int, model:AnyObject!, actionDelegate:MarkTableCallBacks?) -> UIView? {
        let v = NormalHeaderView(frame: CGRectMake(0,0, 300, 40))
        v.backgroundColor = UIColor.redColor()
        v.setupModel(model as! ModelType, actionDelegate:actionDelegate)
        return v
    }
}

//MARK:MarkTableViewFooterSectionProtocol
class NormalSectionHelper:NSObject, MarkTableViewFooterSectionProtocol {
    func height() -> CGFloat {
        return 10;
    }
    func view(section:Int, model:AnyObject!, actionDelegate:MarkTableCallBacks?) -> UIView? {
        let v = UIView(frame: CGRectMake(0,0, 300, 10))
        v.backgroundColor = UIColor.lightGrayColor()
        return v
        //   return self
    }
}
最后,贴上封装起来的框架.

//
//  Template.swift
//  TableTest
//
//  Created by heqinglong on 16/3/17.
//  Copyright © 2016年 heqinglong. All rights reserved.
//

import Foundation
import UIKit

protocol MarkCellProtocol {
    func identifier()->String
    func heightForModel(model:Any!)->CGFloat
    func setupWithModel(model:Any!, cell:UITableViewCell,  actionDelegate:MarkTableCallBacks?)
    func Class()->AnyClass  //应该在这个函数所隐藏的那个Cell所使用的是当前这个CellProtocol
}

extension UITableView{
    func setDD(dd:MarkTableViewDD.SpecialSctionSpecialCell){
        self.dataSource = dd
        self.delegate = dd
    }
    func setDD(dd:MarkTableViewDD.Normal, cellProtocol:MarkCellProtocol, useNib:Bool = false){
        self.dataSource = dd.realSpecialDD
        self.delegate = dd.realSpecialDD
        dd.helper = cellProtocol
        if useNib == false {
            self.registerClass(cellProtocol.Class(), forCellReuseIdentifier: cellProtocol.identifier())
        }else{
            self.registerNib(UINib(nibName:cellProtocol.identifier(), bundle: nil),
                forCellReuseIdentifier: cellProtocol.identifier())
        }
    }
    func setDD(dd:MarkTableViewDD.SingleSection, cellProtocol:MarkCellProtocol, useNib:Bool = false){
        self.dataSource = dd.realSpecialDD
        self.delegate = dd.realSpecialDD
        dd.helper = cellProtocol
        if useNib == false {
            self.registerClass(cellProtocol.Class(), forCellReuseIdentifier: cellProtocol.identifier())
        }else{
            self.registerNib(UINib(nibName:cellProtocol.identifier(), bundle: nil),
                forCellReuseIdentifier: cellProtocol.identifier())
        }
    }
}

protocol MarkTableViewFooterSectionProtocol{
    func height()->CGFloat
    func view(section:Int, model:AnyObject!, actionDelegate:MarkTableCallBacks?)->UIView?
}

protocol MarkTableViewHeaderSectionProtocol{
    func height()->CGFloat
    func view(section:Int, model:AnyObject!, actionDelegate:MarkTableCallBacks?)->UIView?
}

@objc protocol MarkTableCallBacks{
    optional func didSelect(indexPath: NSIndexPath)
    optional func doAction(action:String, model:AnyObject!, fromClass:AnyClass)
}

class MarkTableViewDD{
    /// 常规的tableViewDD,需要外部设置footer和header的代理到这个对象本身.callback必须传递进来,但是可以是nil的
    class Normal:NSObject {
        private var realSpecialDD:SpecialSctionSpecialCell!
        var sectionDatas:Array<(sectionData:AnyObject?, cellData:NSArray?)>{
            set{
                self.realSpecialDD.sectionDatas = []
                newValue.forEach({
                    self.realSpecialDD.sectionDatas.append((sectionData: $0.sectionData,
                        headerHelper: self.headerHelper,
                        footerHelper: self.footerHelper,
                        cellHelper: self.helper,
                        cellData: $0.cellData))
                })
            }
            get{
                return self.realSpecialDD.sectionDatas.map{
                    return ($0.sectionData, $0.cellData)
                }
            }
        }
        private var helper:MarkCellProtocol!{
            didSet{
                for i in 0self.realSpecialDD.sectionDatas.count-1{
                    self.realSpecialDD.sectionDatas[i].cellHelper = helper
                }
            }
        }
        private var footerHelper:MarkTableViewFooterSectionProtocol?
        private var headerHelper:MarkTableViewHeaderSectionProtocol?
        
        init(callbackObj:MarkTableCallBacks!,
            headerHelper:MarkTableViewHeaderSectionProtocol?,
            footerHelper:MarkTableViewFooterSectionProtocol? ){
                super.init()
                self.realSpecialDD = SpecialSctionSpecialCell(callbackObj: callbackObj)
                self.footerHelper = footerHelper
                self.headerHelper = headerHelper
        }
    }
    
    class SingleSection:NSObject {
        private var realSpecialDD:SpecialSctionSpecialCell!
        var cellDatas:NSArray? {
            set{
                self.realSpecialDD.sectionDatas[0].cellData = newValue
            }
            get{
                return self.realSpecialDD.sectionDatas[0].cellData
            }
        }
        
        init(callbackObj:MarkTableCallBacks!){
            super.init()
            self.realSpecialDD = SpecialSctionSpecialCell(callbackObj: callbackObj)
            self.realSpecialDD.sectionDatas = [(sectionData:nil, headerHelper:nil, footerHelper:nil, cellHelper:nil, cellData:self.cellDatas)]
        }
        private var helper:MarkCellProtocol!{
            didSet{
                self.realSpecialDD.sectionDatas[0].cellHelper = helper
            }
        }
    }
    
    typealias FullModelType = (sectionData: AnyObject?,
        headerHelper:MarkTableViewHeaderSectionProtocol?,
        footerHelper:MarkTableViewFooterSectionProtocol?,
        cellHelper:MarkCellProtocol?,
        cellData:NSArray?)
    class SpecialSctionSpecialCell:NSObject, UITableViewDataSource, UITableViewDelegate {
        var sectionDatas:Array<FullModelType> = [(sectionData:nil, headerHelper:nil, footerHelper:nil, cellHelper:nil, [])]
        
        init(callbackObj:MarkTableCallBacks!){
            self.delegate = callbackObj
        }
        private var delegate:MarkTableCallBacks
        
        @objc func numberOfSectionsInTableView(tableView: UITableView) -> Int {
            return sectionDatas.count
        }
        
        //Cell implementation
        @objc func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
            let dataAndHelper = sectionDatas[indexPath.section]
            if let helper = dataAndHelper.cellHelper {
                let cell = tableView.dequeueReusableCellWithIdentifier(helper.identifier(), forIndexPath: indexPath)
                helper.setupWithModel(sectionDatas[indexPath.section].cellData?[indexPath.row], cell: cell, actionDelegate:delegate)
                return cell
            }else{
                return UITableViewCell()
            }
            
        }
        @objc func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
            tableView.deselectRowAtIndexPath(indexPath, animated: true)
            if let select = delegate.didSelect {
                select(indexPath)
            }
        }
        @objc func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
            if let d = sectionDatas[section].cellData{
                return d.count
            }else{
                return 0
            }
        }
        @objc func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
            let dataAndHelper = sectionDatas[indexPath.section]
            if let helper = dataAndHelper.cellHelper {
                return helper.heightForModel(sectionDatas[indexPath.section].cellData?[indexPath.row])
            }else{
                return 0
            }
        }
        
        //Section implementation
        @objc func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
            let dataAndHelper = sectionDatas[section]
            if let footerHelper = dataAndHelper.footerHelper {
                return footerHelper.height()
            }else{
                return 0
            }
        }
        @objc func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
            let dataAndHelper = sectionDatas[section]
            if let headerHelper = dataAndHelper.headerHelper {
                return headerHelper.height()
            }else{
                return 0
            }
        }
        @objc func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
            let dataAndHelper = sectionDatas[section]
            if let footerHelper = dataAndHelper.footerHelper {
                return footerHelper.view(section, model: sectionDatas[section].sectionData, actionDelegate:delegate)
            }else{
                return nil
            }
        }
        @objc func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
            let dataAndHelper = sectionDatas[section]
            if let headerHelper = dataAndHelper.headerHelper {
                return headerHelper.view(section, model:sectionDatas[section].sectionData, actionDelegate:delegate)
            }else{
                return nil
            }
        }
    }
}