简体   繁体   中英

How to get access to ViewController's property from AppDelegate if it is in TabBarController?

I have a UITabBarController as the root view controller and I need to get access to one property in ProfileViewController.

Here is the storyboard:

在此处输入图片说明

func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
    let rootVC = self.window?.rootViewController

    if "com.spbpu.csse" == url.scheme {
        //I need here to get VC property and do something like vc.oauth2.handleRedirectURL(url)

        return true
    }
    return false
}

I'd recommend against accessing the view controller from the app delegate. It puts too much knowledge of what the view controller needs (and its structure) in the app delegate. It's a fragile design.

A better approach would be to define your own NotificationCenter notification. Post that notification from the app delegate with the needed payload (the URL).

Add code in the appropriate view controller to listen for that custom notification. When the notification is received in the view controller, get the URL and act accordingly.

This approach puts the knowledge of who cares about the notification and how to handle the notification where it belongs. It also allows more than one view controller (or other classes) to act on the same notification without adding more and more logic in the app delegate.

Easiest dirty way to just find desire view controller:

let profile = (rootVC as? UITabBarController)?.viewControllers?
    .first { $0 is ProfileViewController }
    .map { $0 as! ProfileViewController } // this unwrap is safe since we filtered by first
profile?.doSomething()

More clean way will be:

  • have some kind of OAuthService that responsible for OAuth authentication, tokens and etc
  • appDelegate have strong reference on OAuthService , since most likely creates it in applicationDidFinishLaunching(_) .
  • OAuthService provide delegate / notification / state streams to inform about session state changes
  • ProfileViewConctoller subscribed to this changes

The right approach should be to have a "dataSource" / "DBManager" You can invoke and it will send data to every requesting object.

(I usually a singleton for it.. even if singletons are often discouraged.. :) )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM