如何在应用程序委托中调用视图控制器中的方法?
如何在应用程序委托中调用视图控制器中的方法?
我需要在AppDelegate中调用ViewController类中的一个方法。这个方法看起来是这样的:
class ViewController:UIViewController {
func myFunction(){
...
}
}
我尝试使用window.rootViewController,但它告诉我myFunction方法不存在,因为rootViewController是UIViewController类型。
我还尝试了以下方法:
var vc = ViewController()
self.vc.myFunction()
但是这将创建ViewController类的一个新实例,这也不是我想要的。
这是我需要从AppDelegate代码中调用myFunction的部分:
class AppDelegate:UIResponder,UIApplicationDelegate {
func handleEvent(){
if UIApplication.shared.applicationState == .active {
// 调用myFunction()
}
else {
...
}
}
}
背景信息:
我正在按照一个地理围栏的教程进行操作:https://www.raywenderlich.com/136165/core-location-geofencing-tutorial
由于即使在应用程序关闭时也会监视用户位置,当事件触发时,应该使用AppDelegate来处理事件,因为视图控制器尚未加载。
在处理事件的AppDelegate中,如果应用程序处于活动状态,我希望弹出一个提示框,让用户选择停止监视位置。停止位置监视的函数(myFunction)在视图控制器中。
在AppDelegate.m文件中,我们可以通过以下方式调用myViewCtlr中的myMethod方法:
1. 在AppDelegate.h文件中定义一个UIViewController类型的属性cur_ViewCtrlr,并声明为nonatomic和retain。代码如下:
... UIViewController *cur_ViewCtrlr; ... @property (nonatomic, retain) UIViewController *cur_ViewCtrlr; ...
2. 在AppDelegate.m文件中,我们可以使用以下代码来调用方法:
cur_ViewCtrlr; ... if([cur_ViewCtrlr isKindOfClass:[myViewCtlr class]]) [(myViewCtlr*) cur_ViewCtrlr myMethod:arg]; ...
3. 在myViewController中的ViewDidLoad方法中,我们可以使用以下代码将当前控制器的引用设置到AppDelegate中:
... - (void)viewDidLoad { ... AppDelegate *My_delegate = (AppDelegate *)[[UIApplication sharedApplication]delegate]; //and set the reference to this conrtoller in the appDelegate My_delegate.cur_ViewCtrlr = self; ...
以上就是在AppDelegate中调用myViewCtlr中方法的解决方法。虽然这种方式并不是最优雅的方式,但在早期的Xcode版本中使用是可行的。
在AppDelegate中调用视图控制器的方法可能是一种不常见且不正确的做法。可以使用NotificationCenter来解决这个问题。在AppDelegate中发送一个通知,在视图控制器中监听并响应该通知。
如果根视图控制器是ViewController:
(window.rootViewController as? ViewController)?.myFunction()
如果根视图控制器是一个导航控制器的顶层视图控制器:
((window.rootViewController as? UINavigationController)?.topViewController as? ViewController)?.myFunction()
但无论哪种情况都不建议这样做。
可以使用NotificationCenter来代替,在AppDelegate中发送通知,在视图控制器中监听并响应通知。以下是在Swift中实现的一行代码的NotificationCenter实现方法,Objective-C代码可以在该页面的另一个答案中找到:NotificationCenter implementation here
在AppDelegate中调用视图控制器的方法是不推荐的做法,通常也是不必要的。如果您想要对以下方法做出响应:
willResignActive willTerminate
您应该使用NotificationCenter来监听这些事件的通知。
为什么不能在AppDelegate中调用视图控制器的方法呢?这是因为在应用程序的生命周期中,AppDelegate负责管理应用程序的整体行为,包括应用程序的启动、终止和状态变化等。而视图控制器是负责管理应用程序中具体界面的逻辑和交互的组件。将视图控制器的方法直接调用放在AppDelegate中,会导致代码的耦合度增加,不利于代码的维护和扩展。
解决这个问题的方法是使用NotificationCenter来监听特定事件的通知。NotificationCenter是iOS中的一个消息通知机制,它允许对象在特定事件发生时发送和接收通知。通过使用NotificationCenter,我们可以在需要的地方监听特定事件的通知,从而做出相应的处理。
例如,如果您想要在应用程序将要进入非活动状态时调用视图控制器的方法,您可以在视图控制器的初始化方法中添加如下代码:
NotificationCenter.default.addObserver(self, selector: #selector(willResignActive), name: UIApplication.willResignActiveNotification, object: nil)
然后,在视图控制器中实现相应的方法:
@objc func willResignActive() {
// 在应用程序将要进入非活动状态时调用的方法
}
通过这种方式,当应用程序将要进入非活动状态时,NotificationCenter会发送一个名为`UIApplication.willResignActiveNotification`的通知,视图控制器就可以接收到这个通知并调用相应的方法。
同样地,您也可以使用NotificationCenter来监听其他事件的通知,比如应用程序将要终止时的通知`UIApplication.willTerminateNotification`。这样,您就可以避免在AppDelegate中直接调用视图控制器的方法,提高代码的可维护性和扩展性。