Nick89 Nick89 - 2 months ago 7
Swift Question

ViewController appears mulitple times when creating a navigationController programmatically in swift

I have been creating my app completely from scratch programmatically, without using Storyboards.

My app is integrated with Firebase, and uses Facebook login.

My setup is fairly simple:



  1. Launch the app -> takes you to the first VC called
    WelcomeViewController
    .

  2. There is a check that happens in the
    viewDidLoad
    method to see if a user is already signed in and exists. If there is, it sends you straight to the second VC called
    FilmsViewController

  3. The
    FilmsViewController
    is a collectionViewController that displays films. The user can press a film, and it takes them to more information about that film.




(For reference, I am already signed in with Facebook in my app)

I have a current issue, where when step 2 above happens, it transitions to the
FilmsViewController
, but it does it like 2 or 3 times. So you see the new VC appear like 2 or 3 times, then the content loads. If you press the
Back
button in the nav bar, it takes you back through the 2 or 3 viewControllers that it loaded before taking you back to the
WelcomeViewController
.

I have set my views up as follows.

In
AppDelegate.swift
:

var window: UIWindow?
var navController: UINavigationController?

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.

navController = UINavigationController()
let firstViewController: WelcomeViewController = WelcomeViewController()
self.navController!.pushViewController(firstViewController, animated: true)

window = UIWindow(frame: UIScreen.main.bounds)
window?.rootViewController = navController
window?.makeKeyAndVisible()

return true

}


In the
WelcomeViewController
in the
viewDidLoad
:

FIRAuth.auth()?.addStateDidChangeListener { auth, user in

if let user = user {

// User is signed in.
// Direct the user to the home screen

let toFilmListVC = FilmsViewController(collectionViewLayout: UICollectionViewFlowLayout())
self.navigationController?.pushViewController(toFilmListVC, animated: true)

} else { ...
}
}


I have looked loads for a solution - and nothing. I've only found one post on this issue, where someone said the solution was to change the class name of that controller, which I have already done and it didn't change anything.

Can anyone help me resolve this, please? Thank you.

Answer

The addStateDidChangeListener is probably being called multiple times.

You should modify it to check whether a FilmsViewController has already been pushed, to prevent pushing another one:

FIRAuth.auth()?.addStateDidChangeListener { auth, user in

    if let user = user {

        // User is signed in.
        // Direct the user to the home screen

        // Only push one FilmsViewController onto the navigation stack!
        var shouldPush = true
        if let navigationController = self.navigationController {
            for viewController in navigationController.viewControllers {
                if viewController is FilmsViewController {
                    shouldPush = false
                }
            }
        }

        if shouldPush {
            let toFilmListVC = FilmsViewController(collectionViewLayout: UICollectionViewFlowLayout())
            self.navigationController?.pushViewController(toFilmListVC, animated: true)
        }
    } else { ...
    }
}