如果它在 TabBarController 中,如何从 AppDelegate 访问 ViewController 的 属性?

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

我有一个 UITabBarController 作为根视图控制器,我需要访问 ProfileViewController 中的一个 属性。

这是故事板:

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
}

找到所需视图控制器的最简单方法:

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

更干净的方法是:

  • 有某种 OAuthService 负责 OAuth 身份验证、令牌等
  • appDelegate 对 OAuthService 有很强的参考,因为很可能在 applicationDidFinishLaunching(_) 中创建它。
  • OAuthService 提供委托/通知/状态流以通知会话状态更改
  • ProfileViewConctoller 订阅了此更改

我建议不要从应用委托访问视图控制器。它在应用程序委托中加入了太多关于视图控制器需要什么(及其结构)的知识。这是一个脆弱的设计。

更好的方法是定义您自己的 NotificationCenter 通知。 Post 来自具有所需负载的应用程序委托的通知(URL)。

在适当的视图控制器中添加代码以侦听该自定义通知。当在视图控制器中收到通知时,获取 URL 并采取相应行动。

这种方法将谁关心通知以及如何处理通知的知识放到了它所属的位置。它还允许多个视图控制器(或其他 类)对同一通知执行操作,而无需在应用程序委托中添加越来越多的逻辑。

正确的方法应该是有一个 "dataSource" / "DBManager" 您可以调用它会将数据发送到每个请求对象。

(我通常为此单身..即使经常不鼓励单身..:))