Search code examples
iosswiftuitabbarcontrollerxcode10

How can I bring a collectionView back to the top when the tabBar icon for that respective view controller is pressed?


I am trying to build a social media app in swift that has a tab bar with 4 icons each connected to a view controller. I want to have the four collection views (that are each associated with a view controller) scroll back to the top when the respective tab bar icon is pressed (Exactly like twitter).

I have the logic for how I want the collection view to come back to the top only if the past tab bar icon was for that respective collection view (this is so that it doesn't just automatically scroll to the top when clicking on the respective tab but needs to be pressed again) I tried to debug my first switch case but have had no luck so I do not have the full code for the other cases yet. What I try to do is reference the correct storyboard, then the correct view controller (in this case homeViewController), and finally call that respective collection view and use setContentOffset to bring it to the top.

Below I provide my whole tabBarController class.

import Foundation
import UIKit

class MainTabController: UITabBarController, UITabBarControllerDelegate {

    var pastTabBar: Int = 0

    override func viewDidLoad() {
        super.viewDidLoad()

        self.delegate = self


    }


    override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {

            let tabBarIndex = tabBar.items?.index(of: item)

            if tabBarIndex == pastTabBar {

                switch tabBarIndex {

                case 0:
                    print ("go to top of home")
                    //updateHomeCollection = 1
                    let HomeSB : UIStoryboard = UIStoryboard(name: "Home", bundle: nil)
                    let HomeVC = HomeSB.instantiateViewController(withIdentifier: "Home") as? HomeViewController
                    HomeVC?.collectionView.setContentOffset(CGPoint(x: 0, y: 0), animated: true)
                case 1:
                    print ("go to top of search")
                case 2:
                    print ("go to top of notifications")

                case 3:
                    print ("go to top of profile")

                default:
                    print ("not working")
                }
            }

        if let tabBarIndex = tabBarIndex {
            pastTabBar = tabBarIndex
        }

        }

}

It keeps signal aborting when I click the home tab! It is printing this exact statement:

Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value

on this line of code:

HomeVC?.collectionView.setContentOffset(CGPoint(x: 0, y: 0), animated: true)

Solution

  • Loading ViewController is not best way. You have to fetch your desired ViewController from Navigation like below

    extension HomeTabVC: UITabBarControllerDelegate {
    
        func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
            if previousController == viewController {
                if let nav = viewController as? UINavigationController, let vc = nav.viewControllers[0] as? FeaturedVC {
                    if vc.isViewLoaded && (vc.view.window != nil) {
                        let visibleIndex = vc.collectionFeatured.indexPathsForVisibleItems
                        if visibleIndex.count != 0 {
                            vc.collectionFeatured.scrollToItem(at: IndexPath (item: 0, section: 0), at: .bottom, animated: true)
                        }
                    }
                }else if let nav = viewController as? UINavigationController, let vc = nav.viewControllers[0] as? CategoryVC {
                    if vc.isViewLoaded && (vc.view.window != nil) {
                        let visibleIndex = vc.collectionViewCategory.indexPathsForVisibleItems
                        if visibleIndex.count != 0 {
                            vc.collectionViewCategory.scrollToItem(at: IndexPath (item: 0, section: 0), at: .bottom, animated: true)
                        }
                    }
                }else{
    
                }
            }
    
            previousController = viewController
    
        }
    }
    

    You have to store Selected ViewController in variable so when you change ViewController from one tab to another it will just change ViewController and when you tap same tab again it will scroll you back to top. This is how iOS is doing it self in all there application