簡體   English   中英

自定義UITableview單元偶爾重疊/再現在其他單元格的頂部

[英]Custom UITableview Cell Occasionally Overlapping/Reproducing On Top Of Other Cell

真的很奇怪,我在這里。

基本上,用戶來到一個附有TableView的View。 有一些數據被調用到后端,並且在數據的完成塊中提供給TableView進行顯示。

在cellForRow 1 of 4可重用,自定義單元格根據某些邏輯出列,然后調用該單元格的配置方法。

這里有些棘手:有些單元格可能需要進一步的異步調用(為自定義顯示獲取更多數據),因此需要一個tableView.reloadRows調用...然后,這兩個截圖最好地解釋了這一點:

錯誤 對

在第一個那個單元格中,“曾經想過你會為克朗代克酒吧做些什么嗎?” 復制在“演員的自我管理”單元格之上,作為包含Twitter信息的單元格,DID需要額外的異步調用來獲取該數據。

有什么想法嗎? 我在begin / endUpdates塊中運行tableView.reloadRows調用,但沒有骰子。

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
}

asynch Twitter電話:

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中的完成塊:

func reload(postID: Int) {

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

}

注意:這不會在100%的時間內發生,大概是網絡依賴的。

我想問題在於計算單元格中存在的組件的大小。 這就像單元格被設計並且在數據可用之前設置了框架以及子視圖。

也許你可以嘗試,

tableView.rowHeight = UITableViewAutomaticDimension tableView.estimatedRowHeight = yourPrefferedHeight

但是你需要確保自動布局約束是正確的,如果所有組件都有高度,單元格可以確定它的高度。

結果發現有一些奇怪的,或者至少我不理解,在estimatedRowHeightreloadRows周圍的行為; 解決方案,通過切向相關的SO問題,緩存行高,因為它們變得可用,並返回如果在heightForRow可用。

我想它不會重新計算重載時的高度或其他東西? 真的不明白為什么這個工作,但我很高興它!

在異步調用之后,而不是tableView.reloadRows嘗試調用:

tableView.beginUpdates()
tableView.setNeedsLayout()
tableView.endUpdates()

似乎數據已填充,但單元格的大小未反映出來。 如果你調用reloadRows我擔心它不會重新計算以下單元格的新位置 - 這意味着如果單元格行3調整到更大的高度,它將變大,但下面的單元格不會被進一步向下推。

我假設在configureFor background / async上processForTwitter 如果是,這就是錯誤。 您的api調用應該在后台,但如果您從緩存中獲取推文,則應該在主線程上和返回單元格之前完成addSubview。 嘗試這樣做,確保在主線程上processForTwitter並將其配置為

   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 {
    // run only this code in background/async

            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)!)
                    }
                }
// completion on main

                if let complete = completion {
  DispatchQueue.main.async {
 complete()

    }   
                }
            })
        }

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

現在序列就像這樣

  1. Cell是第一次加載
  2. 在緩存中找不到推文
  3. processForTwitter異步網絡調用和單元格在沒有適當數據的情況下返回
  4. 異步調用得到推文。 並在主線程上調用完成,導致重新加載
  5. 在主線程上再次調用configure for
  6. 在保留主線程時,在緩存中找到tweet。
  7. 添加你的TWTRTweetView(你還在主線程上),這將在你的單元格返回之前完成。

記住這一點,在CellForIndexPath中返回單元格之前,應該在主線程上添加單元格中用於計算單元格大小的每個組件。

我遇到了類似的問題。

    [self.tableView beginUpdates];
    [self configureDataSource]; // initialization of cells by dequeuing 
    [self.tableView insertSections:[[NSIndexSet alloc] initWithIndex:index] withRowAnimation:UITableViewRowAnimationFade];
    [self.tableView endUpdates];

以及之后

    [self.tableView beginUpdates];
    [self configureDataSource]; // initialization of cells by dequeuing  
    [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:index] withRowAnimation:UITableViewRowAnimationFade];
    [self.tableView endUpdates];

我的TableViewController的兩行重疊。

然后我發現了捕獲的位置。

在beginUpdate和endUpdate之后是兩個為單元格調用的方法:estimatedHeightForRowAtIndexPath和heightForRowAtIndexPath。 但是沒有調用cellForRowAtIndexPath。

其中一個重疊單元格已出列但我只在cellForRowAtIndexPath方法中設置了它的文本/值。 因此,正確計算了單元格高度但是內容不正確。

我的解決方法是在將單元格出列后也設置文本/值。 所以唯一的區別在於我的configureDataSource方法:

    [self.tableView beginUpdates];
    [self configureDataSource]; // init of cells by dequeuing and set its texts/values  
    // delete or insert section
    [self.tableView endUpdates];

(其他可能的解決方法是避免細胞的重新初始化。但是這種初始化細胞的緩存對於具有大量細胞的TableView來說並不好)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM