如何正确管理精心设计的 Collection View cellForItemAt 方法?
How to properly manage elaborate Collection View cellForItemAt method?
我是一个相当新的开发人员,我有一些很长的 cellForItemAt 方法。我觉得我错过了一些重要的东西。
在这个 ViewController 中,我有一个分段控件,它使用布尔值 taskView
属性.
过滤数据
这是我的 cellForItemAt 调用的样子:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: TaskCell.reuseIdentifier, for: indexPath) as! TaskCell
//SwipeCell Delegate
cell.delegate = self
var transactionResults: Results<Transaction>
if taskView {
transactionResults = unclearedTransactionsToDate
} else {
transactionResults = allTransactions
}
cell.configureCollectionViewCells(indexPath, transactionResults)
let balanceAtDate: Double = realm.objects(Transaction.self).filter("transactionDate <= %@", transactionResults[indexPath.item].transactionDate).sum(ofProperty: "transactionAmount")
cell.balanceLabel.attributedText = balanceAtDate.toAttributedString(size: 9, offset: 6)
if transactionResults[indexPath.item].isCleared == false && !taskView {
cell.amountLabel.textColor = .lightGray
cell.subcategoryLabel.textColor = .lightGray
cell.dateLabel.textColor = .lightGray
cell.balanceLabel.textColor = .lightGray
cell.circleView.backgroundColor = .lightGray
} else {
cell.subcategoryLabel.textColor = .black
cell.dateLabel.textColor = .black
cell.balanceLabel.textColor = .black
cell.circleView.backgroundColor = UIColor(rgb: transactionResults[indexPath.item].transactionCategory!.categoryColor)
}
return cell
}
}
在我的 configureCollectionViewCells
方法中我有:
func configureCollectionViewCells(_ indexPath: IndexPath, _ transaction: Results<Transaction>) {
imageView.image = UIImage(named: transaction[indexPath.item].transactionCategory!.categoryName)
imageView.tintColor = .white
circleView.backgroundColor = UIColor(rgb: transaction[indexPath.item].transactionCategory!.categoryColor)
subcategoryLabel.textColor = .black
dateLabel.textColor = .black
balanceLabel.textColor = .black
subcategoryLabel.text = transaction[indexPath.item].transactionSubCategory?.subCategoryName
amountLabel.attributedText = transaction[indexPath.item].transactionAmount.toAttributedString(size: 9, offset: 6)
let formatter = DateFormatter()
formatter.dateFormat = "MMMM dd, yyyy"
let dateString = formatter.string(from: transaction[indexPath.item].transactionDate)
dateLabel.text = dateString
if transaction[indexPath.item].transactionAmount > 0 {
amountLabel.textColor = UIColor(rgb: Constants.green)
} else {
amountLabel.textColor = UIColor(rgb: Constants.red)
}
}
代码有效,但我感觉它没有正确实现。有人可以就如何管理如此冗长的功能给我一些建议(请记住我是编程新手)吗?我觉得我错过了几个概念。
有些人刚刚说“把所有东西都扔进 cellForItemAt”,有些人在 cellForItemAt 中只有 3 行。
我想也许我应该覆盖 collectionView 单元格中的 layoutSubviews
方法并在那里实现一些代码。
非常感谢任何一般或具体的建议。我也有兴趣研究是否有人有关于该主题的任何资源。
提前致谢。
你所做的事情本身并没有“错”。然而,有一种观点认为,理想情况下,cellForRowAt
应该对细胞的内部界面一无所知。此 (cellForRowAt
) 是 数据源 。它应该只将 data 交给单元格。您有一个单元格子类 (TaskCell),所以它只需要一些方法或属性来告知它数据是什么,然后单元格应该根据这些设置自行格式化并填充自己的界面。
如果将所有格式化和配置代码都移到 cell 子类中,cellForRowAt
实现会更短、更清晰、更清晰,分工也会更合适。
为了支持这一理念,我只想补充一点,Apple 在 iOS14 中采用了它,其中一个单元格现在可以拥有一个 UIContentConfiguration 对象,该对象的工作是从cellForRowAt
进入单元格的 contentView
。因此,例如,而不是说(对于 table 视图单元格)cell.textLabel.text = "howdy"
你说 configuration.text = "howdy"
并让配置对象担心接口中可能涉及 UILabel 的事实。
我是一个相当新的开发人员,我有一些很长的 cellForItemAt 方法。我觉得我错过了一些重要的东西。
在这个 ViewController 中,我有一个分段控件,它使用布尔值 taskView
属性.
这是我的 cellForItemAt 调用的样子:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: TaskCell.reuseIdentifier, for: indexPath) as! TaskCell
//SwipeCell Delegate
cell.delegate = self
var transactionResults: Results<Transaction>
if taskView {
transactionResults = unclearedTransactionsToDate
} else {
transactionResults = allTransactions
}
cell.configureCollectionViewCells(indexPath, transactionResults)
let balanceAtDate: Double = realm.objects(Transaction.self).filter("transactionDate <= %@", transactionResults[indexPath.item].transactionDate).sum(ofProperty: "transactionAmount")
cell.balanceLabel.attributedText = balanceAtDate.toAttributedString(size: 9, offset: 6)
if transactionResults[indexPath.item].isCleared == false && !taskView {
cell.amountLabel.textColor = .lightGray
cell.subcategoryLabel.textColor = .lightGray
cell.dateLabel.textColor = .lightGray
cell.balanceLabel.textColor = .lightGray
cell.circleView.backgroundColor = .lightGray
} else {
cell.subcategoryLabel.textColor = .black
cell.dateLabel.textColor = .black
cell.balanceLabel.textColor = .black
cell.circleView.backgroundColor = UIColor(rgb: transactionResults[indexPath.item].transactionCategory!.categoryColor)
}
return cell
}
}
在我的 configureCollectionViewCells
方法中我有:
func configureCollectionViewCells(_ indexPath: IndexPath, _ transaction: Results<Transaction>) {
imageView.image = UIImage(named: transaction[indexPath.item].transactionCategory!.categoryName)
imageView.tintColor = .white
circleView.backgroundColor = UIColor(rgb: transaction[indexPath.item].transactionCategory!.categoryColor)
subcategoryLabel.textColor = .black
dateLabel.textColor = .black
balanceLabel.textColor = .black
subcategoryLabel.text = transaction[indexPath.item].transactionSubCategory?.subCategoryName
amountLabel.attributedText = transaction[indexPath.item].transactionAmount.toAttributedString(size: 9, offset: 6)
let formatter = DateFormatter()
formatter.dateFormat = "MMMM dd, yyyy"
let dateString = formatter.string(from: transaction[indexPath.item].transactionDate)
dateLabel.text = dateString
if transaction[indexPath.item].transactionAmount > 0 {
amountLabel.textColor = UIColor(rgb: Constants.green)
} else {
amountLabel.textColor = UIColor(rgb: Constants.red)
}
}
代码有效,但我感觉它没有正确实现。有人可以就如何管理如此冗长的功能给我一些建议(请记住我是编程新手)吗?我觉得我错过了几个概念。
有些人刚刚说“把所有东西都扔进 cellForItemAt”,有些人在 cellForItemAt 中只有 3 行。
我想也许我应该覆盖 collectionView 单元格中的 layoutSubviews
方法并在那里实现一些代码。
非常感谢任何一般或具体的建议。我也有兴趣研究是否有人有关于该主题的任何资源。
提前致谢。
你所做的事情本身并没有“错”。然而,有一种观点认为,理想情况下,cellForRowAt
应该对细胞的内部界面一无所知。此 (cellForRowAt
) 是 数据源 。它应该只将 data 交给单元格。您有一个单元格子类 (TaskCell),所以它只需要一些方法或属性来告知它数据是什么,然后单元格应该根据这些设置自行格式化并填充自己的界面。
如果将所有格式化和配置代码都移到 cell 子类中,cellForRowAt
实现会更短、更清晰、更清晰,分工也会更合适。
为了支持这一理念,我只想补充一点,Apple 在 iOS14 中采用了它,其中一个单元格现在可以拥有一个 UIContentConfiguration 对象,该对象的工作是从cellForRowAt
进入单元格的 contentView
。因此,例如,而不是说(对于 table 视图单元格)cell.textLabel.text = "howdy"
你说 configuration.text = "howdy"
并让配置对象担心接口中可能涉及 UILabel 的事实。