【问题标题】:How do I access my viewController from my appDelegate? iOS如何从我的 appDelegate 访问我的 viewController? iOS
【发布时间】:2012-04-18 10:10:00
【问题描述】:

我有一个 iOS 应用程序,我在 xCode 中创建为“基于视图的应用程序”。我只有一个 viewController,但它会自动显示,而且我看不到将它与我的 appDelegate 关联的代码。我需要将数据从我的 appDelegate 传递到我的 viewController,但不知道如何实现。

我的应用委托.h:

#import <UIKit/UIKit.h>


@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) NSDictionary *queryStrings;

@end

另外,appDidFinishLoadingWithOptions:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // Override point for customization after application launch.
    [[JMC sharedInstance] configureJiraConnect:@"https://cmsmech.atlassian.net/"           projectKey:@"WTUPLOAD" apiKey:@"7fc060e1-a795-4135-89c6-a7e8e64c4b13"];

    if ([launchOptions objectForKey:UIApplicationLaunchOptionsURLKey] != nil) {
        NSURL *url = [launchOptions objectForKey: UIApplicationLaunchOptionsURLKey];
        NSLog(@"url received: %@", url);
        NSLog(@"query string: %@", [url query]);
        NSLog(@"host: %@", [url host]);
        NSLog(@"url path: %@", [url path]);
        queryStrings = [self parseQueryString:[url query]];
        NSLog(@"query dictionary: %@", queryStrings);
    }
    else {
        queryStrings = [self parseQueryString:@"wtID=nil"];
    }

    return YES;
}

