想象一个表视图控制器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类的子类在这里 ),而不是一种语言的解决方案。
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)
}
}
}