↑クリックして拡大
↑クリックして拡大
↑クリックして拡大
↑クリックして拡大

頭痛が減ったので共有です!

rebuild.fmを応援しています!

HOME > UIWindowを理解してMain.storyboardを削除してみる

UIWindow

iOS開発でよく耳にしていたUIWindowクラス。正直私はあまり理解していませんでしたのでこの記事にて 理解を深めたいと思います。

UIWindowサンプル画像

UIWindowのクラス階層

NSObject

UIResponder

UIView

UIWindow


参考:iOS開発におけるウィンドウ「UIWindow」の知られざる活用方法とは? #iOS
参考:UIKit Framework Reference UIWindow Class Reference
参考:026 UIWindowの表示
参考:How to set UIWindow property in Swift

どこで利用されているか

例えばSingle View Applicationで新規プロジェクトを作成した場合。ひっそりと一行windowの宣言がAppDelegate.swiftに記載されているだけです。つまり、 開発者もあまり気にしないでUIWindowを使っているようです。


@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        // Override point for customization after application launch.
        return true
    }
    ...
    
}

では、消してコンパイルするとどうなるかやってみます。


@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        // Override point for customization after application launch.
        return true
    }
    ...
    
}

あれ、ランタイムエラーがでるかと思いましたがコンパイルは成功。ただしアプリ起動時にエミュレーターの画面は真っ黒でログには以下のようなエラーがでました


2015-01-23 07:20:27.159 
 The app delegate must implement the window property if it wants to use a main storyboard file.

AppDelagateクラスにはかならずwindowをプロパティにセットしてね(もしstoryboradを使うんであれば)。 AppDelegate.swfitのクラス宣言には、UIApplicationDelegateプロトコルが記載されていますが、 おそらくこのクラス内部でインターフェース的にルールに縛られているようです。UIApplicationDelegateの中身を見てみます。


protocol UIApplicationDelegate : NSObjectProtocol {
    ...
        optional var window: UIWindow? { get set }
    ...
}

宣言されていました。ただ、optionalの記載があるのでコンパイルはできたのかと思われます。先ほどのエラーメッセージによればstoryboardを使わないのであればUIWindowを消しても良さそうなのかな、、、調査してみます

以下の記事によると、storyboardを削除してUIWindowを実装することはできそうです
参考:How do I create a new Swift project without using Storyboards?

Main.storyboardを削除して、以下に修正してコンパイルしてみます


@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        
        self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
        self.window!.backgroundColor = UIColor.whiteColor()
        self.window!.makeKeyAndVisible()
        
        return true
    }
    ...
    
} 

画面が真っ暗にはらず設定した白背景が正しく表示されました。ただし以下ログがコンソールに表示されていました。


2015-01-23 07:36:37.957 
Application windows are expected to have a root view controller at the end of application launch

アプリは起動時にルートビューコントラーを保有している必要があるとの記載がありました。UIWindowの宣言とmakeKeyAndVisibleだけでは 足りないようですので、もうすこし調査します。

解決しました。エラーメッセージにあったようにrootViewControllerとしてセットしていなかった為でした


@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        
        self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
        self.window!.rootViewController = ViewController()
        self.window!.backgroundColor = UIColor.whiteColor()
        self.window!.makeKeyAndVisible()
        
        return true
    }
    ...
    
} 

これでViewControllerクラスが自動で生成されrootViewとしてセットされます。

例えば以下のように、独自に作成したUIViewControllerをプロトコルに持っている SwiftSalaryManViewControllerを宣言させることもできます。


@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        
        self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
        self.window!.rootViewController = SwiftSalaryManViewController()
        self.window!.backgroundColor = UIColor.whiteColor()
        self.window!.makeKeyAndVisible()
        
        return true
    }
    ...
    
} 

まとめ

UIWindowは特に気にしなくても良い。のかな、、、storyboardを消さなくても開発はできますので、、、、ただ、スッキリAppDelegate等の起動まわりを 理解は深まったのでモヤモヤがなくなってUIWindowの呪縛から逃れた気持ちになりました。微力でもお役に立てていれば嬉しいです。

↓こんな記事もありますよ!


2021-05-14 14:21:41

WatchOSのwatchconnectivityのFiletransferの落とし穴。と、避け方。

AppleWatch 実機だと成功するんだけど、シュミレーターだと失敗するという、、、 昔作成してた時は成功してたのになーと思って調べると、どうやら昔は成功してたみたい。watchOS6以降は...

2021-05-06 14:04:37

LINEのアニメーションスタンプ制作の落とし穴、、、失敗談

ゴールデンウィークにLINEスタンプを作成してみました。 作り切って申請も通したんですが、意図したアニメーションと違う、、、、 LINEクリエーターの画面だと、アニメーションのプレビュー...

2021-05-01 18:05:35

久しぶりのAdmobをobjective-cに実装。コンパイルエラーだらけ。バーミッション不具合でエミュレータにインスコできない。

忘れないようにメモ エミュレータにアプリをインストールする際にパーミッション系のエラーがでた時、また、iphone実機にインストールする際にも権限系のエラーが出る場合。 ターゲット→ex...
このエントリーをはてなブックマークに追加
右側のFacebookのLikeをクリック頂けると記事更新の際に通知されますので宜しければご利用下さい!