为啥我们需要 dequeueReusableCell func 获得的向上转换单元格?
Posted
技术标签:
【中文标题】为啥我们需要 dequeueReusableCell func 获得的向上转换单元格?【英文标题】:Why do we need upcasting cell obtained by dequeueReusableCell func?为什么我们需要 dequeueReusableCell func 获得的向上转换单元格? 【发布时间】:2018-01-17 10:56:25 【问题描述】:我很困惑
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! MessageCell
if let message = messages?[indexPath.item]
cell.message = message
cell.timeLibel
return cell
我应该将单元格向上转换为由重用标识符隐含的类。所以事实证明(在我的情况下) deqeueReusableCell 函数的结果不是 MessageCell 类,即使我已经完全注册了它
collectionView?.register(MessageCell.self, forCellWithReuseIdentifier: cellId)
此外,当我尝试查看它是不是真的 MessageCell 实例时
cell.isKind(of: MessageCell.self)
它返回真。但与此同时,当我尝试访问 MessageCell 类的实例属性时,它会引发错误“'UICollectionViewCell' 类型的值没有成员'消息”
但是参考说:
在您的委托方法中将适当的视图出列后, 配置其内容并返回到collection view中使用。
以及来自 UICollectionViewDataSource 的参考:
您对此方法的实现负责创建, 配置并返回给定项目的适当单元格。 您可以通过调用 集合的 dequeueReusableCell(withReuseIdentifier:for:) 方法 查看并传递对应于单元格的重用标识符 输入你想要的。
为什么我们需要向上转型 let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) ?
这里是 MessageCell 等
class MessageCell: BaseCell
var message: Message?
didSet
nameLabel.text = message?.friend?.name
if let profileImageName = message?.friend?.profileImageName
profileImageView.image = UIImage(named: profileImageName)
messageLabel.text = message?.text
let profileImageView: UIImageView =
let imageView = UIImageView()
imageView.contentMode = .scaleAspectFill
imageView.layer.cornerRadius = 34
imageView.layer.masksToBounds = true
return imageView
()
let dividerLineView: UIView =
let view = UIView()
view.backgroundColor = UIColor(white: 0.5, alpha: 0.5)
return view
()
let nameLabel: UILabel =
let label = UILabel()
label.text = "Mark Zuckerberg"
label.font = UIFont.systemFont(ofSize: 18)
// label.backgroundColor = UIColor.brown
return label
()
let messageLabel: UILabel =
let label = UILabel()
label.text = "Your friends message and something else..."
label.textColor = UIColor.darkGray
label.font = UIFont.systemFont(ofSize: 14)
// label.backgroundColor = UIColor.green
return label
()
let timelabel : UILabel =
let label = UILabel()
label.text = "12:05 pm"
label.font = UIFont.systemFont(ofSize: 16)
label.textAlignment = .right
// label.textColor = UIColor.white
// label.backgroundColor = UIColor.black
return label
()
let hasReadImageView: UIImageView =
let imageView = UIImageView()
imageView.contentMode = .scaleAspectFill
imageView.layer.cornerRadius = 10
imageView.layer.masksToBounds = true
return imageView
()
override func setupViews()
addSubview(profileImageView)
addSubview(dividerLineView)
profileImageView.image = UIImage(named: "zuckprofile")
hasReadImageView.image = UIImage(named: "zuckprofile")
setupContainerView()
addConstraintsWithFormat( "H:|-12-[v0(68)]|", views: profileImageView)
addConstraintsWithFormat( "V:[v0(68)]", views: profileImageView)
addConstraint(NSLayoutConstraint(item: profileImageView, attribute: .centerY, relatedBy: .equal, toItem: self, attribute: .centerY, multiplier: 1, constant: 0))
addConstraintsWithFormat( "H:|-82-[v0]|", views: dividerLineView)
addConstraintsWithFormat( "V:[v0(1)]|", views: dividerLineView)
func setupContainerView()
let containerView = UIView()
addSubview(containerView)
addConstraintsWithFormat("H:|-90-[v0]|", views: containerView)
addConstraintsWithFormat( "V:[v0(50)]", views: containerView)
addConstraint(NSLayoutConstraint(item: containerView, attribute: .centerY, relatedBy: .equal, toItem: self, attribute: .centerY, multiplier: 1, constant: 0))
containerView.addSubview(nameLabel)
containerView.addSubview(messageLabel)
containerView.addSubview(timelabel)
containerView.addSubview(hasReadImageView)
containerView.addConstraintsWithFormat( "H:|[v0][v1(80)]-12-|", views: nameLabel, timelabel )
containerView.addConstraintsWithFormat( "V:|[v0(26)][v1(24)]|", views: nameLabel,messageLabel )
containerView.addConstraintsWithFormat( "H:|[v0]-8-[v1(20)]-12-|", views: messageLabel, hasReadImageView )
containerView.addConstraintsWithFormat("V:[v0(20)]|", views: hasReadImageView)
containerView.addConstraintsWithFormat( "V:|[v0(24)]", views: timelabel)
addConstraint(NSLayoutConstraint(item: nameLabel, attribute: .centerY, relatedBy: .equal, toItem: timelabel, attribute: .centerY, multiplier: 1, constant: -1.4 ))
extension UIView
func addConstraintsWithFormat(_ format: String , views: UIView...)
var viewsDictionary = [String: UIView]()
for (index, view) in views.enumerated()
let key = "v\(index)"
viewsDictionary[key] = view
view.translatesAutoresizingMaskIntoConstraints = false
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: format, options: NSLayoutFormatOptions(), metrics: nil, views: viewsDictionary))
class BaseCell : UICollectionViewCell
let a = 5
override init(frame: CGRect)
super.init(frame: frame)
setupViews()
layer.masksToBounds = true
required init?(coder aDecoder: NSCoder)
fatalError("init(coder:) has not been implemented")
func setupViews()
backgroundColor = UIColor.blue
【问题讨论】:
如果我没记错的话,isKindOf 将检查对象是否可以成功转换为该类型。但它实际上并没有那样投射。您需要自己执行此操作,因为只有您会知道您为该重用标识符注册了什么类型 请再看看我的问题 isKind(of:) 返回一个布尔值,指示接收者是给定类的实例还是从该类继承的任何类的实例。 MessageCell 长什么样子? 这是在构建时和运行时发生的区别。 dequeue 函数的定义说它返回一个 UICollectionView 单元格,这意味着它也可以是 MessageCell 的子类。因此,在构建时,编译器不知道要返回什么(没有进行编译来确定这一点),因此您必须向下转换为正确的类型。然而,在运行时,系统确切地知道它是什么,因此可以确定正确的类型。 【参考方案1】:dequeueReusable 用于提高内存效率。它在较低级别的工作方式我的朋友对此有详细的解释https://medium.com/ios-seminar/why-we-use-dequeuereusablecellwithidentifier-ce7fd97cde8e
我希望它回答了你的问题。
【讨论】:
以上是关于为啥我们需要 dequeueReusableCell func 获得的向上转换单元格?的主要内容,如果未能解决你的问题,请参考以下文章
iOS:UICollectionView 内容重置和 dequeueReusableCell
如何使用 tableView.dequeueReusableCell 以编程方式将单元格样式添加到单元格?
如何在 UITableView 中实现 dequeueReusableCell(withIdentifier:) 的代码?