从 AppDelegate 呈现特定的视图控制器

Posted

技术标签:

【中文标题】从 AppDelegate 呈现特定的视图控制器【英文标题】:Presenting a specific view controller from AppDelegate 【发布时间】:2012-03-03 18:55:00 【问题描述】:

每次我的应用程序处于活动状态时,我都会尝试呈现一个视图控制器(密码请求类型视图)。输入正确的密码后,它应该会从堆栈中弹出。我尝试推送的密码视图不是初始视图控制器,因此我无法从 AppDelegate 的 applicationDidBecomeActive 访问它。

我还尝试从 MainViewController 的 ViewWillAppear 推送密码视图,但是当应用程序激活时它不会被调用;仅在屏幕刷新时。

过去几天我一直在研究类似的问题,但我仍然不了解正确的方法。我听说我可能无法以这种方式推送视图,因为可能会在 Storyboard 或 NavigationController 连接/初始化/等之前调用 applicationDidBecomeActive。

如果有人可以为我提供推送/呈现视图的正确方法,或者如果有其他地方可以更好地执行此类操作,我将不胜感激。

已解决:我刚刚从情节提要中删除了视图并改用了笔尖。我用过:

PasscodeUnlockVC *passcodeUnlock = [[PasscodeUnlockVC alloc] initWithNibName:@"PasscodeUnlockVC" bundle:[NSBundle mainBundle]];
[(UINavigationController *)self.window.rootViewController pushViewController:passcodeUnlock animated:NO];

查看层次结构数据:

(gdb) po [[(id)UIApp keyWindow] recursiveDescription]
<UIWindow: 0x736a4b0; frame = (0 0; 320 480); layer = <UIWindowLayer: 0x7367b40>>
   | <UILayoutContainerView: 0x76977a0; frame = (0 0; 320 480); autoresize = W+H; layer =     <CALayer: 0x769de60>>
   |    | <UINavigationTransitionView: 0x7692110; frame = (0 0; 320 480); clipsToBounds = YES;      autoresize = W+H; layer = <CALayer: 0x769a8c0>>
   |    |    | <UIViewControllerWrapperView: 0x73868d0; frame = (0 64; 320 416); autoresize =  W+H; layer = <CALayer: 0x75510e0>>
   |    |    |    | <UIView: 0x76b93e0; frame = (0 0; 320 416); autoresize = W+H; layer = <CALayer: 0x7386850>>
   |    | <UINavigationBar: 0x73664b0; frame = (0 20; 320 44); clipsToBounds = YES; opaque =  NO; autoresize = W; layer = <CALayer: 0x7366550>>
   |    |    | <UINavigationBarBackground: 0x7360ea0; frame = (0 0; 320 44); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x7366520>> - (null)
   |    |    | <UINavigationItemView: 0x76b95e0; frame = (160 21; 0 0); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x76aa8e0>>
   |    |    | <UINavigationItemButtonView: 0x7550650; frame = (5 7; 73 30); opaque = NO;   userInteractionEnabled = NO; layer = <CALayer: 0x7368b40>>
Current language:  auto; currently objective-c
(gdb) 

【问题讨论】:

我不熟悉viewDidBecomeActive 消息,当我搜索developer.apple.com 时,我没有得到任何结果。也许你应该告诉我们更多关于这个方法的信息,或者甚至向我们展示你的代码。 对不起,我的意思是 applicationDidBecomeActive。我会编辑帖子。 我正在尝试复制您显示的模态视图,但它告诉我 pushViewController:animated 无法识别,您能否告诉我您是否在 ios 6 上尝试过? 【参考方案1】:

我建议你使用applicationWillEnterForeground:,而不是applicationDidBecomeActive:,因为它更适合多任务手势。例如,如果用户双击主页按钮显示任务栏,然后在不更改应用程序的情况下关闭任务栏,您不希望设置锁定屏幕。

大概你的AppDelegate 有一个window 属性,并且你知道你的窗口的根视图控制器是一个UINavigationController

- (void)applicationWillEnterForeground:(UIApplication *)application 
    PasscodeViewController *pvc = [[PasscodeViewController alloc] init];
    [(UINavigationController *)self.window.rootViewController pushViewController:pvc animated:NO];
    // [pvc release]; if not using ARC

【讨论】:

我在没有任何警告或错误的情况下实现了该代码,但它没有显示整个视图,它只是显示导航栏,其下方有一个黑屏。有任何想法吗?我不必在标题中声明视图或做任何事情吗?再次感谢。 在调试器中暂停并执行po [[(id)UIApp keyWindow] recursiveDescription] 好的,我得到了关于视图层次结构的信息,但我不确定如何解析/使用它。 SO上的其他人也遇到了同样的黑屏问题,解决方法是删除loadView实现,反正我也没有。 将视图层次结构转储放在您的问题中,以便我看到它。 好吧,我在转储 (0x76b93e0) 中看到了一个可能属于您的 PasscodeViewController 的视图。您需要弄清楚为什么它没有正确设置。视图控制器有笔尖吗?是否命名为PasscodeViewController.xib【参考方案2】:

已解决

PasscodeViewController *vc = [[UIStoryboard storyboardWithName:@"Main" bundle:nil] instantiateViewControllerWithIdentifier:@"passcodeVCID"]; 
UINavigationController *navController = [[UINavigationController alloc]initWithRootViewController:vc];
navController.navigationBar.hidden = YES;
vc.mode = @"enable";
self.window.rootViewController = navController;  

applicationWillEnterForeground 方法中使用。

【讨论】:

【参考方案3】:

Swift 版本的快速通用方式:

getRootViewController().presentViewController(messageVC, animated: true, completion: nil)

func getRootViewController() -> UIViewController

    return (UIApplication.sharedApplication().delegate?.window??.rootViewController)!

【讨论】:

【参考方案4】:

这是 Swift 4 中的完整解决方案 在 didFinishLaunchingWithOptions 中实现这个

 func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool 

 let isLogin = UserDefaults.standard.bool(forKey: "Islogin")
    if isLogin
        self.NextViewController(storybordid: "OtherViewController")


    else
        self.NextViewController(storybordid: "LoginViewController")

    

在 Appdelegate.swift 中的任何地方编写这个函数

  func NextViewController(storybordid:String)


    let storyBoard:UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
    let exampleVC = storyBoard.instantiateViewController(withIdentifier:storybordid )
   // self.present(exampleVC, animated: true)
    self.window = UIWindow(frame: UIScreen.main.bounds)
    self.window?.rootViewController = exampleVC
    self.window?.makeKeyAndVisible()

【讨论】:

以上是关于从 AppDelegate 呈现特定的视图控制器的主要内容,如果未能解决你的问题,请参考以下文章

如何从 appdelegate xcode 11 swift 5 呈现视图控制器

目标 C:如何从 appdelegate 呈现模态视图控制器?

如何通过 TabBarController => NavbarController 从 Appdelegate 呈现视图控制器

从UITabBarController内部呈现UINavigationController

无法从 App Delegate 呈现视图控制器

从 AppDelegate、Swift 导航到 TabBarController 内的特定视图控制器