【问题标题】:How to call method in view controller in app delegate?如何在应用程序委托中调用视图控制器中的方法?
【发布时间】:2017-04-22 23:54:26
【问题描述】:

我需要在 AppDelegate 的 ViewController 类中调用一个方法。该方法如下所示:

class ViewController: UIViewController {

    func myFunction() {
        ...
    }
}

我尝试过使用 window.rootViewController,但它告诉我方法 myFunction 不存在,因为 rootViewController 的类型是 UIViewController。

我也试过

var vc = ViewController()
self.vc.myFunction()

但这正在创建 ViewController 类的新实例,这也不是我想要的。

这是我需要调用 myFunction 的 AppDelegate 代码部分:

class AppDelegate: UIResponder, UIApplicationDelegate {

    func handleEvent() {
        if UIApplication.shared.applicationState == .active {
            // call myFunction()
        }
        else {
            ...
        }
    }
}

上下文: 我正在关注地理围栏教程:https://www.raywenderlich.com/136165/core-location-geofencing-tutorial

由于即使关闭应用程序也会监视用户位置,因此当触发事件时,应使用 AppDelegate 处理事件,因为尚未加载视图控制器。

在我处理事件的 AppDelegate 中,如果应用程序处于活动状态,我想弹出一个警报让用户选择停止监视位置。停止位置监控的函数(myFunction)在视图控制器中。

【问题讨论】:

  • 尝试从应用程序委托调用视图控制器中的任何内容是一个糟糕的设计。你想达到什么目的?并显示相关的应用委托代码。
  • 正如 rmaddy 指出的那样,您不应该在尚未完全组装好的视图控制器上调用方法(它尚未显示)。但是,您可以设置属性。所以告诉我们为什么需要在视图控制器中调用一个甚至还不存在的函数。
  • 编辑了我的帖子。

标签: ios swift


【解决方案1】:

如果它的根很容易:

(window.rootViewController as? ViewController)?.myFunction()

如果它在一个navigationController之上

((window.rootViewController as? UINavigationController)?.topViewController as? ViewController)?.myFunction()

但无论哪种情况,这都很奇怪,而且可能不是正确的做法。改用 NotificationCenter 并在 AppDelegate 中发布通知名称,然后让 ViewController 侦听消息并做出相应响应。

【讨论】:

【解决方案2】:

您不应该从 appdelegate 调用视图控制器方法。是一种不好的做法,通常不需要。 如果您想对以下方法做出反应: willResignActive willTerminate

您应该使用 NotificationCenter 收听这些事件的通知。

【讨论】:

    【解决方案3】:

    发送通知听起来是一种更简洁的方式。但是为了做 OP 正在尝试的事情,虽然不干净,我曾经在早期的 Xcode 日子里做过,做完后我没有任何问题。

    假设你想从 AppDelegate.m 调用 myViewCtlr 中的 myMethod

    在 App Delegate 中执行此操作

    //In AppDelegate.h define
    ...
    UIViewController *cur_ViewCtrl
    ... 
    @property (nonatomic, retain) UIViewController *cur_ViewCtrlr;
    
    
    // in the AppDelegate.m you can call the method like this:
    
    @synthetize cur_ViewCtrlr;
    ... 
    if([cur_ViewCtrlr isKindOfClass:[myViewCtlr class]])
           [(myViewCtlr*) cur_ViewCtrlr myMethod:arg];
    ...    
    

    然后您只需将指针设置为当前控制器,为简单起见,如果您要通过差异屏幕翻转,您可能必须在 ViewWillAppear 中执行此操作,但想法是相同的

    // In myViewController
    ...
    - (void)viewDidLoad
    {
      ...
      AppDelegate *My_delegate = (AppDelegate *)[[UIApplication sharedApplication]delegate];
      //and set the reference to this conrtoller in the appDelegate
      My_delegate.cur_ViewCtrlr = self; 
    ...
    

    【讨论】:

      猜你喜欢
      • 2015-08-22
      • 2011-12-29
      • 2012-01-11
      • 1970-01-01
      • 1970-01-01
      • 2011-06-26
      • 1970-01-01
      • 2020-09-20
      • 1970-01-01
      相关资源
      最近更新 更多