【问题标题】:How to present View Controller modally on app launch?如何在应用启动时以模态方式呈现视图控制器?
【发布时间】:2014-09-08 00:14:23
【问题描述】:

我创建了一个仅在我的应用首次启动时出现的屏幕;效果很好。但是,我想在我的根视图控制器顶部以模态方式呈现此屏幕(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;
}

【问题讨论】:

    标签: ios objective-c


    【解决方案1】:

    我知道你必须打电话给

    [self.window makeKeyAndVisible];
    

    在呈现视图控制器之前

    【讨论】:

    • 我老是加了一个dispatch_after,明显不好。这真的解决了。谢谢!
    【解决方案2】:

    我已经多次阅读并遇到过这个问题。完全解决此问题的一种方法(没有任何闪烁或警告)是考虑将包含您的根视图控制器和模态呈现的视图控制器的自定义容器视图控制器作为子视图控制器。然后容器视图控制器可以使用自定义动画在两者之间转换,效果与呈现/关闭非常相似。

    让我们考虑以下容器视图控制器:

    @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];
    

    【讨论】:

      【解决方案3】:

      假设您已经在情节提要中创建了 EditorsNoteViewController,您应该像这样初始化它:

      UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
      EditorsNoteViewController *vc = (EditorsNoteViewController*)[storyboard instantiateViewControllerWithIdentifier:@"EditorsNoteOrWhateverIdentifierYouChose"];
      

      尝试检查您的 RootViewController -viewDidLoad 中的 NSUserDefaults,如果是第一次,请在此处显示新的 UIViewController(这样您就不需要弄乱您的 AppDelegate)。

      如果你想以动画形式呈现它,你可以在 -viewDidAppear 而不是 -viewDidLoad 中做到这一点。

      【讨论】:

      • 见上面的编辑;不知道为什么它仍然无法正常工作。注意:我的 EditorsNoteViewController 是一个 xib 文件,不是在故事板中创建的。
      • 无论如何,如果您想直观地呈现视图控制器,alloc init 将不会这样做。试试 -initWithNibName:@"nib" bundle:nil。
      • 您可以在 RootViewController 的 -(void)prepareForSegue 中使用 alloc init 并将其呈现在 -viewDidLoad 中,方法是:'[self performSegueWithIdentifier:@"your segue" sender:self]'跨度>
      • 使用 initWithNibName 也不起作用...:/ performSegueWithIdentifier 仅在我在情节提要中创建视图时才起作用?
      • 是的,它只适用于情节提要。抱歉没注意:(
      猜你喜欢
      • 1970-01-01
      • 2020-11-24
      • 2011-01-20
      • 2014-01-20
      • 1970-01-01
      • 2023-03-18
      • 2013-09-20
      • 1970-01-01
      • 2022-01-11
      相关资源
      最近更新 更多