IOS:程序化rootViewController以不同于Storyboard' isInitialView'

时间:2014-08-13 10:32:24

标签: ios uiview uiviewcontroller swift mpmovieplayercontroller

目的是实现一个启动画面,只有在我修改didFinishLaunchingWithOptions后才会显示,以便动态选择合适的视图控制器。逻辑似乎工作正常,我打算加载的视图是启动的视图

然而,如果我没有更改didFinishLaunchingWithOptions功能,则UI似乎缺少原本会显示的元素。

func application(application: UIApplication!, didFinishLaunchingWithOptions launchOptions: NSDictionary!) -> Bool
{
    window = UIWindow(frame: UIScreen.mainScreen().bounds)
    let storyBoard = UIStoryboard(name: "Main", bundle: nil)
    var entryViewController: UIViewController?

    if NSUserDefaults.standardUserDefaults().boolForKey("hasSeenWelcomeScreen") == true
    {
        entryViewController = storyBoard.instantiateViewControllerWithIdentifier("NavigationController") as? UIViewController
    }
    else
    {
        entryViewController = storyBoard.instantiateViewControllerWithIdentifier("WelcomeViewController") as? UIViewController
        NSUserDefaults.standardUserDefaults().setValue(true, forKey: "hasSeenWelcomeScreen")
        NSUserDefaults.standardUserDefaults().synchronize()
    }

    self.window?.rootViewController = entryViewController
    self.window?.makeKeyAndVisible()

    return true
}

我的WelcomeViewController是一个简单的视图,1 label1 buttona movie在后​​台播放(类似于Spotify / Vine的欢迎屏幕)。调试代码我可以看到初始化方法确实被执行了,但是当我动态覆盖初始视图

时,它只是似乎没有显示的框架
import UIKit
import MediaPlayer
import QuartzCore

class WelcomeViewController: UIViewController {

    var moviePlayerController: MPMoviePlayerController = MPMoviePlayerController()

    @IBOutlet weak var loginButton: UIButton!
    @IBOutlet weak var appNameLabel: UILabel!

    override func viewDidLoad()
    {
        super.viewDidLoad()
        buildMoviePreview()
        buildButtonDesign()
    }

    override func viewWillAppear(animated: Bool)
    {
        self.view.addSubview(self.moviePlayerController.view)
        self.view.addSubview(self.loginButton)
        self.view.addSubview(self.appNameLabel)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    override func prefersStatusBarHidden() -> Bool {
        return true
    }

    private func buildButtonDesign()
    {
        loginButton.layer.borderColor = UIColor.whiteColor().CGColor
        loginButton.layer.borderWidth = 2.0
        loginButton.layer.cornerRadius = 7.0
    }

    private func buildMoviePreview()
    {
        let filePath = NSBundle.mainBundle().pathForResource("intro", ofType: "mov")
        self.moviePlayerController.contentURL = NSURL.fileURLWithPath(filePath)
        self.moviePlayerController.movieSourceType = .File
        self.moviePlayerController.repeatMode = .One
        self.moviePlayerController.view.frame = self.view.bounds
        self.moviePlayerController.scalingMode = .AspectFill
        self.moviePlayerController.controlStyle = .None
        self.moviePlayerController.allowsAirPlay = false
        self.moviePlayerController.shouldAutoplay = true
        self.moviePlayerController.play()
    }
}

为了完整起见,这些是使用XCode UI调试器时布局的差异。请注意,即使它们实现了相同的viewController,它们也有所不同。唯一的区别是,一个已通过编程方式设置为初始视图,而另一个已通过故事板设置为初始视图

View Comparison


并排渲染问题的屏幕截图

uiRendering

2 个答案:

答案 0 :(得分:1)

你的做法......不寻常。故事板有一个根视图控制器,原因通常在启动时您只需让应用程序处理加载故事板并将该根视图控制器安装为窗口的主视图控制器。 (加载的Storyboard在应用程序目标的常规设置中指定为"主界面")

在这种情况下,我建议将根视图控制器设置为"正常"应用程序的视图...您希望用户在日常启动应用程序时看到的应用程序。

首次发布时定义您的""将控制器视为故事板中的单独视图控制器,并将根视图控制器中的模态segue添加到第一个启动视图控制器上。

然后在您的applicationDidFinishLaunching中,如果用户从未见过第一个启动控制器......只需要让Storyboard接受该segue。如果用户已经看到第一个启动演示文稿将跳过segue。

我在代码中看到的另一个问题是viewWillAppear方法。您不必在viewWillAppear中将视图添加为子视图...这些子视图应该是在从nib文件加载视图时设置的。

一个例外是您的电影播放器​​的视图,但您的电影播放器​​由一个单独的视图控制器拥有。该单独的视图控制器与视图控制器层次结构分离,并且没有在正确的时间调用它自己的视图控制器方法。 (所以它永远不会收到类似" viewWillAppear"这可能会让它让电影准备好播放的电话)。

您可能想要做的是实施" awakeFromNib"并确保影片播放器的视图控制器是此视图控制器的子控制器。 (所以在AwakeFromNib中,WelcomeViewController使用addChildViewController来确保电影控制器在层次结构中。)

答案 1 :(得分:1)

用户2故事板会更好:

  • 一个欢迎屏幕
  • 另一个与你的应用程序的其余部分

应用程序启动将如下所示:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool {

    var storyBoard : UIStoryboard!
    if NSUserDefaults.standardUserDefaults().boolForKey("hasSeenWelcomeScreen") == true {
        changeStoryBoard("Main")
    }
    else {
        changeStoryBoard("Welcome")
    }

    return true
}


func changeStoryBoard(name :String) {
    var storyBoard = UIStoryboard(name:name, bundle: nil)
    var viewController: AnyObject! = storyBoard.instantiateInitialViewController() ;
    self.window!.rootViewController = viewController as UIViewController
}