简体   繁体   中英

ios8 UITableView scrolling jumps back when scrolling up

I have an odd situation with my UItableView.

I am loading images from the internet and presenting them in a uitableviewcell in an asynchronous manner. When I scroll down (ie row 1 to 6) the scroll scrolls down smoothly just as I expect it to.

However, then I scroll up (ig row 6 to 1) the scroll jumps back. for example if I scroll from row 6 to row 5, it will jump back to row 6. The second time I try to scroll up it lets me go up to row 4, but then it scrolls me back to row 5 or 6 but usually just 5.

What I don't understand is why this is happening in only one direction.

It seems to be effecting ios 8 but not ios 7.

Therefore it is an implementation difference in how ios8 and 7 handle the uitableview.

How can I fix this?


Here is some code to give you some context

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    CVFullImageTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath];
    CVComicRecord *comicRecord = self.comicRecords[indexPath.row];
    [cell.loaderGear stopAnimating];
    [cell.text setText:comicRecord.title];
    NSString *UUID = comicRecord.fullImagePageURL.absoluteString;
    [cell setUUID:UUID];
    //Check if image is in the cache
    UIImage *fullImage = [self.contentViewCache objectForKey:UUID];
    [cell setComicFullImage:fullImage];

    if (fullImage) {
        return cell;
    }

    [cell.loaderGear startAnimating];

    [self requestImageForIndexPath:indexPath];
    return cell;
}

- (void)requestImageForIndexPath:(NSIndexPath *)indexPath {
    CVComicRecord *comicRecord = self.comicRecords[indexPath.row];
    NSString *UUID = comicRecord.fullImagePageURL.absoluteString;

    if ([self.contentViewCache objectForKey:UUID]) {
        //if it is already cached, I do not need to make a request.
        return;
    }

    id fd = CVPendingOperations.sharedInstance.fullDownloadersInProgress[UUID];

    if (fd) {
        //if it is in the queue you do no need to make a request
        return;
    }

    comicRecord.failedFull = NO;
    CVFullImageDownloader *downloader = [[CVFullImageDownloader alloc] initWithComicRecord:comicRecord withUUID:UUID];
    [CVPendingOperations.sharedInstance.fullDownloaderOperationQueue addOperation:downloader];
    //when operation completes it will post a notification that will trigger an observer to call fullImageDidFinishDownloading
}

- (void)fullImageDidFinishDownloading:(NSNotification *)notification {
    CVComicRecord *comicRecord = notification.userInfo[@"comicRecord"];
    NSString *UUID = notification.userInfo[@"UUID"];
    UIImage *fullImage = notification.userInfo[@"fullImage"];

    comicRecord.failedFull = NO;

    [self.contentViewCache setObject:fullImage forKey:UUID];
    dispatch_async(dispatch_get_main_queue(), ^{
        for (NSIndexPath *indexPath in [self.tableView indexPathsForVisibleRows]) {
            CVFullImageTableViewCell *cell = (id)[self.tableView cellForRowAtIndexPath:indexPath];
            if (cell) {
                if ([cell.UUID isEqualToString:UUID]) {
                    [cell.loaderGear stopAnimating];
                    [cell setComicFullImage:fullImage];
                    [cell layoutIfNeeded];
                }
            }
        }
    });
}

#pragma mark - Scroll

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    static int oldOffset = 0;
    int newOffset = scrollView.contentOffset.y;

    int dy = newOffset- oldOffset;
    if (dy > 0) {
        [self hideNavigationbar:YES animationDuration:0.5];
    } else  if (dy < 0) {
        [self hideNavigationbar:NO animationDuration:0.5];
    }

    oldOffset = newOffset;
}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
    if (decelerate == NO) {
        [self prioritizeVisisbleCells];
        //currentPage is a property that stores that last row that the user has seen
        [self setCurrentPage:[self currentlyViewedComicIndexPath].row];
    }
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    [self prioritizeVisisbleCells];
    //currentPage is a property that stores that last row that the user has seen
    [self setCurrentPage:[self currentlyViewedComicIndexPath].row];
}

- (void)prioritizeVisisbleCells {
    NSArray *ips = [self.tableView indexPathsForVisibleRows];
    NSArray *activeIndexPaths = [CVPendingOperations.sharedInstance.fullDownloadersInProgress allKeys];

    //add visible cells to queue first
    NSSet *visible = [NSSet setWithArray:ips];
    NSMutableSet *invisible = [NSMutableSet setWithArray:activeIndexPaths];
    [invisible minusSet:visible];

    for (NSIndexPath *ip in invisible) {
        NSOperation *op = CVPendingOperations.sharedInstance.fullDownloadersInProgress[ip];
        [op setQueuePriority:NSOperationQueuePriorityNormal];
    }

    for (NSIndexPath *ip in visible) {
        NSOperation *op = CVPendingOperations.sharedInstance.fullDownloadersInProgress[ip];
        [op setQueuePriority:NSOperationQueuePriorityHigh];
    }
}

I found the answer in this post very helpful: Table View Cells jump when selected on iOS 8

Try to implement the tableView:estimatedHeightForRowAtIndexPath: in the UITableViewDelegate protocol. It works for me.

Implement the self-sizing and correct view constraints in your storyboard.

in your code put this together

tableView.rowHeight = UITableViewAutomaticDimension; tableView.estimatedRowHeight = CGFloat value (the initial value)

This exact problem was happening to me while I was using the UITableViewAutomaticDimension and the estimatedRowHeight , as @nferocious76 suggested.

The issue was that my estimatedRowHeight was 400.0 while the actual row height was more like 80.0 (I copy/pasted it from another table view in my app with large cells). I never bothered to change it because I had read somewhere that the estimatedRowHeight didn't really matter as long as it was greater than the actual row height, but apparently this is not the case.

您应该自己计算行高,并且应该删除代码中估计行高的所有内容。

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