我有一个UITableViewCell
子类,它有一个通过代码创建的自定义子视图。现在问题是我试图滚动UITableView 少跳跃。
以下是设置方法。
CustomSubview
是通过代码UIView
BasePostCell
是UITableViewCell
是UITableViewCell
子类,用作其他一些单元格的基础UserPostCell
,TextPostCell
和DiscussionPostCell
是使用BasePostCell
生成的xib
子类,因为我不知道是否已知有可能以某种方式将xib继承到另一个xib,我只使用viewWithTag
和awakeFromNib
将子视图连接到各自的变量,您将在下面的示例代码中看到NSLayoutConstraints
进行设置的,从我阅读/研究过的内容比我通过代码创建视图然后只需手动计算高度和宽度要慢得多每个细胞。如果可以的话,我想,但是现在我没有这样的奢侈,因为真正的代码库中有大约20多个不同的单元格。 (这只是一个示例代码)我想要以某种方式改变的课程是CustomSubview
或BasePostCell
;或者如果有更好的方法,请告诉我。
这是我的代码
模特
class Post {
var type: PostType = .text
var text: String = ""
var title: String = ""
var displayPhoto: String?
// ... there are other attributes here
enum PostType {
case text, user, discussion
}
}
基础课
class CustomSubview: UIView {
lazy var likeButton: UIButton = {
let button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
button.backgroundColor = .black
button.titleLabel?.font = UIFont(face: .helveticaNeue, style: .regular, size: 14) // this is a helper function of mine
button.setTitleColor(UIColor.white, for: .normal)
button.setTitleColor(UIColor.gray, for: .selected)
return button
}()
// The rest are more or less the same as how likeButton is created
// the most important part is `translatesAutoresizingMaskIntoConstraints`
// should be set to true since I use `NSLayoutConstraints`
lazy var commentButton: UIButton = { ... }()
lazy var shareButton: UIButton = { ... }()
lazy var followButton: UIButton = { ... }()
lazy var answerButton: UIButton = { ... }()
func configure(withType type: PostType) {
// I don't know if this is the right way to do this
self.subviews.forEach { $0.removeFromSuperview() }
switch type {
case .text:
[ self.likeButton, self.commentButton, self.shareButton ].forEach { self.addSubview($0) }
// constraints code block
// code goes something like this
self.addConstraints(NSLayoutConstraint.constraints(
withVisualFormat: "H:|-0-[btnLike(==btnComment)]-0-[btnComment]-0-[btnShare(==btnComment)]-0-|",
options: NSLayoutFormatOptions(),
metrics: nil,
views: ["btnLike": self.likeButton,
"btnComment": self.commentButton,
"btnShare": self.shareButton]))
case .user:
[ self.followButton, self.shareButton ].forEach { self.addSubview($0) }
// insert more constraints code block here
case .discussion:
[ self.answerButton, self.commentButton, self.shareButton ].forEach { self.addSubview($0) }
// insert more constraints code block here
}
}
}
class BasePostCell: UITableViewCell {
// ... there are other subviews but
// only this view is modularly created
var customSubview: CustomSubview?
override func awakeFromNib() {
super.awakeFromNib()
self.customSubview = self.viewWithTag(990) as? CustomSubview
}
func configure(withPost post: Post) {
self.customSubview?.configure(withType: post.type)
}
}
BasePostCell的子类
class UserPostCell: BasePostCell {
var imgDisplayPhoto: UIImageView?
override func awakeFromNib() {
super.awakeFromNib()
self.imgDisplayPhoto = self.viewWithTag(0) as? UIImageView
}
override func configure(withPost post: Post) {
super.configure(withPost: post)
self.imgDisplayPhoto?.image = post.image
}
}
class TextPostCell: BasePostCell {
var lblContent: UILabel?
override func awakeFromNib() {
super.awakeFromNib()
self.lblContent = self.viewWithTag(1) as? UILabel
}
override func configure(withPost post: Post) {
super.configure(withPost: post)
self.lblContent?.text = post.text
}
}
class DiscussionPostCell: BasePostCell {
var lblContent: UILabel?
var lblDiscussionTitle: UILabel?
override func awakeFromNib() {
super.awakeFromNib()
self.lblContent = self.viewWithTag(1) as? UILabel
self.lblDiscussionTitle = self.viewWithTag(2) as? UILabel
}
override func configure(withPost post: Post) {
super.configure(withPost: post)
self.lblContent?.text = post.text
self.lblDiscussionTitle?.text = post.title
}
}
最后在SampleViewController
class SomeViewController: UIViewController {
@IBOutlet var tableView: UITableView!
var posts: [Post] = []
var heightForPost: [IndexPath: CGFloat] = [:]
override func viewDidLoad() {
super.viewDidLoad()
// let's just say I initialized the posts
self.posts = <SomePostsArrayHere>
// ... register nib to tableview codes here.
self.tableView.delegate = self
self.tableView.dataSource = self
self.tableView.reloadData()
}
// ... other implementations
}
// Here is the delegate and dataSource
extension SomeViewController: UITableViewDelegate, UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.posts.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let post = self.posts[indexPath.row]
var postCell: BasePostCell
switch post.type {
case .text:
postCell = tableView.dequeueReusableCell(withIdentifier: "TextPostCell", for: indexPath) as! TextPostCell
case .user:
postCell = tableView.dequeueReusableCell(withIdentifier: "UserPostCell", for: indexPath) as! UserPostCell
case .discussion:
postCell = tableView.dequeueReusableCell(withIdentifier: "DiscussionPostCell", for: indexPath) as! DiscussionPostCell
}
postCell.configure(withPost: post)
return postCell
}
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
self.heightForPost[IndexPath] = cell.frame.size.height
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return self.heightForPost[indexPath] ?? UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return 300
}
}
答案 0 :(得分:1)
我已经建议使用时间分析器来识别问题代码,但我仍然在代码中看到一个禁忌。
在配置单元格时,您始终在configure(withType type: PostType)
上致电CustomSubview
。在那里,你删除子视图和&#34;重建&#34;他们。这不是你应该在可重复使用的单元格中做的事情 - 你不想触摸它们的视图层次结构,你想要做的就是改变它们的内容,例如,更改标签中的文本,更改imageView等中的图像。否则,您不会使用可重复使用的单元格的全部功能。
只需更改BaseClass
以仅配置子视图层次结构,然后在cellForRowAt
中仅设置子视图的内容:
class BasePostCell: UITableViewCell {
// ... there are other subviews but
// only this view is modularly created
var customSubview: CustomSubview?
override func awakeFromNib() {
super.awakeFromNib()
self.customSubview = self.viewWithTag(990) as? CustomSubview
}
func configure(withPost post: Post) {
// don't reconfigure the customView view hierarchy here, it gets called everytime cellForRowAt is called
}
}
class UserPostCell: BasePostCell {
var imgDisplayPhoto: UIImageView?
override func awakeFromNib() {
super.awakeFromNib()
// subviews setup just once here, because for the UserPostCell
// the type of the post will never change
self.customSubview?.configure(withType: .user)
self.imgDisplayPhoto = self.viewWithTag(0) as? UIImageView
}
override func configure(withPost post: Post) {
super.configure(withPost: post)
self.imgDisplayPhoto?.image = post.image
}
}
class TextPostCell: BasePostCell {
var lblContent: UILabel?
override func awakeFromNib() {
super.awakeFromNib()
self.customSubview?.configure(withType: .text)
self.lblContent = self.viewWithTag(1) as? UILabel
}
override func configure(withPost post: Post) {
super.configure(withPost: post)
self.lblContent?.text = post.text
}
}
class DiscussionPostCell: BasePostCell {
var lblContent: UILabel?
var lblDiscussionTitle: UILabel?
override func awakeFromNib() {
super.awakeFromNib()
self.customSubview?.configure(withType: .discussion)
self.lblContent = self.viewWithTag(1) as? UILabel
self.lblDiscussionTitle = self.viewWithTag(2) as? UILabel
}
override func configure(withPost post: Post) {
super.configure(withPost: post)
self.lblContent?.text = post.text
self.lblDiscussionTitle?.text = post.title
}
}