Ios 为什么我们需要由dequeueReusableCell func获得的向上转换单元?
事实上,我很困惑Ios 为什么我们需要由dequeueReusableCell func获得的向上转换单元?,ios,swift,uicollectionview,Ios,Swift,Uicollectionview,事实上,我很困惑 override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! MessageCell
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
}
我应该将单元格向上转换为reuseIdentifier暗示的类。因此,事实证明(在我的例子中),DequeReusablecell函数的结果不是MessageCell类,即使我已经准确地注册了它
collectionView?.register(MessageCell.self, forCellWithReuseIdentifier: cellId)
此外,当我试图看到它是真实的而不是MessageCell实例时
cell.isKind(of: MessageCell.self)
这是真的。但同时,当我试图访问MessageCell类的实例属性时,它抛出一个错误“类型为'UICollectionViewCell'的值没有成员'message”
但参考称:
将委托方法中的相应视图出列后,
配置其内容并将其返回到集合视图以供使用
从UICollectionViewDataSource的引用:
此方法的实现负责创建,
配置并返回给定项的相应单元格。
你可以通过打电话给
集合的dequeueReuseAbleCell(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
}
}
为了提高内存效率,可以使用dequeueReusable。它在较低级别的工作方式我的朋友对此有详细的解释
我希望它能回答您的问题。如果我没记错的话,isKindOf将检查对象是否可以成功铸造为该类型。但实际上并不是这样。您需要自己完成这项工作,因为只有您知道您已为该ReuseIdentifier注册的类型。请重新查看我的问题种类(of:)返回一个布尔值,该值指示接收方是给定类的实例还是从该类继承的任何类的实例。MessageCell看起来像什么?这是生成时和运行时发生的情况之间的差异。dequeue函数的定义表示它返回一个UICollectionView单元格,这意味着它也可以是MessageCell所在的子类。因此,在构建时,编译器不知道将返回什么(没有进行编译来确定这一点),因此必须向下转换到正确的类型。但是,在运行时,系统确切地知道它是什么,因此可以确定正确的类型。