6

I want to simulate the behaviour of twitter or instagram in their list:

When double tap in UITabBarItem, the list is scrolling to top. Somebody knows how can I do this? I have 4 items in my UITabBarController, all of them are list, so I want to do this thing for all.

The problem is when I tap bar item in a push view of mi list, this function calls and detect double tap before get the root view controller of the navigation.

I hope can be clear with my problem.

var previousController: UIViewController?

func tabBarController(tabBarController: UITabBarController, didSelectViewController viewController: UIViewController) {
    if previousController == viewController{
        if let navVC = viewController as? UINavigationController, vc = navVC.viewControllers.first as? HomeViewController {
            vc.tableBusinessList.setContentOffset(CGPointZero, animated: true)
            print("same")
        }
    }else{
        print("No same")
    }
    previousController = viewController
}

The behaviour is no correct. When I pop the view with the tab bar item, the root view is on cell 0

enter image description here

Dasoga
  • 5,489
  • 4
  • 33
  • 40

3 Answers3

14

Ok so I think the best way to proceed is to check if the viewController with your tableView is visible, if it isn't, then don't call set content offset.

So:

var previousController: UIViewController?

func tabBarController(tabBarController: UITabBarController, didSelectViewController viewController: UIViewController) {
    if previousController == viewController {
        if let navVC = viewController as? UINavigationController, vc = navVC.viewControllers.first as? HomeViewController {

            if vc.isViewLoaded() && (vc.view.window != nil) {
                // viewController is visible
                vc.tableBusinessList.setContentOffset(CGPointZero, animated: true)
            }

            print("same")
        }
    }else{
        print("No same")
    }

    previousController = viewController

}
Olivier Wilkinson
  • 2,836
  • 15
  • 17
2

Swift 3

extension UIViewController {
    func scrollToTop() {
        func scrollToTop(view: UIView?) {
            guard let view = view else { return }

            switch view {
            case let scrollView as UIScrollView:
                if scrollView.scrollsToTop == true {
                    scrollView.setContentOffset(CGPoint(x: 0.0, y: -scrollView.contentInset.top), animated: true)
                    return
                }
            default:
                break
            }

            for subView in view.subviews {
                scrollToTop(view: subView)
            }
        }

        scrollToTop(view: self.view)
    }
}

How to use

var previousController: UIViewController?

func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {

        //when user is in FeedViewController and scroll at last record and want to
        if previousController == viewController {
            if let navVC = viewController as? UINavigationController, let vc = navVC.viewControllers.first as? HomeViewController {

                if vc.isViewLoaded && (vc.view.window != nil) {
                    vc.scrollToTop()
                }
                print("same")
            }
        }
        else{
            print("No same")
        }

        previousController = viewController
        return true;
    }

Note: I use @Olivier Wilkinson and show how to use at a required place using an extension for a scroll to the top. (Tested for collection view)

Hardik Thakkar
  • 15,269
  • 2
  • 94
  • 81
  • works like a charm. But I have a bug on my side. I'm having 3 bar items and whenever I'm clicking on the last one it somehow messes my "UITabBarControllerDelegate" cause when I go back to the first bar item "func tabBarController" doesn't trigger anymore..any ideea? appreciate whatsoever – Mohamed Lee May 09 '18 at 12:54
  • This method call when you tap on tab bar 2 times, when you change tab from 3rd to 1st to need to tap 2 times, try like this. – Hardik Thakkar May 09 '18 at 12:59
  • I know. It works perfectly with 1st and 2nd tab items . Btw this is implemented in 1st tabbar. But if i navigate to 3rd it s messing somehow my delegate i dont know cause it wont work anymore – Mohamed Lee May 09 '18 at 13:26
  • You need to write this method in you main UITabBarController and above method is its delegate method so when user change tabbar it calls automatically. – Hardik Thakkar May 10 '18 at 04:03
  • Doesnt work on my side. swift 4. I implemented it in Tabbarcontroller class. nothing happens when I tapped the bar item – Utku Dalmaz Aug 06 '18 at 17:18
  • you need to tap 2 times it it tap on same tabbar secondtime it will work, put break points and check in which state it go. – Hardik Thakkar Aug 07 '18 at 03:58
1

Olivier Wilkinsons answer is great, but the scrolling up part doesn't work anymore in Swift 4, so replace

vc.tableBusinessList.setContentOffset(CGPointZero, animated: true)

with

vc.tableBusinessList.scrollRectToVisible(CGRect(x: 0, y: 0, width: 1, height: 1), animated: true)

an you're all set