iOS在没有闪存的情况下启动模态视图控制器

son*_*rxo 35 objective-c startup modalviewcontroller ios

我想在初次启动时向用户提供一个教程向导.

有没有办法UIViewController在应用程序启动时呈现模态,而不至少看到毫秒,它rootViewController背后呢?

现在我正在做这样的事情(为了清楚起见省略了首次启动检查):

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    // ...

    UIStoryboard *storyboard = self.window.rootViewController.storyboard;
    TutorialViewController* tutorialViewController = [storyboard instantiateViewControllerWithIdentifier:@"tutorial"];
    tutorialViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
    [self.window makeKeyAndVisible];
    [self.window.rootViewController presentViewController:tutorialViewController animated:NO completion:NULL];
}
Run Code Online (Sandbox Code Playgroud)

没有运气.我试图[self.window makeKeyAndVisible];[... presentViewController:tutorialViewController ...]声明之前 移动,但随后模态甚至没有出现.

小智 33

所有presentViewController方法都要求呈现视图控制器首先出现.为了隐藏根VC,必须呈现覆盖.启动屏幕可以继续显示在窗口上,直到演示文稿完成,然后淡出叠加层.

    UIView* overlayView = [[[UINib nibWithNibName:@"LaunchScreen" bundle:nil] instantiateWithOwner:nil options:nil] firstObject];
overlayView.frame = self.window.rootViewController.view.bounds;
overlayView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

UIStoryboard *storyboard = self.window.rootViewController.storyboard;
TutorialViewController* tutorialViewController = [storyboard instantiateViewControllerWithIdentifier:@"tutorial"];
tutorialViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self.window makeKeyAndVisible];
[self.window addSubview:overlayView];
[self.window.rootViewController presentViewController:tutorialViewController animated:NO completion:^{
    NSLog(@"displaying");
    [UIView animateWithDuration:0.5 animations:^{
        overlayView.alpha = 0;
    } completion:^(BOOL finished) {
        [overlayView removeFromSuperview];
    }];
}];
Run Code Online (Sandbox Code Playgroud)

  • 我认为**Spoek**将他的名字改为**ullstrm**,无论如何这是解决方案**Cœur**指的是:/sf/answers/2902881411/ (3认同)
  • 如果有人面临_开始/结束外观转换的不平衡呼叫_,请参阅********答案以获取使用`DispatchQueue`的解决方案。 (2认同)

ull*_*trm 11

布鲁斯在Swift 3中的回答是:

if let vc = window?.rootViewController?.storyboard?.instantiateViewController(withIdentifier: "LOGIN")
    {
        let launch = UIStoryboard(name: "LaunchScreen", bundle: nil).instantiateInitialViewController()!
        launch.view.frame = vc.view.bounds
        launch.view.autoresizingMask = [UIViewAutoresizing.flexibleWidth, UIViewAutoresizing.flexibleHeight]
        window?.makeKeyAndVisible()
        window?.addSubview(launch.view)

        //Using DispatchQueue to prevent "Unbalanced calls to begin/end appearance transitions"
        DispatchQueue.global().async {
            // Bounce back to the main thread to update the UI
            DispatchQueue.main.async {
                self.window?.rootViewController?.present(vc, animated: false, completion: {

                    UIView.animate(withDuration: 0.5, animations: {
                        launch.view.alpha = 0
                    }, completion: { (_) in
                        launch.view.removeFromSuperview()
                    })
                })
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

  • 迄今为止最佳解决方案 您甚至可以添加一个解释,说明为什么必须执行`DispatchQueue.global().async`来解决_Unbalanced调用以开始/结束外观transition_. (3认同)

小智 8

也许你可以使用"childViewController"

UIStoryboard *storyboard = self.window.rootViewController.storyboard;
TutorialViewController* tutorialViewController = [storyboard instantiateViewControllerWithIdentifier:@"tutorial"];

[self.window addSubview: tutorialViewController.view];
[self.window.rootViewController addChildViewController: tutorialViewController];

[self.window makeKeyAndVisible];
Run Code Online (Sandbox Code Playgroud)

当您需要解雇您的导师时,您可以从超级视图中删除其视图.你也可以通过设置alpha属性在视图上添加一些动画.希望有用:)

  • 我只是尝试这种方法.我不能接受这个作为正确的答案,因为它不使用模态演示,但我已经投票了,谢谢! (3认同)

Ben*_*hen 6

这个问题在iOS 10中仍然存在.我的修复是:

  1. viewWillAppear加入莫代尔VC作为childVC到rootVC
  2. viewDidAppear:
    1. 删除modalVC作为rootVC的子级
    2. 以动态方式呈现childVC

码:

extension UIViewController {

    func embed(childViewController: UIViewController) {
        childViewController.willMove(toParentViewController: self)

        view.addSubview(childViewController.view)
        childViewController.view.frame = view.bounds
        childViewController.view.autoresizingMask = [.flexibleHeight, .flexibleWidth]

        addChildViewController(childViewController)
    }


    func unembed(childViewController: UIViewController) {
        assert(childViewController.parent == self)

        childViewController.willMove(toParentViewController: nil)
        childViewController.view.removeFromSuperview()
        childViewController.removeFromParentViewController()
    }
}


class ViewController: UIViewController {

    let modalViewController = UIViewController()

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

        //BUG FIX: We have to embed the VC rather than modally presenting it because:
        // - Modal presentation within viewWillAppear(animated: false) is not allowed
        // - Modal presentation within viewDidAppear(animated: false) is not visually glitchy
        //The VC is presented modally in viewDidAppear:
        if self.shouldPresentModalVC {
            embed(childViewController: modalViewController)
        }
        //...
    }


    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        //BUG FIX: Move the embedded VC to be a modal VC as is expected. See viewWillAppear
        if modalViewController.parent == self {
            unembed(childViewController: modalViewController)
            present(modalViewController, animated: false, completion: nil)
        }

        //....
    }
}
Run Code Online (Sandbox Code Playgroud)