斯威夫特,“子”的UITableView的数据源的方法,不知何故?(Swift, “subclass

2019-11-04 01:25发布

想象一个表视图控制器ExtraRowTableViewController

它总是插入一个额外的行,后(假设)第三行。

因此,在这个例子中...

class SomeList:ExtraRowTableViewController
override func numberOfSectionsInTableView(tableView: UITableView)->Int
    {
    return yourData.count ... say, 50 items
    }
override func tableView
    (tableView:UITableView, cellForRowAtIndexPath indexPath:NSIndexPath)
                                        -> UITableViewCell
    {
    return yourData.cell ... for that row number
    }

ExtraRowTableViewController将“接管”,并实际上将返回51。

对于的cellForRowAtIndexPath,它会“接管”,并在四排回到了自己的细胞,它会返回你的第N行从0到3,它会回报您的电池行减一的行以上四种。

这怎么能在实现ExtraRowTableViewController

这样SomeList的程序员需要做一点变化都没有。

你会被继承的UITableView,或者数据源委托..或?


为了澄清,一个例子使用情况而定,我们说,加入广告,编辑字段,或者一些特殊的新闻,在第四排。 这将是恰当的SomeList的程序员需要做绝对没有达到这一点,即它是在一个完全面向对象的方式实现。


请注意,这是当然的,容易只需添加新的“替代品”的呼叫,你的表视图将“只知道”来使用,而不是正常的呼叫。 (RMenke具有提供的这低于有用完整示例。)所以,

class SpecialTableViewController:UITableViewController

func tableView(tableView: UITableView, specialNumberOfRowsInSection section: Int) -> Int
  {
  print ("You forgot to supply an override for specialNumberOfRowsInSection")
  }

func tableView
  (tableView:UITableView, specialCellForRowAtIndexPath indexPath:NSIndexPath) -> UITableViewCell
  {
  print ("You forgot to supply an override for specialCellForRowAtIndexPath")
  }

override final func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
  {
  return self.specialNumberOfRowsInSection(section) + 1
  }

override final func tableView
  (tableView:UITableView, cellForRowAtIndexPath indexPath:NSIndexPath) -> UITableViewCell
  {
  if indexPath.row == 4
    { return ... the special advertisement cell ... }
  if indexPath.row < 4
    { return self.specialCellForRowAtIndexPath( indexPath )
  if indexPath.row > 4
    { return self.specialCellForRowAtIndexPath( [indexPath.row - 1] )
  }

在这个例子中你的表视图程序员必须“只知道”,他们必须在SpecialTableViewController使用specialNumberOfRowsInSection和specialCellForRowAtIndexPath而不是通常的电话......它不是一个干净,插入式,面向对象的解决方案。


注:我很欣赏你也可能以某种方式覆盖信号(如讨论NSObject类的子类在这里 ),而不是一种语言的解决方案。

Answer 1:

GitHub的链接 - >可能包含更多更新的代码

要回答这个问题 :是不是可以覆盖在子类的形式的UITableViewController和UITableViewDataSource之间的功能的标准流程。

该UIKit的源代码就像一个大黑盒子,我们无法看到或修改。 (应用程序将如果你被拒绝。)做的正是你想你需要重写,使他们指向第三函数,而不是在协议功能的函数调用从UITableViewDataSource的功能是什么。 这第三个功能将改变基本行为和触发来自UITableViewDataSource功能。 这样,它都会保持不变为其他开发者。

哈克 :子类中的整个的UITableViewController - >你需要存储性能。 这样其他人可以继承您的自定义类,他们将不会看到引擎盖下的任何魔法/一塌糊涂。


下面的类使用相同的样式普通的UITableViewController。 用户覆盖他们希望改变的方法。 由于这些方法是对现有功能内使用你会得到一个改变的功能。

不幸的是这是不可能来标记这些功能为私有。


对于indexPath适配器存储Bool和原indexPath。 - >这将符合您的数据。

新插入的细胞会得到基于他们所创建的部分和计数器的indexPath。 - >可能是有益的。


更新:y行后添加X多余的行


class IATableViewController: UITableViewController {

    private var adapters : [[cellAdapter]] = []

    private struct cellAdapter {
        var isDataCell : Bool = true
        var indexPath : NSIndexPath = NSIndexPath()
    }

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func cellIdentifier(tableView: UITableView, isDataCell: Bool) -> String {
        return "Cell"
    }


    func numberOfSections(tableView: UITableView) -> Int {
        return 0
    }

    func numberOfRowsInSection(tableView: UITableView, section: Int) -> Int {
        return 0
    }

    func insertXRowsEveryYRows(tableView: UITableView, section: Int) -> (numberOfRows:Int, everyYRows:Int)? {
        //(numberOfRows:0, everyYRows:0)
        return nil
    }

    func insertXRowsAfterYRows(tableView: UITableView, section: Int) -> (numberOfRows:Int, afterYRows:Int)? {
        //(numberOfRows:0, afterYRows:0)
        return nil
    }

    internal override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        let sections = numberOfSections(tableView)

        adapters = []

        for _ in 0..<sections {
            adapters.append([])
        }

        return sections
    }

    internal override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of rows
        let rows = numberOfRowsInSection(tableView, section: section)

        adapters[section] = []

        for row in 0..<rows {
            var adapter = cellAdapter()
            adapter.indexPath = NSIndexPath(forRow: row, inSection: section)
            adapter.isDataCell = true
            adapters[section].append(adapter)
        }

        insertion(tableView, section: section)

        return adapters[section].count
    }

    private func insertion(tableView: UITableView, section: Int) {

        if let insertRowEvery = insertXRowsEveryYRows(tableView, section: section) {
            let insertionPoint = insertRowEvery.everyYRows
            let insertionTimes = insertRowEvery.numberOfRows

            var counter = 0

            var startArray = adapters[section]
            var insertionArray: [cellAdapter] = []

            while !startArray.isEmpty {

                if startArray.count > (insertionPoint - 1) {

                    for _ in 0..<insertionPoint {
                        insertionArray.append(startArray.removeFirst())
                    }
                    for _ in 0..<insertionTimes {
                        var adapter = cellAdapter()
                        adapter.indexPath = NSIndexPath(forRow: counter, inSection: section)
                        adapter.isDataCell = false
                        insertionArray.append(adapter)
                        counter += 1
                    }
                } else {
                    insertionArray += startArray
                    startArray = []
                }
            }

            adapters[section] = insertionArray

        }
        else if let insertRowAfter = insertXRowsAfterYRows(tableView, section: section) {

            let insertionPoint = insertRowAfter.afterYRows
            let insertionTimes = insertRowAfter.numberOfRows

            if adapters[section].count > (insertionPoint - 1) {

                for i in 0..<insertionTimes {

                    var adapter = cellAdapter()
                    adapter.indexPath = NSIndexPath(forRow: i, inSection: section)
                    adapter.isDataCell = false
                    adapters[section].insert(adapter, atIndex: insertionPoint)

                }
            }
        }
    }


    func insertionCellForRowAtIndexPath(tableView: UITableView, cell: UITableViewCell, indexPath: NSIndexPath) -> UITableViewCell {

        return cell
    }



    func dataCellForRowAtIndexPath(tableView: UITableView, cell: UITableViewCell, indexPath: NSIndexPath) -> UITableViewCell {

        return cell

    }


    internal override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

        let adapter = adapters[indexPath.section][indexPath.row]

        let identifier = cellIdentifier(tableView, isDataCell: adapter.isDataCell)
        let cell = tableView.dequeueReusableCellWithIdentifier(identifier, forIndexPath: indexPath)

        switch adapter.isDataCell {
        case true :
            return dataCellForRowAtIndexPath(tableView, cell: cell, indexPath: adapter.indexPath)
        case false :
            return insertionCellForRowAtIndexPath(tableView, cell: cell, indexPath: adapter.indexPath)
        }
    }
}


文章来源: Swift, “subclass” the data source methods of UITableView somehow?