diff --git a/Tusker/Screens/Timeline/TimelineTableViewController.swift b/Tusker/Screens/Timeline/TimelineTableViewController.swift index e10f83f8..00606091 100644 --- a/Tusker/Screens/Timeline/TimelineTableViewController.swift +++ b/Tusker/Screens/Timeline/TimelineTableViewController.swift @@ -109,8 +109,9 @@ class TimelineTableViewController: EnhancedTableViewController { // MARK: - Table view delegate override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { + // don't remove rows when jumping to the top, otherwise jumping back down might try to show removed rows // when scrolling upwards, decrement reference counts for old statuses, if necessary - if scrollViewDirection < 0 { + if !isCurrentlyScrollingToTop, scrollViewDirection < 0 { if indexPath.section <= timelineSegments.count - 2 { // decrement ref counts for all sections below the section below the current section // (e.g., there exist sections 0, 1, 2 and we're currently scrolling upwards in section 0, we want to remove section 2) diff --git a/Tusker/Screens/Utilities/EnhancedTableViewController.swift b/Tusker/Screens/Utilities/EnhancedTableViewController.swift index 0c66bd54..e11c34bf 100644 --- a/Tusker/Screens/Utilities/EnhancedTableViewController.swift +++ b/Tusker/Screens/Utilities/EnhancedTableViewController.swift @@ -11,25 +11,26 @@ import SafariServices class EnhancedTableViewController: UITableViewController { - var prevScrollToTopOffset: CGPoint? = nil - - private var topOffset: CGPoint { - // when scrolled to top, the content offset is negative the height of the UI above the scroll view (i.e. the nav and status bars) - let windowScene = view.window!.windowScene! - let barOffset = -1 * (navigationController!.navigationBar.frame.height + windowScene.statusBarManager!.statusBarFrame.height) - // add one so it's not technically all the way at the top, and scrollViewWShouldScrollToTop is still called to trigger undo - return CGPoint(x: 0, y: barOffset + 1) - } + private var prevScrollToTopOffset: CGPoint? = nil + private(set) var isCurrentlyScrollingToTop = false override func scrollViewShouldScrollToTop(_ scrollView: UIScrollView) -> Bool { if let offset = prevScrollToTopOffset { tableView.setContentOffset(offset, animated: true) prevScrollToTopOffset = nil + return false } else { prevScrollToTopOffset = tableView.contentOffset - tableView.setContentOffset(topOffset, animated: true) + isCurrentlyScrollingToTop = true + return true } - return false + } + + override func scrollViewDidScrollToTop(_ scrollView: UIScrollView) { + isCurrentlyScrollingToTop = false + // add one so it's not technically scrolled all the way to the top, + // otherwise there's no way of detecting a status bar press to scroll back down + tableView.contentOffset.y -= 0.5 } override func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {