swiftgoogle-cloud-firestorememory-leaksuiscenedelegateguard-statement

is this firestore closure causing a memory leak?


So my goal is to fix this condition issue when it comes to instantiating the right viewController. I have a function that I basically use to navigate a user to the right viewController depending on the type of user and if they're logged in or not.

Here is this function :

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    guard let windowScene = (scene as? UIWindowScene) else { return }

    let window = UIWindow(windowScene: windowScene)
    self.window = window

    let auth = Auth.auth()
    let actualuser = Auth.auth().currentUser


    auth.addStateDidChangeListener { (_, user) in
        if user != nil {

            db.document("student_users/\(actualuser?.uid)").getDocument { (docSnapshot, error) in
                if error != nil {
                    print("\(error)")
                } else {
                    let docSnap = docSnapshot?.exists
                    guard docSnap! else {
                        let alreadyLoggedInAsASchoolViewController = self.storyboard.instantiateViewController(withIdentifier: Constants.StoryboardIDs.SchoolEventDashboardStoryboardID) as! SchoolTableViewController
                        let navigationizedSchoolVC = UINavigationController(rootViewController: alreadyLoggedInAsASchoolViewController)
                        self.window!.rootViewController = navigationizedSchoolVC
                        self.window!.makeKeyAndVisible()
                        return
                    }
                        let alreadyLoggedInAsAStudentViewController = self.storyboard.instantiateViewController(withIdentifier: Constants.StoryboardIDs.StudentEventDashboardStoryboardID) as! StudentSegmentedTableViewController
                        let navigationizedVC = UINavigationController(rootViewController: alreadyLoggedInAsAStudentViewController)
                        self.window!.rootViewController = navigationizedVC
                        self.window!.makeKeyAndVisible()
                 
                }
            }
        } else {
            let notLoggedInAtAll = self.storyboard.instantiateViewController(withIdentifier: Constants.StoryboardIDs.GothereMainMenuStoryboardID) as! GothereMainMenuViewController
            let navMainMenu = UINavigationController(rootViewController: notLoggedInAtAll)
            self.window!.rootViewController = navMainMenu
            self.window!.makeKeyAndVisible()
        }
    }
}

I also have the exact block of code like this for the sceneDidEnterForeground for push notification purposes. Now the issue is when I run the simulator and launch the app for the first time, the correct viewController will show up, but when I logout as a school user and login as a school user in that same simulator session, the wrong viewController (aka the viewController of the other type of user) shows up.

Not that it would be a real situation in production where a student user would just have access to a school user's account and log in like that in the same scene session, but still, better to be safe than sorry. So this leads to me ask, is this a memory leak or a completely different issue?

I also get this error :

unbalanced error


Solution

  • Your query is based on the variable actualuser, which looks like it is only set once, when the scene is first set up. Inside the state change callback, it's never updated.

    So, when you log out, then log back in as a different user, that initial value of actualuser will be used, explaining why you see the wrong view controller. Then, when you run the app again and the scene is set up, actualuser gets set to the auth().currentUser again, showing you the correct view controller.

    The solution here is to base your query on the current (and current) user.

    Something like:

     db.document("student_users/\(user.uid)")
    

    (Instead of checking user != nil, do an optional binding with let user = user and then you can avoid the ? unwrapping)

    This is not, by the way, a memory leak, which is a different type of issue: https://en.wikipedia.org/wiki/Memory_leak