寫了太多tableView,發(fā)現(xiàn)每次都要實(shí)現(xiàn)TableView的兩個(gè)代理太麻煩。我在swift層面做了一次封裝。
我想要每個(gè)使用tableView的地方,都不在需要單獨(dú)實(shí)現(xiàn)一份tableViewDataSource和TableViewDelegate.
下面是理想的使用實(shí)例:
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 = [
            ("單獨(dú)指定每一個(gè)實(shí)物的創(chuàng)建的控制器", [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,跳轉(zhuǎn)到SpecialSectionCell中\(zhòng)(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)數(shù)據(jù)模型 \(model),事件名:\(action)"
        let alert = UIAlertView(title: title, message:"", delegate: nil,
            cancelButtonTitle: "取消", otherButtonTitles: "確定")
        alert.show()
    }
}
當(dāng)然,我做了兩個(gè)分支,這個(gè)實(shí)例已經(jīng)代表了兩種情況,一種是Normal,使用tableView時(shí),既有Section又有Cell,并且是重復(fù)的多個(gè)Section的情況。
另一個(gè)分支是Single的情況,只有一個(gè)Section并且沒有sectionHeader只有cell。

這里是更復(fù)雜的情況,每個(gè)Section和Cell都由對(duì)應(yīng)的那個(gè)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:"這里是另外一項(xiàng)Section,有自己指定創(chuàng)建協(xié)議",
            headerHelper:NormalHeaderView(),
            footerHelper:NormalSectionHelper(),
            cellHelper:SpecialCell1(),
            ["上的飛機(jī)上的老費(fèi)勁了深刻的風(fēng)格",
                "粉紅色的附件是對(duì)方講課老師",
                "我一偶估計(jì)哦ID房間給大家發(fā)國際的風(fēng)格  ",
                "收到fish地方hi地方看見你看看多少"]
        )
        let data2:MarkTableViewDD.FullModelType = (
            sectionData:"這里是第一個(gè)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)數(shù)據(jù)模型 \(model),事件名:\(action)"
        let alert = UIAlertView(title: title, message:"", delegate: nil,
            cancelButtonTitle: "取消", otherButtonTitles: "確定")
        alert.show()
    }
    
}
這里是輔助的幾個(gè)實(shí)現(xiàn):
比如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())"
    }
}


以及另外的幾個(gè)分類實(shí)現(xiàn):
//MARK:NewCell

class NormalCell:UITableViewCell{
    typealias ModelType = Int
    var actionDelegate:MarkTableCallBacks? = nil
    var model:ModelType! {
        didSet{
            self.textLabel?.text = "這是數(shù)據(jù)\(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  //應(yīng)該在這個(gè)函數(shù)所隱藏的那個(gè)Cell所使用的是當(dāng)前這個(gè)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{
    /// 常規(guī)的tableViewDD,需要外部設(shè)置footer和header的代理到這個(gè)對(duì)象本身.callback必須傳遞進(jìn)來,但是可以是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
            }
        }
    }
}