简体   繁体   中英

weird tableView animation when using insert function

I'm trying to insert number more cells in the table view when the user reaches the bottom of the table. the insert is working fine, but a weird animation is happening when scrolling up.

I tried to add beginUpdates() and endUpdates() before and after the insert() method. but this didn't help. I tried to add tableView.contentInsetAdjustmentBehavior = .never in viewDidLoad and it didn't help.

the code I tried is:

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        if tableView.contentOffset.y >= (tableView.contentSize.height - tableView.frame.size.height) {
            loadMoreCells()
        }

func loadMoreCells() {
       ServerRequests.getDataServerRequest(id: provider.ID, page: page) { (foundEpisodes) in
            if foundEpisodes.count > 0 {
                let previous = self.episodes.count
                self.episodes.insert(contentsOf: foundEpisodes, at: self.episodes.count)
                self.isViewOpen.insert(contentsOf: [Bool](repeatElement(false, count: foundEpisodes.count)), at: self.isViewOpen.count)
                var indexPathsToBeInserted = [IndexPath]()
                for i in previous..<self.episodes.count{
                    indexPathsToBeInserted.append(IndexPath(row: i, section: 0))
                }
                self.tableView.insertRows(at: indexPathsToBeInserted, with: UITableViewRowAnimation.none)
            }
        }
    }

Am I calling the insert in the wrong place? or what is the wrong thing I am doing ?

UPDATE

in viewDidLoad :

tableView.register(UINib(nibName: NIB_NAME, bundle: nil), forCellReuseIdentifier: NIB_IDENTIFIRE)

in cellForRow :

let cell = tableView.dequeueReusableCell(withIdentifier: NIB_IDENTIFIRE, for: indexPath) as! EpisodePerProviderTableViewCell
    cell.setUpCell(tableView: tableView, episode: episodes[indexPath.row], indexPath: indexPath, isViewOpen: isViewOpen)

    return cell

the setUpCell function is:

unc setUpCell(tableView: UITableView, episode: Episode, indexPath: IndexPath, isViewOpen: [Bool]) {
    isMenuVisible = false
    menuView.isHidden = true
    if (isViewOpen[indexPath.row]){
        descriptionLabel.numberOfLines = 100
        moreLessLabel.text = "Less"
    }else{
        descriptionLabel.numberOfLines = 2
        moreLessLabel.text = "More"
    }
    tableView.beginUpdates()
    tableView.endUpdates()

    self.isViewOpen = isViewOpen
    self.indexPath = indexPath
    self.tableView = tableView
    self.episode = episode
    arrowButton.transform = .identity

    //set up cell content
    if let myDate = dateFormatter.date(from: episode.episodePostDate) {
        postedDate.text = dateFormatter.timeSince(from: myDate as NSDate)
    }
    episodeImage.windless.start()
    episodeImage.sd_setImage(with: URL(string: episode.episodeImageUrl ?? ""), placeholderImage: UIImage(named: "FalloundPlayerLogo")) { (providerImage, error, SDImageCacheType, url) in
        self.episodeImage.windless.end()
    }
    title.text = episode.episodeName
    durationLabel.text = "".formatted(time: Float(episode.episodeDuration), withoutSec: true)
    descriptionLabel.text = episode.episodeDescription
}

I think the problem is because loadMoreCells is called too many times.

try using this check instead of willDisplay:

if indexPath.row == yourArrayOfCells.count - 1{
    loadMoreCells()
}

UPDATE

So I have some how of the same issue, after some digging I found this solution for myself :

//conform to UIScrollViewDelegate

let threshold : CGFloat = 10.0 // threshold from bottom of tableView
var isLoadingMore = false //checks if API session ended

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    let contentOffset = scrollView.contentOffset.y
    let maximumOffset = scrollView.contentSize.height - scrollView.frame.size.height;

    if !isLoadingMore && (maximumOffset - contentOffset) <= threshold {

        self.isLoadingMore = true
        DispatchQueue.main.async {
            loadMoreCells() 
            self.isLoadingMore = false
        }
    }
}

If the API request happening too fast and the load looks funny you can add a delay :

        DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
            loadMoreCells() 
            self.isLoadingMore = false
        }

If it won't work I will assume that the issue is not in the code you provided.

UPDATE-2

Those 2 funcs in setUpCell() aren't neccessery :

tableView.beginUpdates()
tableView.endUpdates()

Hope this helps.

UIView.setAnimationsEnabled(false)
self.tableView.beginUpdates()

self.tableView.insertRows(at: indexPathsToBeInserted, with: UITableViewRowAnimation.none)

self.tableView.endUpdates()
UIView.setAnimationsEnabled(true)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM