问题:
我需要 top populate tableView 以保持加载现有单元格的内容,例如播放视频。
ref.child(live_mode).queryOrderedByKey().queryLimited(toLast: 200).observe(.childAdded, with: {snapshot in
self.posts.insert(PostFeed(uid: uid , profile_image_url: profile_image_url, profile_name: profile_name, post_id: post_id, post_title: post_title, post_text: post_text, post_type: post_type, youtube_video_url: youtube_video_url, youtube_video_id: youtube_video_id, youtube_image_url: youtube_image_url, time_stamp: time_stamp, like_count: "0"), at: 0)
self.tableView.insertRows(at: [IndexPath.init(row: 0, section: 0)], with: .automatic)
})
上述方法的问题是在分配标签时,单元格索引路径都是一样的
extension ChatViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if(posts[indexPath.row].post_type == "text"){
let textCell = tableView.dequeueReusableCell(withIdentifier: "TextTableViewCell", for: indexPath) as! TextTableViewCell
textCell.mainContentView.backgroundColor = .appBackgroundColor
let profileImageURL = posts[indexPath.row].profile_image_url
textCell.profileImageView.layer.borderWidth = 1.0
textCell.profileImageView.layer.masksToBounds = false
textCell.profileImageView.layer.borderColor = UIColor.white.cgColor
textCell.profileImageView.layer.cornerRadius = textCell.profileImageView.frame.size.width / 2
textCell.profileImageView.clipsToBounds = true
textCell.profileImageView.af_setImage(withURL: URL(string: profileImageURL)!, placeholderImage: avatar_placeholder, filter: nil, imageTransition: .crossDissolve(0.5), runImageTransitionIfCached: true, completion: nil)
textCell.usernameLabel.text = posts[indexPath.row].profile_name
textCell.textBodyTextView.text = posts[indexPath.row].post_text
textCell.usernameLabel.font = .sfProMedium(ofSize: 14)
textCell.usernameLabel.textColor = .systemGray
textCell.textBodyTextView.font = .sfProSemiBold(ofSize: 15)
textCell.textBodyTextView.textColor = .label
textCell.shareButton.addTarget(self, action: #selector(shareButtonTap(sender:)), for: .touchUpInside)
textCell.shareButton.tag = indexPath.row
textCell.elipsesButton.addTarget(self, action: #selector(elipsesButtonTap(sender:)), for: .touchUpInside)
textCell.elipsesButton.tag = indexPath.row
return textCell
}else{
print("print loadign cll: ", indexPath.row)
let videoCell = tableView.dequeueReusableCell(withIdentifier: "VideoTableViewCell", for: indexPath) as! VideoTableViewCell
videoCell.mainContentView.backgroundColor = .appBackgroundColor
let profileImageURL = posts[indexPath.row].profile_image_url
let youtubeImageURL = posts[indexPath.row].youtube_image_url
let yt_video_id = posts[indexPath.row].youtube_video_id
videoCell.profileImageView.layer.borderWidth = 1.0
videoCell.profileImageView.layer.masksToBounds = false
videoCell.profileImageView.layer.borderColor = UIColor.white.cgColor
videoCell.profileImageView.layer.cornerRadius = videoCell.profileImageView.frame.size.width / 2
videoCell.profileImageView.clipsToBounds = true
videoCell.usernameLabel.text = posts[indexPath.row].profile_name
videoCell.textBodyTextView.text = posts[indexPath.row].post_title
videoCell.usernameLabel.font = .sfProMedium(ofSize: 14)
videoCell.usernameLabel.textColor = .systemGray
videoCell.textBodyTextView.font = .sfProSemiBold(ofSize: 15)
videoCell.textBodyTextView.textColor = .label
videoCell.yt_thumbnail_image.isHidden = false
let recognizer = UITapGestureRecognizer(target: self, action: #selector(handleYTTap(_:)))
videoCell.yt_thumbnail_image.tag = indexPath.row
videoCell.yt_thumbnail_image.isUserInteractionEnabled = true
videoCell.yt_thumbnail_image.addGestureRecognizer(recognizer)
recognizer.delegate = self
recognizer.view?.tag = indexPath.row
videoCell.shareButton.addTarget(self, action: #selector(shareButtonTap(sender:)), for: .touchUpInside)
videoCell.shareButton.tag = indexPath.row
videoCell.elipsesButton.addTarget(self, action: #selector(elipsesButtonTap(sender:)), for: .touchUpInside)
videoCell.elipsesButton.tag = indexPath.row
videoCell.elipsesButton.isUserInteractionEnabled = true
videoCell.logoLoadingImageView.isHidden = true
videoCell.playerView.isHidden = true
videoCell.playerView.delegate = self
videoCell.playerView.tag = indexPath.row
videoCell.profileImageView.af_setImage(withURL: URL(string: profileImageURL)!, placeholderImage: avatar_placeholder, filter: nil, imageTransition: .crossDissolve(0.5), runImageTransitionIfCached: true, completion: nil)
videoCell.yt_thumbnail_image.af_setImage(withURL: URL(string: youtubeImageURL)!, placeholderImage: thumbnail_placeholder, filter: nil, imageTransition: .crossDissolve(0.5), runImageTransitionIfCached: false, completion: nil)
return videoCell
}
return UITableViewCell()
}
输出:
单元格索引路径:[0, 0] 单元格索引路径:[0, 0] 单元格索引路径: [0, 0] 单元格索引路径:[0, 0] 单元格索引路径:[0, 0] 单元格索引 路径:[0, 0] 单元格索引路径:[0, 0] 单元格索引路径:[0, 0]
通过使用 insertRows 但保持唯一的 indexPath.row 值来 top load tableView 的正确方法是什么?
tableView.reloadData() 给我正确的唯一索引,但没有提供顶部加载 tableView 的能力,以避免刷新单元格数据,例如在单元格中播放视频。
伪代码:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
customCounter = customCounter + 1
let cellTag = customCounter
print("cell index tag: ", cellTag)
}
我也试过 self.posts.count - 1,但索引在初始加载时没有正确显示。当我滚动到底部然后回到顶部时,它们就位了。
self.tableView.insertRows(at: [IndexPath.init(row: self.posts.count - 1, section: 0)], with: .automatic)
当你打电话
self.tableView.insertRows(at: [IndexPath.init(row: 0, section: 0)], with: .automatic)
您指定所有索引路径都在 0,0 - 这就是为什么您在 cellForRow 方法中看到结果的原因。您总是在索引 0 处插入单元格,这是预期的,也是预期的行为。
当您像您所说的那样调用 reloadData 时,它将重新加载所有单元格,您将获得正确的索引。但是,您依赖于当前出队单元格中值的索引路径。这是行不通的,因为您不应该在单元格和索引路径之间添加关系。
来自docs:
表视图维护一个队列或 UITableViewCell 对象列表 数据源已标记为重用。从您的数据中调用此方法 当要求为表视图提供新单元格时,源对象。 如果一个可用的单元格可用,则此方法使现有单元格出列或创建一个 使用您之前注册的类或 nib 文件的新文件。
这意味着当你做
textCell.shareButton.tag = indexPath.row
您的单元格 shareButton.tag 将包含当前索引路径,但单元格将被重复使用,稍后您将设置一个不代表模型中实际位置的标签(这是您所期望的) .
因此,与其尝试依赖标签来确定点击了哪个按钮,不如依赖按钮所在的单元格。如果您可以获得该单元格,那么您可以调用
indexPathForCell
,这将为您提供当前的索引路径给定单元格的 - 然后您可以使用它来制作指向您的模型的地图。
检查这个答案了解更多信息。