How to call method in view controller in app delegate?

I need to call a method in my ViewController class in AppDelegate. This is what the method looks like this:

class ViewController: UIViewController {

    func myFunction() {
        ...
    }
}

I've tried using window.rootViewController, but it's telling me the method myFunction does not exist, since rootViewController is of type UIViewController.

I've also tried

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

But this is creating a new instance of the ViewController class, and that's not what I want, either.

Here is the part of the AppDelegate code that I need myFunction to be called from:

class AppDelegate: UIResponder, UIApplicationDelegate {

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

Context: I'm following a geofencing tutorial: https://www.raywenderlich.com/136165/core-location-geofencing-tutorial

Since user location is being monitored even when app is closed, when an event is triggered, AppDelegate should be used to handle the event, since view controller is not yet loaded.

In my AppDelegate that handles event, if the application is active, I would like to pop up an alert to have the user choose to stop monitoring location. The function that stops location monitoring (myFunction) is in view controller.


if its the root its easy:

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

if its on top of a navigationController

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

But in either case its weird and probably not the right thing to do. Use NotificationCenter instead and post a notification name in your AppDelegate and then have the ViewController listen for messages and respond accordingly.


Sending a Notification sounds like a cleaner way. But to do what the OP is trying although not clean I used to do it on the early Xcode days and I had no issues when done.

Let's say you want to call myMethod in myViewCtlr from AppDelegate.m

in App Delegate do this

//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];
...    

Then you just set the pointer to the current controller as this, for simplicity I put on the ViewDidLoad you may have to do it in the ViewWillAppear if you are flipping thru diff screens, but the idea is the same

// 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; 
...

You shouldn't call view controllers methods from the appdelegate. Is a bad practice and generally is not required. If you want to react to methods such as: willResignActive willTerminate

you should listen to notifications for those events using the NotificationCenter.

链接地址: http://www.djcxy.com/p/68296.html

上一篇: 动态递归lambda表达式

下一篇: 如何在应用程序委托中调用视图控制器中的方法?