Load Data Before Adding ViewControllers to UITabBarController

175 Views Asked by At

In my application, once the user logs in from the LoginViewController, he is directed to the ProfileTabBarController.

ProfileTabBarController is a subclass of UITabBarController.It consists of three view controllers all of which need a reference to an instance of Profile.

When the ProfileTabBarController is pushed, it loads the user's profile. Once the profile loads successfully, it sets a reference to profile on each of its view controllers and then adds them as tab items.

The reason I chose this approach is that if the user launches the application and his token hasn't expired, the application should go directly to the ProfileTabController; the user need not login again. Rather than duplicate the code for loading the profile in both AppDelegate and LoginViewController, I felt it was better to encapsulate it in ProfileTabBarController.

The problem with this approach is that during the segue, the UITabBarController appears black as no view controller has been set. I managed to remedy this by creating a LoadingViewController and setting it initially as the only UIViewController of ProfileTabController

My question is whether there is a better approach to solving this problem. I don't really like the idea of having a UIViewController with no other purpose then to display a loading icon.

2

There are 2 best solutions below

0
On BEST ANSWER

I was able to eliminate the Loading ViewController by making use of NSNotificationCenter.

  • ProfileTabBarController adds the three ViewControllers and then begins loading the profile.

override func viewDidLoad() { super.viewDidLoad()

    self.setupUI()
    self.setupViewControllers()
    self.loadProfile()

}

  • Once loading completes, the ProfileTabBarController emits a ProfileDidLoad notification.

let completion = { (profile: Profile?) in

MBProgressHUD.hideHUDForView(self.view, animated: true)

if let profile = profile {

    self.profile = profile
    NSNotificationCenter.defaultCenter().postNotificationName(Notification.ProfileDidLoad, object: self.profile)

} else {

    UIAlertView(
        title: "",
        message: NSLocalizedString("Error loading profile", comment: ""),
        delegate: nil,
        cancelButtonTitle: "OK"
        ).show()

}

}

  • The ViewControllers observe the ProfileDidLoad notification:

    func setupNotificationObserver(){

        NSNotificationCenter.defaultCenter().addObserver(self, selector: "profileDidLoad:", name: Notification.ProfileDidLoad, object: nil)
    
    }
    
    @objc func profileDidLoad(notification: NSNotification){
    
        if let profile = notification.object as? Profile{
            self.profile = profile
        }
    
    }
    

In this way, the view controllers are immediately displayed after login without the need of a loading screen.

0
On

Presenting a tab view controller with no views doesn't make much sense, so I think your solution of giving it a view controller to handle this loading state makes perfect sense. Throw in some cool animation to keep the user entertained.

It's also possible that something could go wrong and the profile may not load properly. This transitional view controller seems like a good place to put the code to deal with possible errors.