RxCocoa/RxSwift在访问TableViewDataSourceNotSet tableView(_:cell



我使用RxCocoa和RxSwift来渲染UITableView对由BehaviorRelay提供的数组。绑定数据的代码如下:

// MyViewModel:
var itemList = BehaviorRelay(value: [MyItem]())
...
func loadData() {
var items = [...] // load items
itemList.accept(items)
}
// ==========
// MyView:
var viewModel = MyViewModel()
func bindData() {
viewModel.itemList.bind(to: tableView.rx.items) { table, index, item in
if item.type == ... {
... // pick cell type based on the item metadata
} else {
let cell = table.dequeueReusableCell(withIdentifier: "MyItemCell") as? MyItemCell {
cell.bindItem(item)
return cell
}
return new UITableViewCell()
}).disposed(by: viewModel.disposeBag)
}
// ==========

在大多数情况下,它工作得很好,但在一些罕见的情况下,我不能用以下堆栈跟踪重现应用程序崩溃,由几个Firebase使用报告:

Crashed: com.apple.main-thread
0  libswiftCore.dylib             0x37d7c _assertionFailure(_:_:file:line:flags:) + 312
1  mycoolapp                      0x8aa968 @objc TableViewDataSourceNotSet.tableView(_:cellForRowAt:) + 84 (RxCocoa.swift:84)
2  mycoolapp                      0x8aae30 @objc RxTableViewDataSourceProxy.tableView(_:cellForRowAt:) + 64 (RxTableViewDataSourceProxy.swift:64)
3  UIKitCore                      0x14b75c -[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:] + 808
4  UIKitCore                      0x219c9c -[UITableView _createPreparedCellForRowAtIndexPath:willDisplay:] + 68
5  UIKitCore                      0x219884 -[UITableView _heightForRowAtIndexPath:] + 124
6  UIKitCore                      0x219720 -[UISectionRowData heightForRow:inSection:canGuess:] + 176
7  UIKitCore                      0x44c328 -[UITableViewRowData heightForRow:inSection:canGuess:adjustForReorderedRow:] + 228
8  UIKitCore                      0x5952c -[UITableViewRowData rectForRow:inSection:heightCanBeGuessed:] + 304
9  UIKitCore                      0x44b8b0 -[UITableViewRowData rectForGlobalRow:heightCanBeGuessed:] + 112
10 UIKitCore                      0x14b378 -[UITableView _prefetchCellAtGlobalRow:aboveVisibleRange:] + 240
11 UIKitCore                      0x14b264 __48-[UITableView _configureCellPrefetchingHandlers]_block_invoke + 52
12 UIKitCore                      0x2186a8 -[_UITableViewPrefetchContext updateVisibleIndexRange:withContentOffset:] + 2100
13 UIKitCore                      0x81be8 -[UITableView _updateCycleIdleUntil:] + 168
14 UIKitCore                      0x811ac ___UIUpdateCycleNotifyIdle_block_invoke + 612
15 libdispatch.dylib              0x2460 _dispatch_call_block_and_release + 32
16 libdispatch.dylib              0x3f88 _dispatch_client_callout + 20
17 libdispatch.dylib              0x127f4 _dispatch_main_queue_drain + 928
18 libdispatch.dylib              0x12444 _dispatch_main_queue_callback_4CF + 44
19 CoreFoundation                 0x9a6c8 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 16
20 CoreFoundation                 0x7c02c __CFRunLoopRun + 2036
21 CoreFoundation                 0x80eb0 CFRunLoopRunSpecific + 612
22 GraphicsServices               0x1368 GSEventRunModal + 164
23 UIKitCore                      0x3a1668 -[UIApplication _run] + 888
24 UIKitCore                      0x3a12cc UIApplicationMain + 340
25 mycoolapp.                     0x1d8564 main + 23 (AppDelegate.swift:23)
26 ???                            0x1b3d9c960 (Missing)

崩溃很难重现(我不能),但它影响了多个用户。bindData方法在viewDidLoad被调用一次,我在每个页面外观上调用loadData(将出现,从另一个页面或应用程序激活停用返回),但不清楚为什么它崩溃以及如何复制/修复它。

崩溃来自TableViewDataSourceNotSet,这似乎是由RxCocoa/RxSwift框架设置的,当请求一个项目的单元格时崩溃。我没有在任何地方显式设置自定义数据源。有什么办法可以防止这种情况发生吗?

bindData方法在每个页面外观(willAppear)上调用,但不清楚为什么它崩溃以及如何复制/修复它。

以上是一个危险信号。您不应该在每个页面外观上都进行绑定。导致解除绑定然后重新绑定的最佳情况。这可能导致系统在某些地方出错,表视图从先前安装的数据源调用numberOfRowsInSection,然后在TableViewDataSourceNotSet对象上调用cellForRowAt

你的绑定应该只发生一次。通常在viewDidLoad。

最新更新