github link -> 可能包含更多更新的代码
回答问题:不能以子类的形式覆盖UITableViewController和UITableViewDataSource之间函数的标准流程。
UIKit 源代码就像一个我们无法看到或更改的大黑盒子。 (如果您这样做,应用程序将被拒绝。)要完全按照您的意愿行事,您需要覆盖从 UITableViewDataSource 调用函数的函数,以便它们指向第三个函数而不是协议函数。这第三个函数将改变基本行为并从 UITableViewDataSource 触发该函数。这样对于其他开发人员来说,一切都会保持不变。
Hack:子类化整个 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)
}
}
}