Reputation: 4746
This is in the same vein as a previous question I here
Basically, UITableView cells would occasionally overlap the data underneath them - I tracked that down to reloadRows acting wonky with estimatedHeight, and my solve was to cache the height when calling willDisplay cell:
and then return that height, or an arbitrary constant if the row hasn't been seen yet, when calling heightForRow
But now the problem is back! Well, a similar one: after propagating a UITableView
with some data, some of it fetched asynchronously, I want to be able to search and repopulate the UITableView.
This data I'm fetching may or may not already be present on the TableView, and in any case I don't consider that - I hit the backend, grab some stuff, and display it.
Except, it gets wonky:
As you can see from the screenshot, there's a cell overlaid on top of another cell with the same content. The TableView only reports there being 2 rows, via numberOfRows
, but the View Hierarchy says there are 3 cells present when I click through to the TableView.
Only thing I can figure is there's some weird race condition or interaction that happens when I reloadRow after fetching the openGraph data.
What gives?
Some code:
Search
fileprivate func search(searchText: String, page: Int) {
postsService.searchPosts(searchText: searchText, page: page) { [weak self] posts, error in
if let weakSelf = self {
if let posts = posts, error == nil {
if !posts.isEmpty {
weakSelf.postListController.configureWith(posts: posts, deletionDelegate: nil, forParentView: "Trending")
weakSelf.page = weakSelf.page + 1
weakSelf.scrollTableViewUp()
} else {
// manually add a "No results found" string to tableFooterView
}
} else {
weakSelf.postListController.configureWith(posts: weakSelf.unfilteredPosts, deletionDelegate: nil, forParentView: "Trending")
weakSelf.scrollTableViewUp()
}
}
}
}
**configureWith*
func configureWith(posts: [Post], deletionDelegate: DeletionDelegate?, forParentView: String) {
self.posts = posts
for post in posts {
//some data pre-processing
if some_logic
if rawURLString.contains("twitter") {
let array = rawURLString.components(separatedBy: "/")
let client = TWTRAPIClient()
let tweetID = array[array.count - 1]
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)!)
}
}
})
}
openGraphService.fetchOGData(url: rawURL, completion: { [weak self] (og, error) in
weakSelf.openGraphService.fetchOGImageData(url: ogImageURL, completion: { (data, response, error) in
if let imageData = data {
weakSelf.imageURLStringToData[ogImageString] = imageData
weakSelf.queueDispatcher.dispatchToMainQueue {
for cell in weakSelf.tableView.visibleCells {
if (cell as! PostCell).cellPost == post {
let cellIndexPath = IndexPath(row: weakSelf.posts.index(of: post)!, section: 0)
weakSelf.tableView.reloadRows(at: [cellIndexPath], with: UITableViewRowAnimation.automatic)
}
}
}
}
})
})
}
self.deletionDelegate = deletionDelegate
self.parentView = forParentView
queueDispatcher.dispatchToMainQueue { [weak self] in
if let weakSelf = self {
weakSelf.tableView.reloadData()
}
}
scrollToPost()
}
Upvotes: 1
Views: 109