結論
クロージャが二重になる場合、どちらのクロージャでも self
を弱参照でキャプチャする必要がある
環境
- Xcode 12.5.1(12E507)
- RxSwift 5.1.3
- RxDataSources 4.0.1
事例
-
UICollectionView
のCellProvider
内部で購読処理を行う
アンチパターン
self.dataSource = UICollectionViewDiffableDataSource<PseudoSection, PseudoItem>(collectionView: collectionView, cellProvider: { (collectionView: UICollectionView, indexPath: IndexPath, item: PseudoItem) -> UICollectionViewCell? in {
if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PseudoCellIdentifier", for: indexPath) {
cell.someSignal
.emit(onNext: { [weak self] _ in
self?.someRelay.accept(())
})
.disposed(by: cell.disposeBag)
return cell
}
return nil
}
- 一見
self
を弱参照しているためメモリリークは発生しないように見える - 実際にはメモリリークが発生する
-
[weak self]
でキャプチャされるself
がCellProvider
クロージャ内で強参照扱いになっている?
修正
self.dataSource = UICollectionViewDiffableDataSource<PseudoSection, PseudoItem>(collectionView: collectionView, cellProvider: { [weak self](collectionView: UICollectionView, indexPath: IndexPath, item: PseudoItem) -> UICollectionViewCell? in {
if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PseudoCellIdentifier", for: indexPath) {
cell.someSignal
.emit(onNext: { [weak self] _ in
self?.someRelay.accept(())
})
.disposed(by: cell.disposeBag)
return cell
}
return nil
}
-
CellProvider
クロージャの内部でself
を弱参照でキャプチャするように - 特段
guard
などでオプショナルを外さなくてもこのままでOK