Search code examples
iosseguepreloadinguitabcontroller

Load Data Before Adding ViewControllers to UITabBarController


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.


Solution

  • 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.