访问块

时间:2015-12-11 09:02:06

标签: swift uitableview exc-bad-access

我有一个非常复杂的表视图设置,我决定使用块结构来创建和选择单元格,以简化未来的开发和更改。

我正在使用的结构如下:

var dataSource: [(
    cells:[ (type: DetailSection, createCell: ((indexPath: NSIndexPath) -> UITableViewCell), selectCell: ((indexPath: NSIndexPath) -> ())?, value: Value?)], 
    sectionHeader: (Int -> UITableViewHeaderFooterView)?, 
    sectionFooter: (Int -> UITableViewHeaderFooterView)?
)] = []

然后我可以在设置函数中设置表格并使我的委托方法相当简单

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = dataSource[indexPath.section].cells[indexPath.row].createCell(indexPath:indexPath)
    return cell
}

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return dataSource[section].cells.count
}

func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return dataSource.count
}

我之前在另一个TVC中做过类似的设置

var otherVCDataSource: [[ (type: DetailSection, createCell: ((indexPath: NSIndexPath) -> UITableViewCell), selectCell: ((indexPath: NSIndexPath) -> ())?)]] = []

此解决方案效果很好。

当我尝试访问其中一个createCell块中的indexPath时,带有sectionHead和footer的当前dataSource会给我一个EXC_BAD_ACCESS。

createCell: {
    (indexPath) in
    let cell:CompactExerciseCell = self.tableView.dequeueReusableCellWithIdentifier(self.compactExerciseCellName, forIndexPath:indexPath) as! CompactExerciseCell
    cell.nameLabel.text = "\(indexPath.row)"
    cell.layoutMargins = UIEdgeInsetsZero
    return cell
}

该应用总是崩溃

self.tableView.dequeueReusableCellWithIdentifier(self.compactExerciseCellName, forIndexPath:indexPath)

我在这里缺少什么?为什么我不能在旧结构中正常工作时访问新结构中的indexPath?这个元组和数组之间的内存管理有什么不同?

更新:

所以我有一个截止日期,最后我不得不放弃并重新编写数据结构。

我的第一次尝试是,而不是将indexPath作为参数发送,发送行和部分重建块内的indexPath 。这适用于数据结构内部的所有内容,但如果我在单元格上单击另一个视图控制器,则在下一个VC中出现单元格时,我得到另一个非常奇怪的崩溃(一些malloc错误,这在我使用ARC时很奇怪)。

我也试图在这次崩溃中四处搜寻,但没有时间花在这上面,所以我不得不转向另一个解决方案。

而不是这个元组数组[([] ,,)]我做了两个数组;一个用于单元格,一个用于页眉和页脚。这个结构消除了indexPath崩溃的问题,但我仍然遇到下一个VC中的问题,在出列单元格时没有停止崩溃

最终的解决方案或解决方法是使用此扩展程序“安全地”访问单元格创建者和选择器:

extension Array {
    subscript (safe index: Int) -> Element? {
        return indices ~= index ? self[index] : nil
    }
}

tableView委托函数中的return语句基本上如下所示:

return dataSource[safe:indexPath.section]?[safe:indexPath.row]?.createCell?(indexPath: indexPath)

而不是

return dataSource[indexPath.section][indexPath.row].createCell?(indexPath: indexPath)

我无法看到它与下一个VC有什么区别,因为如果执行nil或在数据结构中查找非现有索引时出现问题,则单元格甚至不应该存在但是这仍然解决了我在下一个VC中出现细胞时遇到的问题。

我仍然不知道为什么数据结构的更改和从数组中获取值的安全扩展会有所帮助,如果有人有任何想法,我会很高兴听到它,但我现在不能在解决方案中进行更多实验。我的猜测是值的安全访问以某种方式重新分配了值并阻止它们被释放。也许元组让编译器无法理解值应该保存在内存中,或者我的代码中只有一个幽灵。我希望有一天我可以回过头来仔细研究一下......

1 个答案:

答案 0 :(得分:0)

这不是问题的答案,而是一个解决方法,如果有人最终陷入这个洞并且必须离开:

首先对数组使用此扩展名:

extension Array {
    subscript (safe index: Int) -> Element? {
        return indices ~= index ? self[index] : nil
    }
}

然后在表格视图中,委托函数使用像这样的扩展

let cell = dataSource[safe:indexPath.section]?[safe:indexPath.row]?.createCell?(indexPath: indexPath)

如果这不起作用,请从数据结构中删除元组,您应该有一个可行的解决方案。

我希望你比这更好运这个问题。