【问题标题】:Programmatically accessing the launch screen XIB or storyboard以编程方式访问启动屏幕 XIB 或情节提要
【发布时间】:2014-09-22 04:49:13
【问题描述】:

应用如何访问用于其启动屏幕的 XIB 或情节提要? XIB 不在主包中(例如:NSBundle.mainBundle().pathsForResourcesOfType(nil, inDirectory: ""))。这尤其出人意料,因为“Launch Screen.xib”列在“Copy Bundle Resources”构建阶段,但未在包中显示 ip,因此 Xcode 必须对其进行特殊处理。

【问题讨论】:

    标签: ios ios8


    【解决方案1】:

    如果 LaunchScreen 是 storyboard 而不是 xib,请使用以下代码。

    let launchScreen = UIStoryboard(name: "LaunchScreen", bundle: nil).instantiateInitialViewController()
    if let launchView = launchScreen?.view {
      view.addSubview(launchView)
    }
    

    【讨论】:

      【解决方案2】:

      由于 Xib 不在主包中,获取路径返回 nil,但是你可以在没有路径帮助的情况下获取启动屏幕的 XIB 使用方法

        let launchScreenNib = UINib(nibName: "LaunchScreen", bundle: nil)
      

      您可以从 XIB 加载获取视图

      // Swift
      let objects = NSBundle.mainBundle().loadNibNamed("LaunchScreen", owner: self, options: nil)
      let view = objects[0] as UIView
      
      // Obj C
      NSArray *objects = [[NSBundle mainBundle] loadNibNamed:@"LaunchScreen" owner:self options:nil];
      UIView *view = [objects objectAtIndex:0];
      

      【讨论】:

      • Xcode 没有为启动屏幕生成 NIB,因此该代码会崩溃。如果 NIB 不在捆绑包中,则 bundle.loadNibNamed(...) 不起作用。我可以通过使用 Interface Builder 中的“用作启动屏幕”选项来让它工作,这使得 Xcode 生成 NIB。
      • @ide update Xcode ,默认在项目创建过程中创建 LaunchScreen.xib。
      • 我的意思是我有 LaunchScreen.xib,当我启动应用程序时它正在显示...只是 Xcode 没有将其转换为 NIB 文件并将其复制到包中。
      【解决方案3】:

      根据我自己的问题,似乎关闭和打开“用作启动屏幕”会导致 Xcode 为启动屏幕构建一个 NIB 文件。

      1. 在完成彻底清理(删除 DerivedData)并从设备中删除应用程序后,我在 LaunchScreen.xib 中关闭了主视图控制器的“用作启动屏幕”。运行应用会导致它在没有启动屏幕的情况下启动,但构建现在正在创建 LaunchScreen.nib。
      2. 再次彻底清理并从设备中删除了该应用程序。重新打开并重建“用作启动屏幕”。在新的 DerivedData 文件夹下的应用程序包中,LaunchScreen.nib 仍然存在。
      3. bundle.loadNibNamed(...) 现在工作正常。

      【讨论】:

        【解决方案4】:

        这是一个 Swift 5,SceneDelegate 实现

        此实现还从 info.plist 文件中检测 LaunchScreen 的配置名称。

        //
        //  SceneDelegate.swift
        //  Extended Launch Screen Example
        //
        //  Created by Leslie Godwin on 2020/04/24.
        //
        
        import UIKit
        
        class SceneDelegate: UIResponder, UIWindowSceneDelegate
        {
            var window:       UIWindow?
            var splashWindow: UIWindow?
        
            func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions)
            {
                // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
                // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
                // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
                guard let _ = (scene as? UIWindowScene) else { return }
            }
        
            func sceneDidDisconnect(_ scene: UIScene)
            {
                // Called as the scene is being released by the system.
                // This occurs shortly after the scene enters the background, or when its session is discarded.
                // Release any resources associated with this scene that can be re-created the next time the scene connects.
                // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
            }
        
            func sceneDidBecomeActive(_ scene: UIScene)
            {
                // ⏳Extend Splash screen only if `splashWindow` is `nil` otherwise it is already shown.
                //
                if let launchStoryboardName = InfoPList.launchStoryboardName,
                   let windowScene          = self.window?.windowScene
                {
                    splashWindow = splashWindow ??
                    {
                        let window = UIWindow(windowScene: windowScene)
                            window.windowLevel = .statusBar
        
                        let storyboard = UIStoryboard(name: launchStoryboardName, bundle: nil)
        
                        window.rootViewController = storyboard.instantiateInitialViewController()
                        window.isHidden           = false
        
                        // ⏳Wait for 5 seconds, then remove.
                        //
                        DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(5))
                        {
                            UIView.animate(withDuration: -1, // system default
                                animations:
                                {
                                    self.splashWindow?.alpha = 0
                                },
                                completion:
                                { _ in
                                    self.splashWindow?.isHidden = true
                                    self.splashWindow = nil
                                }
                            )
                        }
        
                        return window
                    }()
                }
        
                // Called when the scene has moved from an inactive state to an active state.
                // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
            }
        
            func sceneWillResignActive(_ scene: UIScene) {
                // Called when the scene will move from an active state to an inactive state.
                // This may occur due to temporary interruptions (ex. an incoming phone call).
            }
        
            func sceneWillEnterForeground(_ scene: UIScene) {
                // Called as the scene transitions from the background to the foreground.
                // Use this method to undo the changes made on entering the background.
            }
        
            func sceneDidEnterBackground(_ scene: UIScene) {
                // Called as the scene transitions from the foreground to the background.
                // Use this method to save data, release shared resources, and store enough scene-specific state information
                // to restore the scene back to its current state.
            }
        }
        
        //
        // PList Helper
        //
        
        struct InfoPList
        {
            private static func value(for name: String) -> String? { Bundle.main.object(forInfoDictionaryKey: name) as? String }
        
            static var bundleIdentifier:         String? { self.value(for: "CFBundleIdentifier") }
            static var bundleDisplayName:        String? { self.value(for: "CFBundleDisplayName") }
            static var bundleShortVersionString: String? { self.value(for: "CFBundleShortVersionString") }
            static var bundleVersion:            String? { self.value(for: "CFBundleVersion") }
        
            static var launchStoryboardName: String? { self.value(for: "UILaunchStoryboardName") }
            static var mainStoryboardName:   String? { self.value(for: "UIMainStoryboardFile") }
        }
        

        【讨论】:

          猜你喜欢
          • 2012-10-13
          • 2013-09-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-12-28
          • 1970-01-01
          • 1970-01-01
          • 2011-03-22
          相关资源
          最近更新 更多