如何在应用启动时以模态方式呈现视图控制器?

5
我已经创建了一个屏幕,在我的应用程序第一次启动时只出现这个屏幕,这非常好。但是,我希望在我的根视图控制器上以模态方式呈现此屏幕(EditorsNoteViewController是我在首次启动时要以模态方式呈现的屏幕)。有谁知道我该如何做到这一点?以下是我到目前为止所拥有的内容:
Appdelegate.m
        - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
        {
            self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
            if ([[NSUserDefaults standardUserDefaults] boolForKey:@"HasLaunchedOnce"])
            {
                NSLog(@"not first launch");

                      self.viewController = [[UIStoryboard storyboardWithName:@"Main_iPhone" bundle:nil] instantiateViewControllerWithIdentifier:@"articlesNav"];
                self.window.rootViewController = self.viewController;

            }
            else
            {
                [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"HasLaunchedOnce"];
                [[NSUserDefaults standardUserDefaults] synchronize];



                self.viewController = [[UIStoryboard storyboardWithName:@"Main_iPhone" bundle:nil] instantiateViewControllerWithIdentifier:@"articlesNav"];
                self.window.rootViewController = self.viewController;


     EditorsNoteViewController *vc = [[EditorsNoteViewController alloc]init];
             [self.viewController.navigationController presentViewController:vc animated:YES completion:nil];

}
                [self.window makeKeyAndVisible];
    return YES;
}
3个回答

5
我发现你需要调用以下代码:
[self.window makeKeyAndVisible];

在呈现视图控制器之前


1
我之前总是添加dispatch_after,显然这不是个好方法。这个方法真的解决了这个问题。谢谢! - olivaresF

1
我已经多次阅读和遇到这个问题。一种完全解决此问题的方法(没有闪烁或警告)是考虑使用自定义容器视图控制器,该容器视图控制器将包含您的根视图控制器和模态呈现的视图控制器作为子视图控制器。然后,容器视图控制器可以使用自定义动画在两者之间进行转换,效果与 present/dismiss 非常相似。
让我们考虑下面的容器视图控制器:
@implementation ContainerViewController {
    NSMutableArray* stack;
}

- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
        stack = [NSMutableArray new];
    }
    return self;
}

- (void) pushViewController:(UIViewController*) viewController {
    UIViewController* currentViewController = [stack lastObject];
    [stack addObject:viewController];
    if (self.isViewLoaded) {
        [self addChildViewController:viewController];
        [currentViewController willMoveToParentViewController:nil];
        viewController.view.frame = CGRectOffset(self.view.bounds, 0, self.view.bounds.size.height);
        [self transitionFromViewController:currentViewController toViewController:viewController duration:0.3   options:kNilOptions animations:^{
            viewController.view.frame = self.view.bounds;
        } completion:^(BOOL finished) {
            [viewController didMoveToParentViewController:self];
            [currentViewController removeFromParentViewController];
        }];
    }
}

- (void) popViewController {
    UIViewController* currentViewController = [stack lastObject];
    [stack removeLastObject];
    if (self.isViewLoaded) {
        UIViewController* viewController = [stack lastObject];
        [self addChildViewController:viewController];
        [currentViewController willMoveToParentViewController:nil];
        [self transitionFromViewController:currentViewController toViewController:viewController duration:0.3   options:kNilOptions animations:^{
            [self.view sendSubviewToBack:viewController.view];
            currentViewController.view.frame = CGRectOffset(self.view.bounds, 0, self.view.bounds.size.height);
        } completion:^(BOOL finished) {
            [viewController didMoveToParentViewController:self];
            [currentViewController removeFromParentViewController];
        }];
    }
}

- (void)viewDidLoad {
    [super viewDidLoad];
    UIViewController* viewController = [stack lastObject];
    [self addChildViewController:viewController];
    [self.view addSubview:viewController.view];
    [viewController didMoveToParentViewController:self];
}

@end

在您的AppDelegate中,您可以这样写:
ContainerViewController* viewController = [ContainerViewController new];
[viewController pushViewController: [RootViewController new];

if ([self shouldPresentModalViewController]) {
    [viewController pushViewController: [ModalViewController new];
}

self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];

在模态视图控制器中,您可以使用以下代码来关闭它:

[((ContainerViewController*) self.parentViewController) popViewController];

0
假设您已经在故事板中创建了EditorsNoteViewController,您应该像这样初始化它:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
EditorsNoteViewController *vc = (EditorsNoteViewController*)[storyboard instantiateViewControllerWithIdentifier:@"EditorsNoteOrWhateverIdentifierYouChose"];

尝试在你的RootViewController -viewDidLoad中检查你的NSUserDefaults,如果是第一次,则在那里呈现新的UIViewController(这样你就不需要在你的AppDelegate中乱搞了)。
如果你想要以动画方式呈现它,可以在-viewDidAppear中而不是-viewDidLoad中执行。

请查看上面的编辑;我不确定为什么它仍然无法工作。注意:我的EditorsNoteViewController是一个xib文件,而不是在故事板中创建的。 - Brittany
无论如何,如果你想要视觉上呈现视图控制器,alloc init 将不起作用。请尝试使用 -initWithNibName:@"nib" bundle:nil。 - Bogdan
你可以在RootViewController的-(void)prepareForSegue方法中使用alloc init,并在-viewDidLoad中使用方法'[self performSegueWithIdentifier:@"your segue" sender:self]'进行呈现。 - Bogdan
抱歉,它只在Storyboard中有效。很抱歉没有注意到 :( - Bogdan
我按照你的方式在我的Storyboard中创建了视图,但是控制台显示以下错误:“警告:试图在不在窗口层次结构中的<UINavigationController: 0x15d608e90>上呈现<UIViewController: 0x15d5174f0>!” 你有什么想法为什么会出现这种情况? - Brittany
显示剩余2条评论

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