LoginSignup
1
1

More than 3 years have passed since last update.

Creating a ViewController & xib, and Loading them from Storyboard

Last updated at Posted at 2019-04-16

hatenablogから2018-12-10の記事を移行しました。
https://bitsandbobs.hatenablog.jp/entry/2018/12/10/025556


ViewController と xib ファイルを作って Storyboard から呼び出す手順をまとめておく。
!注意!これは Cocoa App (macOS アプリ) に関する記事です。

環境

  • macOS High Sierra 10.13.6
  • Xcode 10.1

手順

ViewController と xib ファイルを作成する

20181210012507.png
New File から

20181210012735.png
macOS / Cocoa Class を選択して Next

20181210012803.png
Subclass of は NSViewController を選択

Also create XIB file for .. のチェックオン (手間が省けるので)

クラス名を入力して Next → Create

20181210012837.png
ViewController のソースファイルと、同名の xib ファイルが作成される

xib の編集

20181210012907.png
File's owner の Custom Class 名に先ほど作ったクラスが設定されていることを確認しておく

その後、好きなように View にアレコレ追加していく(割愛)

Storyboard の編集

20181210013134.png
View Controller の Custom Class 名に作ったクラスを指定する

20181210013152.png
デフォルトで作られている View を Storyboard から削除しておく

(Storyboard に View が残っていると xib ファイルではなく、この View を優先して表示するため)

あとがき

当初 xib ファイルが読み込まれずどハマりしました。
Storyboard で ViewController を追加したときに初期作成される View を削除してなかったからですが、単純なことほど気づきにくいものですね。
この問題の原因を調べる過程でわかったことを以下にまとめておきます。

  • ViewController が View を初期化するとき(loadView がコールされるとき) nibName プロパティが nil の場合はクラス名と同名の xib ファイルをロードする

Prior to OS X v10.10, the loadView() method did not provide well-defined behavior if the nibName property’s value was nil. In macOS 10.10 and later, however, you get correct behavior without specifying a nib name as long as the nib file’s name is the same as that of the view controller.

loadView() - NSViewController | Apple Developer Documentation

  • ViewController が Storyboard からインスタンス化されるときは init(nibName: bundle:) ではなく init(coder:) コンストラクタがコールされる
  • Storyboard にて ViewController に View が設定されている場合は、nibName = ViewController の Object ID1 + "-view-" + View の Object ID (例: "XfG-lQ-9wD-view-Qcj-BY-oc5")となる
  • Storyboard にて ViewController に View が設定されていない場合は nibName = nil となる

ちなみに調査の過程で以下の方法を試しました。
困ったことに、これらは全て期待する動きをしたのですよね。

  • NSViewController の修正
    • viewDidLoad で NSNib#instantiate
    • loadView をオーバーライドして NSNib#instantiate
    • init(coder:) をオーバーライドして super.init(nibName: bundle:)
    • nibName プロパティをオーバーライドして nil またはクラス名を返す
  • Storyboard の修正
    • User Defined Runtime Attributes に nibName:String を追加する
    • Storyboard の ViewController から View を消す(!!!)

Runtime Attributes に nibName を追加する方法は ViewController クラスは作らないけど View は xib で外だしにしたいときとかに使えそうです。

nibName や init(coder:) をオーバーライドする方法は xib のファイル名がクラス名と異なるとき(例えば、動的にViewを切り替えるときなど)に使えるかもしれません。

参考


  1. Object ID は Identity inspector の Document に表示されている 

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1