【问题讨论】:

    标签: ios uiviewcontroller uikit storyboard


    【解决方案1】:

    您可以通过以下方式访问它:

    MyViewController* mainController = (MyViewController*)  self.window.rootViewController;
    

    如果您将视图嵌套在 tabviewcontroller 或导航控制器后面,它将返回给您,您需要访问其中的视图控制器

    【讨论】:

    • 抱歉,self 在这种情况下是什么?您指的是 UIApplicationDelegate 中的-window 属性吗?如果是这样,那只有 iOS 5+ - 只是提醒一下。
    • @ConradShultz 是的,它是 UIApplicationDelegate。知道这一点很重要,谢谢!
    • 我不确定这是最好的还是唯一的方法,但这就是我选择这样做的方式,而且效果很好。谢谢。
    • 如果我要访问的视图控制器是我从 rootviewcontroller 呈现的视图控制器怎么办?我通过故事板中的标识符呈现它。如何访问它?
    • 我如何声明在带有目标 c 的 ios 11 中它给了我错误
    【解决方案2】:

    如何使用老式的NSNotifications 将您的应用程序代理的消息发送给任何需要更新的内容(例如您的视图控制器)?或者您可以使用Key Value Observing,这样您的视图控制器就可以在您的应用委托中查看某些属性。

    【讨论】:

    • NSNotificationCenter 适用于松散耦合的关系。如果这个项目只有一个视图,由于关系更紧密,委托可能是更好的方法。
    • @jmstone - 让根视图控制器成为应用程序委托的 delegate?从概念上讲,这似乎是可行的,但它确实看起来可能令人困惑,尤其是对于新手 Objective C 的人。
    • 当然。我仍然相信他拥有视图控制器作为属性。即使在 IB 中自动设置,他也可以设置一个 IBOutlet 并将其连接起来。
    • 问题是 ViewController.h 和 ViewController.m 是由 xCode 以及我的 AppDelegate.m 和 .h 创建的。在我的 appDelegate 中没有任何地方创建了我的 ViewController 实例,设置为 rootViewController 或其他任何东西......这是我的 AppDelegate.h 它只有窗口:
    • 请编辑您的问题并从您的 applicationDidFinishLaunchingWithOptions 方法中发布代码。
    【解决方案3】:

    由于您只有一个视图控制器,因此通用方式(与您的应用程序的设置方式无关):

    UIViewController *vc = [[[UIApplication sharedApplication] keyWindow] rootViewController];
    

    【讨论】:

      【解决方案4】:

      如果您想获得任何其他UIViewController,而不仅仅是rootViewController

      UIWindow *window=[UIApplication sharedApplication].keyWindow;
      UIViewController *root = [window rootViewController];
      
      UIStoryboard *storyboard = root.storyboard;
      CustomViewController *vcc =(CustomViewController *) [storyboard instantiateViewControllerWithIdentifier:@"storyBoardID"];
      

      【讨论】:

      • 很高兴看到我的回答对您有帮助 @JenyaKyrmyza :)
      【解决方案5】:

      Swift 的方式,你可以从任何地方调用它,而不仅仅是 appdelegate:

      /// EZSwiftExtensions - Gives you the VC on top so you can easily push your popups
      public var topMostVC: UIViewController? {
          var presentedVC = UIApplication.sharedApplication().keyWindow?.rootViewController
          while let pVC = presentedVC?.presentedViewController {
              presentedVC = pVC
          }
      
          if presentedVC == nil {
              print("EZSwiftExtensions Error: You don't have any views set. You may be calling them in viewDidLoad. Try viewDidAppear instead.")
          }
          return presentedVC
      }
      

      它作为标准功能包含在:

      https://github.com/goktugyil/EZSwiftExtensions

      【讨论】:

      • 到目前为止,这似乎是最好的答案。
      【解决方案6】:

      如果您使用基于视图的应用程序模板,则应该可以通过应用程序委托中的属性访问单个视图控制器。它与设置为导航控制器的根视图控制器的视图控制器相同。

      如果由于某种原因您的项目设置不同,您可以获取窗口的根视图控制器,它应该是导航控制器,然后获取其顶部视图控制器。

      编辑: 所以问题是这样的:在 iOS5 和 Storyboard 中,Apple 已经抽象了很多你曾经可以访问的初始设置(如果你选择不使用 storyboard,仍然可以访问)。他们更改了传递给 main() 的参数,并在情节提要中进行了更多设置(实际上只是一个 nib)。恕我直言,这部分是为了防止人们使用繁重的操作使 AppDelegate 超载,就像您正在做的那样。 AppDelegate 本质上是为了管理应用程序生命周期而存在的。它并不是真的要执行将信息传递给视图控制器的方法。实际上,为自己提供数据是您的视图控制器的工作。我建议将代码移动到您的视图控制器中,也许在 viewDidLoad 中。如果您需要知道您正在执行的launchOptions objectForKey 测试的结果,您可以非常简单地在您的AppDelegate 上创建一个属性,例如BOOL launchOptionsURLKeyExists,并进行适当的设置。然后,您只需在视图控制器中获取此属性的值。你的 AppDelegate 已经是一个单例了,所以你可以通过 [UIApplication sharedApplication].delegate 来访问它

      编辑 2: viewWillAppear/viewDidAppear 在视图添加到视图控制器中的 UIApplicationDidEnterForegroundNotification 通知时被调用,并在该消息发布时做出适当响应。

      【讨论】:

      • 没有属性也不知道在哪里设置,就是我这里说的……在哪里设置???这是我的 appDelegate.h:#import
      • 我已经编辑了我的回复。我从不使用故事板,所以我忘记了他们现在抽象了很多这些东西。
      • 问题是当应用程序变为活动状态时,我需要提取新的查询字符串并将其发送到我的视图控制器,但我知道在应用程序变为活动状态时调用的唯一方法是在应用程序中委托(willBecomeActive 或其他)。我需要视图控制器意识到它可能已经通过不同的查询字符串变得活跃......
      • 不是真的。那就是问题所在! ViewWillAppear 是我在控制器中的代码获取查询字符串的地方,但是当应用程序变为活动状态(在后台之后)时它不会被调用,它只会在初始启动时被调用。请立即使用此线程:stackoverflow.com/questions/10017305/…
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-13
      • 1970-01-01
      • 2018-06-26
      相关资源
      最近更新 更多