Swift tableView insertRows 在顶部,同时保持适当的索引

问题描述 投票:0回答:1

问题:

我需要 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)
ios swift uitableview
1个回答
0
投票

当你打电话

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
,这将为您提供当前的索引路径给定单元格的 - 然后您可以使用它来制作指向您的模型的地图。

检查这个答案了解更多信息。

© www.soinside.com 2019 - 2024. All rights reserved.