自定义 UITableview 单元格偶尔会在其他单元格之上重叠/复制 [英] Custom UITableview Cell Occasionally Overlapping/Reproducing On Top Of Other Cell

查看:33
本文介绍了自定义 UITableview 单元格偶尔会在其他单元格之上重叠/复制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在这里遇到了非常奇怪的问题.

Really strange problem I'm having here.

基本上,用户来到一个附有 TableView 的视图.调用后端获取一些数据,并在该数据的完成块中提供给 TableView 以显示.

Basically, the user comes to a View that has a TableView attached to it. There's a call to the backend for some data, and in the completion block of that data is provided to the TableView to display.

在 cellForRow 1 of 4 可重用中,自定义单元格根据某种逻辑出列,然后调用该单元格的配置方法.

In cellForRow 1 of 4 reusable, custom cells is dequeued, based on some logic, and then a configure method for that cell is called.

这就是它变得棘手的地方:某些单元格可能需要进一步的异步调用(为其自定义显示获取更多数据),因此需要调用 tableView.reloadRows ......那么,这两个最好解释发生了什么截图:

Here's where it gets tricky: Some of the cells might require further asynchronous calls (to fetch more data for their custom displays), thus required a tableView.reloadRows call...What's happening, then, is best explained by these two screenshots:

在第一个单元格中,有没有想过你会为克朗代克酒吧做什么?"复制在演员的自我管理"单元格之上,因为包含 Twitter 信息的单元格需要额外的异步调用来获取该数据.

In the first one, that cell with "Ever wonder what YOU'D do for a klondike bar?" is replicated on top of the "Self-Management for Actor's" cell which, as a cell containing Twitter info DID require an additional asynch call to fetch that data.

有什么想法吗?我在 begin/endUpdates 块内运行 tableView.reloadRows 调用,但没有骰子.

Any thoughts? I'm running the tableView.reloadRows call inside of a begin/endUpdates block, but no dice.

cellForRow:

cellForRow:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let postAtIndexPath = posts[indexPath.row]
    let cell: PostCell!

    if postAtIndexPath.rawURL == "twitter.com" {
        cell = tableView.dequeueReusableCell(withIdentifier: "TwitterCell", for: indexPath) as! TwitterCell
    } else if !postAtIndexPath.rawURL.isEmpty {
        cell = tableView.dequeueReusableCell(withIdentifier: "LinkPreviewCell", for: indexPath) as! LinkPreviewCell
    } else if postAtIndexPath.quotedID > -1 {
        cell = tableView.dequeueReusableCell(withIdentifier: "QuoteCell", for: indexPath) as! QuoteCell
    } else {
        cell = tableView.dequeueReusableCell(withIdentifier: "PostCell", for: indexPath) as! PostCell
    }

    cell.isUserInteractionEnabled = true

    cell.privacyDelegate = self
    cell.shareDelegate = self
    cell.likeDelegate = self
    cell.linkPreviewDelegate = self
    cell.reloadDelegate = self
    postToIndexPath[postAtIndexPath.id] = indexPath

    if parentView == "MyLikes" || parentView == "Trending" {
        cell.privatePostButton.isHidden = true
        cell.privatePostLabel.isHidden = true
    }

    cell.configureFor(post: postAtIndexPath,
                         liked: likesCache.postIsLiked(postId: postAtIndexPath.id),
                         postIdToAttributions: postIdToAttributions,
                         urlStringToOGData: urlStringToOGData,
                         imageURLStringToData: imageURLStringToData)

    cell.contentView.layoutIfNeeded()

    return cell
}

异步 ​​Twitter 调用:

asynch Twitter call:

private func processForTwitter(og: OpenGraph, urlLessString: NSMutableAttributedString, completion:(() -> ())?) {
    let ogURL = og[.url]!
    let array = ogURL.components(separatedBy: "/")
    let client = TWTRAPIClient()
    let tweetID = array[array.count - 1]
    if let tweet = twitterCache.tweet(forID: Int(tweetID)!)  {
        for subView in containerView.subviews {
            subView.removeFromSuperview()
        }

        let tweetView = TWTRTweetView(tweet: tweet as? TWTRTweet, style: .compact)
        containerView.addSubview(tweetView)
        tweetView.translatesAutoresizingMaskIntoConstraints = false
        tweetView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor).isActive = true
        tweetView.topAnchor.constraint(equalTo: containerView.topAnchor).isActive = true
        containerView.leftAnchor.constraint(equalTo: tweetView.leftAnchor).isActive = true
        containerView.rightAnchor.constraint(equalTo: tweetView.rightAnchor).isActive = true
        containerView.isHidden = false
        postText.isHidden = false

    } else {
        client.loadTweet(withID: tweetID, completion: { [weak self] (t, error) in
            if let weakSelf = self {
                if let tweet = t {
                    weakSelf.twitterCache.addTweetToCache(tweet: tweet, forID: Int(tweetID)!)
                }
            }

            if let complete = completion {
                complete()
            }
        })`enter code here`
    }

    if urlLessString.string.isEmpty {
        if let ogTitle = og[.title] {
            postText.text = String(htmlEncodedString: ogTitle)
        }
    } else {
        postText.attributedText = urlLessString
    }
}

tableviewcontroller 中的完成块:

completion block in the tableviewcontroller:

func reload(postID: Int) {

    tableView.beginUpdates()
    self.tableView.reloadRows(at: [self.postToIndexPath[postID]!], with: .automatic)
    tableView.endUpdates()

}

注意:这不会在 100% 的情况下发生,大概是依赖于网络.

NB: this doesn't happen 100% of the time, it is, presumably, network dependent.

推荐答案

事实证明,围绕 estimatedRowHeightreloadRows;解决方案,通过一个切线相关的 SO 问题,是在行高可用时缓存行高,如果在 heightForRow 中可用,则返回该行高.

Turns out there's weird, or at least I don't understand it, behavior around estimatedRowHeight and reloadRows; solution, via a tangentially related SO question, was to cache the row heights as they become available and return that if available in heightForRow.

我猜它不会在重新加载时重新计算高度或其他东西?真的不明白具体为什么会这样,但我很高兴它确实如此!

I guess it doesn't recalculate the heights, or something, on a reload? Really don't understand specifically WHY this works, but I'm happy it does!

这篇关于自定义 UITableview 单元格偶尔会在其他单元格之上重叠/复制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