【问题标题】:How to present two different ViewControllers from AppDelegate based on two conditions in iOS?如何根据 iOS 中的两个条件从 AppDelegate 呈现两个不同的 ViewController?
【发布时间】:2013-12-12 07:53:59
【问题描述】:

当应用程序从最小化恢复时,我想从 AppDelegate 呈现两个 ViewController。
我已经使用applicationWillEnterForeground: 函数来呈现 ViewControllers。但是,当我使用以下代码运行应用程序时,它会崩溃并显示错误:Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Application tried to present a nil modal view controller on target <ViewController: 0x1566a420>.' 而且我使用 storyBoards 来呈现 ViewControllers 而不是 nib 文件。 请帮助我解决这个问题,因为我哪里出错了。一周以来我一直在为此苦苦挣扎。

- (void)applicationWillEnterForeground:(UIApplication *)application
{
    if(ConditionOne)
    {
         [self.window.rootViewController presentViewController:[self getMyFilesActivityView] animated:YES completion:nil];
         [self.window.rootViewController dismissViewControllerAnimated:YES completion:nil];
    }
    else if(ConditionTwo)
    {
         [self.window.rootViewController presentViewController:[self getPasswordActivityView] animated:YES completion:nil];
         [self.window.rootViewController dismissViewControllerAnimated:YES completion:nil];
    }
}
-(MyFilesViewController *)getMyFilesActivityView
{
    if(self.myFiles== nil)
    {
        self.myFiles = [[MyFilesViewController alloc]init];
        myFiles = [self.storyboard instantiateViewControllerWithIdentifier:@"MyFilesID"];
    }
    return self.myFiles;
}
-(PasswordEnterViewController *)getPasswordActivityView
{
    if(self.passwordEnter== nil)
    {
        self.passwordEnter = [[PasswordEnterViewController alloc]init];
        passwordEnter = [self.storyboard instantiateViewControllerWithIdentifier:@"PasswordEnterID"];
    }
    return self.passwordEnter;
}

【问题讨论】:

    标签: ios cocoa-touch uiviewcontroller


    【解决方案1】:

    这里有些地方不对。

    首先,当你运行这段代码时:

    [self.window.rootViewController presentViewController:[self getMyFilesActivityView] animated:YES completion:nil];
    [self.window.rootViewController dismissViewControllerAnimated:YES completion:nil];
    

    它将首先呈现视图控制器,然后直接将其关闭,这不是您想要的。您想在显示另一个视图控制器之前关闭旧视图控制器吗?那么你应该这样做:

    [self.window.rootViewController dismissViewControllerAnimated:YES completion:^{
        [self.window.rootViewController presentViewController:[self getViewController] animated:YES completion:nil];
    }];
    

    另外,你的 getter 有一些非常错误的地方:

        self.passwordEnter = [[PasswordEnterViewController alloc]init];
        passwordEnter = [self.storyboard instantiateViewControllerWithIdentifier:@"PasswordEnterID"];
    

    第一行分配一个 PasswordEnterViewController,第二行做同样的事情。在这种情况下,第一行不会做任何事情(如果 self.passwordEnter 和 passwordEnter 甚至是同一个变量,那就很不清楚了。)

    这就是你的 setter 的样子:

    - (PasswordEnterViewController *)passwordEnter
    {
        if(_passwordEnter == nil)
        {
            self.passwordEnter = [self.storyboard instantiateViewControllerWithIdentifier:@"PasswordEnterID"];
        }
        return _passwordEnter;
    }
    

    您的 passwordEnter 属性应如下所示:

    @property (nonatomic, strong) UIViewController *passwordEnter;
    

    此外,请删除您可能正在进行的任何 @synthesize 调用,因为您似乎覆盖了自动合成器,这使得您的代码难以遵循。

    当你的 setter 和 property 看起来像上面那样时,你可以简单地使用下面的代码来呈现它:

    [self.window.rootViewController presentViewController:self.passwordEnter animated:YES completion:nil];
    

    【讨论】:

    • 我尝试了和你说的一样的方法,但它仍然崩溃并出现同样的错误。
    • 那么要么你的故事板标识符是错误的,要么你实现了错误的吸气剂。无论哪种情况,getter 都必须返回 nil。尝试在此处设置断点并找出原因
    • 我已将情节提要也声明为属性。那么这会影响代码吗??
    • 是的,这可能是问题所在。不要声明情节提要! self.storyboard 是一个视图控制器属性,它获取运行代码的视图控制器从中加载的故事板。相反,您可以使用 [[UIStoryboard storyboardWithName:@"StoryboardName"] instantiateView... 等
    • 如果我不声明情节提要,那么它会显示错误为“选择器实例化ViewControllerWithIdentifier 没有已知类:
    猜你喜欢
    • 2016-08-22
    • 1970-01-01
    • 2018-02-27
    • 1970-01-01
    • 1970-01-01
    • 2022-08-19
    • 1970-01-01
    • 1970-01-01
    • 2020-07-07
    相关资源
    最近更新 更多