我有点困惑为什么这个方法返回nil:
func indexPath(for cell: UITableViewCell) -> IndexPath?
这是一些调试器输出:
(lldb) po expandingCell
<MyApp.BankDetailsTableViewCell: 0x7f9ec307da00; baseClass = UITableViewCell; frame = (0 495.01; 414 258); clipsToBounds = YES; hidden = YES; autoresize = W; layer = <CALayer: 0x60400003ffc0>>
(lldb) po self.tableView.visibleCells
▿ 8 elements
▿ 0 : <MyApp.AddressTableViewCell: 0x7f9ec2e49600; baseClass = UITableViewCell; frame = (0 207.01; 414 70); clipsToBounds = YES; autoresize = W; layer = <CALayer: 0x60800022fc40>>
▿ 1 : <MyApp.BankDetailsTableViewCell: 0x7f9ec307da00; baseClass = UITableViewCell; frame = (0 277.01; 414 258); clipsToBounds = YES; autoresize = W; layer = <CALayer: 0x60400003ffc0>>
▿ 2 : <MyApp.TransactionLinkTableViewCell: 0x7f9ec585d800; baseClass = UITableViewCell; frame = (0 535.01; 414 70); clipsToBounds = YES; autoresize = W; layer = <CALayer: 0x600000025e60>>
- 3 : <MyApp.SeparatorTableViewCell: 0x7f9ec3003000; baseClass = UITableViewCell; frame = (0 605.01; 414 44); autoresize = W; layer = <CALayer: 0x604000225780>>
▿ 4 : <MyApp.GenericFieldTableViewCell: 0x7f9ec3071a00; baseClass = UITableViewCell; frame = (0 649.01; 414 44); autoresize = W; layer = <CALayer: 0x604000226100>>
▿ 5 : <MyApp.GenericFieldTableViewCell: 0x7f9ec28eb600; baseClass = UITableViewCell; frame = (0 693.01; 414 44); autoresize = W; layer = <CALayer: 0x6080004337a0>>
▿ 6 : <MyApp.GenericFieldTableViewCell: 0x7f9ec590c800; baseClass = UITableViewCell; frame = (0 737.01; 414 44); autoresize = W; layer = <CALayer: 0x600000038b60>>
▿ 7 : <MyApp.GenericFieldTableViewCell: 0x7f9ec5849000; baseClass = UITableViewCell; frame = (0 781.01; 414 44); autoresize = W; layer = <CALayer: 0x600000037080>>
(lldb)
您可以看到展开的单元格位于可见列表中(数组索引1)。那么为什么我的代码为此返回nil?
if let indexPath = self.tableView.indexPath(for: expandingCell) {
// NEVER REACHES HERE. Returns nil
} else {
log.warning("This shouldn't happen. The indexPath should be returned by tableView!")
}
为了给出一些额外的上下文,我正在响应按下按钮,然后应该在单元格'isExpanded'上设置一个标志,然后我调用self.tableView.beginUpdates()和.endUpdates()(同时为heightForRow(at:...)提供一个新值,以便单元格高度扩大。
答案 0 :(得分:0)
我并不是真的喜欢使用这种方法,所以我不惜一切代价避免使用它。在您的情况下,如果您真的需要索引路径,我宁愿在数据源请求单元格时分配它。所以在cellForRow
中,我将自定义单元格出列并分配其数据对象及其索引路径。
但总的来说这也是一个坏主意(把它放在其他数据源或委托方法中也没什么区别)因为你的数据(例如对象数组)可能会在选择完成时按下(按下按钮)并且你可能会再次遇到麻烦。
所以我发现最好的方法是将对象设置为单元格并将self指定为委托。应该通知单元代表单击某个特定对象的按钮,然后代理可以使用该按钮来扩展单元格...某些代码可能会澄清此过程:
假设您有一个视图控制器,它是表视图的数据源,并且您的表视图显示了MyObject
类型的对象,因此您有一些方法可以注入这些对象:
private typealias DataObject = (object: MyObject, extended: Bool) // TODO: use class, not typealias so you can easily change "extended" property for it
private var dataSource: [DataObject] = []
func setDataArray(array: [MyObject]) {
dataSource = array.map { (object: $0, extended: false) } // TODO: fetch extended from current data source if it exists, else use default
tableView.reloadData()
}
因此行的单元格看起来像:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell...
cell.object = dataSource[indexPath.row].object
cell.delegate = self
return cell
}
行的高度:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
dataSource[indexPath.row].extended ? 100.0 : 44.0
}
现在是细胞代表:
func myCell(_ sender: MyCell, shouldToggleObjectBeingExtended object: MyObject) {
if let target = dataSource.first(where: { $0.object === object }) {
target.extended = !target.extended // To use this you must have a class instead of typealias
tableView.beginUpdates()
tableView.endUpdates()
}
}
我可以想象这可能与你所拥有的有点颠倒,但创建这样一个系统通常会付出很大的代价。在修改源代码时,您完全脱离了表视图,这使事情变得更简单和稳定。我希望它可以帮助你解决问题。
至于根据我的经验,这种方法中的“虫子”总是有点搞笑。通常有一些解决方案,但很少有一个解决方案。
答案 1 :(得分:0)
我只是回答我自己的问题。对我来说,这似乎是UIKit中的一个错误,但无论如何,我刚才补充道
var indexPath: IndexPath? = nil
的子类UITableViewCell
我将其设置为-tableView:cellForRowAt:
并在prepareForReuse
然后我可以直接询问单元格他代表什么indexPath。
看起来不太理想,但它确实有效。