iOS - 从ViewController调用AppDelegate方法

252
我想做的是点击一个按钮(通过代码创建)后,它会调用不同的视图控制器,然后在新的视图控制器中运行一个函数。
我知道这在IB(Interface Builder即Xcode中的可视化界面编辑器)中可能很容易实现,但那不是一个选项。
一个例子就是你有两个视图控制器,一个带有一个房屋的启动画面。另一个视图控制器包含了一个房屋的漫游,你可以按照预定顺序进入所有房间。启动画面将为每个房间提供按钮,让你可以跳转到漫游过程的任何点。
13个回答

542

您可以像这样访问委托:

MainClass *appDelegate = (MainClass *)[[UIApplication sharedApplication] delegate];

用你的应用程序类的名称替换MainClass

然后,如果你有另一个视图控制器的属性,你可以调用类似以下代码:

[appDelegate.viewController someMethod];

12
有时需要在使用处导入appDelegate.h文件,或者使用@class appDelegate。 - Zaky German
3
在我看来,appDelegate.h 文件是放在目标的前缀/预编译头文件中的一个很好的选择。 - mharper
48
如果你像@mharper所说,在Prefix.pch中导入你的应用程序代理,你也可以同时添加以下内容:#define AppDelegate ((MyAppDelegateClass *)[UIApplication sharedApplication].delegate),这样就可以像'[AppDelegate.viewController someMethod]'一样访问你的应用程序代理了。这使得它变得更简单一些,但也更容易被滥用。 - Kenny Lövrin
在我的应用程序委托.h文件的@end之后,我添加了#define AppDelegate ((MyAppDelegateClass *)[UIApplication sharedApplication].delegate) 现在无论哪个类导入应用程序委托都可以直接使用[AppDelegate.viewController someMethod] - harveyslash

45

如果有人想知道如何在Swift中实现此操作:

if let myDelegate = UIApplication.sharedApplication().delegate as? AppDelegate {
   myDelegate.someMethod()
}

如果在Swift中使用if let appDelegate = UIApplication.sharedApplication().delegate as? AppDelegate {}是更好的方法。 - cbartel
@petrsyn 你是说委托可以是nil吗?难道每个应用程序不都有一个AppDelegate吗? - mfaani
在最近的 Swift 版本中,sharedApplication() 应该被替换为 shared。即,删除 "Application" 和括号。因此,Swift 5.2 的完整工作代码如下:if let myDelegate = UIApplication.shared.delegate as? AppDelegate { myDelegate.someMethod() } - sfarbota

41

听起来你只需要设置一个UINavigationController

你可以通过下面的方法在程序的任何地方获取AppDelegate

YourAppDelegateName* blah = (YourAppDelegateName*)[[UIApplication sharedApplication]delegate];

在你的应用代理中,你应该设置好你的导航控制器,可以通过IB或者代码方式。如果是代码方式,假设你已经创建了“House overview”视图控制器,那么在你的AppDelegate didFinishLaunchingWithOptions方法中应该像这样实现...

self.m_window = [[[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds] autorelease];
self.m_navigationController = [[[UINavigationController alloc]initWithRootViewController:homeViewController]autorelease];
[m_window addSubview:self.m_navigationController.view];

之后,您只需要为每个“房间”创建一个视图控制器,并在捕获到按钮点击事件时调用以下内容...

YourAppDelegateName* blah = (YourAppDelegateName*)[[UIApplication sharedApplication]delegate];
[blah.m_navigationController pushViewController:newRoomViewController animated:YES];

我没有测试过上面的代码,所以请原谅任何语法错误,但希望伪代码能够有所帮助...


8
你的答案也是正确的,最终我采用了Cristian和你的答案的结合。我希望我能够分配勾选标记。 - Mytheral

19

这是我做事的方式。

[[[UIApplication sharedApplication] delegate] performSelector:@selector(nameofMethod)];

别忘了导入。

#import "AppDelegate.h"

13

只需按照以下步骤进行操作:

1.在想要获取应用程序委托对象的类中导入您的应用程序委托。

#import "YourAppDelegate.h"

2.在你的类内部创建一个应用委托对象的实例(它基本上是一个单例)。

YourAppDelegate *appDelegate=( YourAppDelegate* )[UIApplication sharedApplication].delegate;

3.现在使用选择器调用方法

if([appDelegate respondsToSelector:@selector(yourMethod)]){

        [appDelegate yourMethod];
    }

或者直接通过

[appDelegate yourMethod];

为Swift语言

let appdel : AppDelegate = UIApplication.shared.delegate as! AppDelegate

我会推荐第一个。跑和走。


这并不是委托的新实例,而是检索单例应用程序的单例委托。 - Ammo Goettsch

11
NSObject <UIApplicationDelegate> * universalAppDelegate = 
    ( NSObject <UIApplicationDelegate> * ) [ [ UIApplication sharedApplication ] delegate ];

这可以避免在各处包含您的AppDelegate.h文件。 这是一个简单的转换,可以大大提高效率,使您能够开发独立的控制器并在其他地方重用它们,而不必担心类名等问题...

享受吧


感谢您的分享,它让我开心了几分钟,可能会有用,但如果我想从中使用像"visibleViewController"这样的方法怎么办呢?它会出现如下错误:在类型为“NSObject <UIApplicationDelegate> *”的对象上找不到属性“visibleViewController”。对此有什么解决方案吗? - mgyky

8
很多好的答案已经被添加了。虽然我想补充一些适合我大部分时间的内容。
#define kAppDelegate ((YourAppDelegate *)[[UIApplication sharedApplication] delegate]);

那就这样了。在应用程序中就像一个常量一样使用它。

例如:

[kAppDelegate methodName];

不要忘记在相应的.pch或宏文件中导入你的AppDelegate.h。


7

如果有人需要在Xamarin(Xamarin.ios / Monotouch)中实现相同的功能,这个方法适用于我:

var myDelegate = UIApplication.SharedApplication.Delegate as AppDelegate;

(需要使用UIKit;)


在 Swift 中正确的语句是 let appdel: AppDelegate = UIApplication.shared.delegate as! AppDelegate。 - Phil

6

针对Swift 3.0及以上版本的更新

//
// Step 1:- Create a method in AppDelegate.swift
//
func someMethodInAppDelegate() {

    print("someMethodInAppDelegate called")
}

通过以下方式从您的控制器调用上述方法

//
// Step 2:- Getting a reference to the AppDelegate & calling the require method...
//
if let appDelegate = UIApplication.shared.delegate as? AppDelegate {

    appDelegate.someMethodInAppDelegate()
}

输出:

enter image description here


5

如果您需要从watchOS上的视图控制器访问WatchKit扩展委托:

extDelegate = WKExtension.sharedExtension().delegate as WKExtensionDelegate?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接