UITableViewDiffableDataSource 不是 deinit
Posted
技术标签:
【中文标题】UITableViewDiffableDataSource 不是 deinit【英文标题】:UITableViewDiffableDataSource are not deinit 【发布时间】:2022-01-21 14:39:46 【问题描述】:我想在我的项目中使用组合并面对问题。 这是 ViewController 的代码
import Combine
import UIKit
class ProfileDetailsController: ViewController
//
// MARK: - Views
@IBOutlet private var tableView: UITableView!
// MARK: - Properties
private typealias DataSource = UITableViewDiffableDataSource<ProfileDetailsSection, ProfileDetailsRow>
private typealias Snapshot = NSDiffableDataSourceSnapshot<ProfileDetailsSection, ProfileDetailsRow>
@Published private var data: [ProfileDetailsSectionModel] =
return ProfileDetailsSection.allCases.map ProfileDetailsSectionModel(section: $0, data: $0.rows)
()
private lazy var dataSource: DataSource =
let dataSource = DataSource(tableView: tableView) tableView, _, model in
let cell = tableView.dequeueReusableCell(withIdentifier: TextFieldTableCell.name) as! TextFieldTableCell
cell.delegate = self
cell.setData(model: model)
return cell
dataSource.defaultRowAnimation = .fade
return dataSource
()
// MARK: - Setup binding
extension ProfileDetailsController
override func setupBinding()
tableView.registerCellXib(cell: TextFieldTableCell.self)
$data.receive(on: RunLoop.main).sink [weak self] models in
let sections = models.map $0.section
var snapshot = Snapshot()
snapshot.appendSections(sections)
models.forEach snapshot.appendItems($0.data, toSection: $0.section)
self?.dataSource.apply(snapshot, animatingDifferences: true)
.store(in: &cancellable)
// MARK: - Cell delegates
extension ProfileDetailsController: TextFieldTableCellDelegate
func switcherAction()
这是单元格的代码。
import UIKit
protocol TextFieldTableCellData
var placeholder: String? get
protocol TextFieldTableCellDelegate: NSObjectProtocol
func switcherAction()
class TextFieldTableCell: TableViewCell
//
// MARK: - Views
@IBOutlet private var textField: ZWTextField!
// MARK: - Properties
public weak var delegate: TextFieldTableCellDelegate?
override class var height: CGFloat
return 72
// MARK: - Public method
extension TextFieldTableCell
func setData(model: TextFieldTableCellData)
textField.placeholder = model.placeholder
ViewController 的deinit
未被调用。
但是当我将此代码用于 ViewController 时
import UIKit
class ProfileDetailsController: ViewController
//
// MARK: - Views
@IBOutlet private var tableView: UITableView!
// MARK: - Properties
@Published private var data: [ProfileDetailsSectionModel] =
return ProfileDetailsSection.allCases.map ProfileDetailsSectionModel(section: $0, data: $0.rows)
()
// MARK: - Startup
extension ProfileDetailsController
override func startup()
tableView.dataSource = self
tableView.registerCellXib(cell: TextFieldTableCell.self)
// MARK: - Startup
extension ProfileDetailsController: UITableViewDataSource
func numberOfSections(in tableView: UITableView) -> Int
return data.count
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
return data[section].data.count
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
let model = data[indexPath.section].data[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: TextFieldTableCell.name) as! TextFieldTableCell
cell.delegate = self
cell.setData(model: model)
return cell
// MARK: - Cell delegates
extension ProfileDetailsController: TextFieldTableCellDelegate
func switcherAction()
一切都很好。 deinit
打来电话。我尝试将 dataSource 设置为可选并将其设置为零 deinit
,结果相同。只有当我评论这一行时才会调用组合 deinit:
cell.delegate = self
有谁知道怎么回事? Xcode 13.2 ios 15.2
【问题讨论】:
这不是答案,但请注意您的代码是错误的。您不应该制作新的快照;您应该获取并修改现有数据的快照。 另外protocol TextFieldTableCellDelegate: NSObjectProtocol
是错误的。这应该是 AnyObject。同样,这不是答案,只是观察。
【参考方案1】:
Combine 的东西完全是红鲱鱼。这就是你找不到问题的原因;你找错地方了。问题在于老式数据源和可区分数据源之间的区别。问题出在这里:
private lazy var dataSource: DataSource = // *
let dataSource = DataSource(tableView: tableView) tableView, _, model in
let cell = tableView.dequeueReusableCell(withIdentifier: TextFieldTableCell.name) as! TextFieldTableCell
cell.delegate = self // *
我已为有问题的行加注星标:
一方面,您(self
,视图控制器)保留了dataSource
。
另一方面,您为数据源提供了一个单元格提供程序函数,您在其中提到了self
。
这是一个保留循环!你需要打破这个循环。改变
let dataSource = DataSource(tableView: tableView) tableView, _, model in
到
let dataSource = DataSource(tableView: tableView) [weak self] tableView, _, model in
(这将编译,因为虽然self
现在是可选的,但cell.delegate
也是。)
【讨论】:
以上是关于UITableViewDiffableDataSource 不是 deinit的主要内容,如果未能解决你的问题,请参考以下文章