UITableViewDiffableDataSource 不是 deinit
UITableViewDiffableDataSource are not deinit
我想在我的项目中使用 Combine 并遇到问题。
这是 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: [=10=], data: [=10=].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 { [=10=].section }
var snapshot = Snapshot()
snapshot.appendSections(sections)
models.forEach { snapshot.appendItems([=10=].data, toSection: [=10=].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: [=12=], data: [=12=].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
上将其设置为 nil,结果相同。仅当我评论此行时才调用 Combine deinit:
cell.delegate = self
有人知道怎么回事吗?
Xcode 13.2 iOS 15.2
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
也是。)
我想在我的项目中使用 Combine 并遇到问题。 这是 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: [=10=], data: [=10=].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 { [=10=].section }
var snapshot = Snapshot()
snapshot.appendSections(sections)
models.forEach { snapshot.appendItems([=10=].data, toSection: [=10=].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: [=12=], data: [=12=].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
上将其设置为 nil,结果相同。仅当我评论此行时才调用 Combine deinit:
cell.delegate = self
有人知道怎么回事吗? Xcode 13.2 iOS 15.2
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
也是。)