ビューベースの iOS アプリケーション テンプレート
-
10-10-2019 - |
質問
Apple の「初めての iOS アプリケーション」ガイドを読みましたが、そこに記載されているすべてのことが非常に明確に思えます。ただし、XCode で提供される View ベースの iOS アプリケーション テンプレートがどのように機能するかを理解しようとすると、いくつかの興味深い難問に遭遇します。
アプリケーションが *-Info.plist ファイルからメイン nib ファイル名 (通常は MainWindow.xib) を取得することを理解しています。私が理解できないのは、デフォルトでこの View ベースのアプリケーション テンプレートで作成されたコントローラーにどの nib ファイルが関連付けられているかを XCode がどのようにして認識するのかということです。このガイドでは、Window ベースのアプリケーションから始めて、次のようなものを「記述する必要があります」。
MyViewController *aViewController = [[MyViewController alloc]
initWithNibName:@"MyViewController" bundle:[NSBundle mainBundle]];
[self setMyViewController:aViewController];
それは完全に理にかなっています。ただし、View ベースの iOS アプリケーション テンプレートにはそのようなものはなく、「ユーザー インターフェイスに XIB を使用する」オプションを指定して UIViewController サブクラスを作成した限り、この nib 仕様はそもそも実際には必要ではないことがわかりました。 」にチェックが入った。私の質問は、XCode がどのペン先がこのコントローラーに関連付けられているかをどのようにして知るのかということです。この接続はいくつかのファイルに保存されていますか、それとも何らかの規則(おそらくコントローラーと nib ファイルに同じ名前)に従って保存されていますか?さらに、MainWindow.xib 内のインターフェイス ビルダーのコントローラー ビューの「"MyViewBasedAppController" からロード」というサブタイトルはどこから来たのでしょうか?コントローラーを手動で追加するときには絶対に存在しないので、単純なコード テンプレートを選択しているだけだと思っているときに、XCode が背後でどのような魔法を実行するのかに興味があります。
解決
ターゲット情報 (ターゲットをダブルクリックすると表示されます) の「プロパティ」タブを見ると、メイン Nib ファイルの名前が表示されます。「Nib」と「Xib」という単語は、これらの目的では交換可能です。Xib は、Nib の新しい代替品にすぎません。
テンプレートから作成したばかりの「MainWindow」になります。MainWindow.xib を開くと、「[プロジェクト名] App Delegate」というオブジェクトがあることがわかります。インスペクターを表示して「i」タブを確認すると、クラスのタイプが表示されます。上部に名前が付けられています。[接続] タブ (右向きの矢印) を確認すると、ファイル所有者 (UIApplication 自体) に「デリゲート」プロパティがアタッチされていることがわかります。
「viewController」というアウトレットがあることもわかります。これは、「[プロジェクト名] View Controller」という xib 内の別のオブジェクトにアタッチされます。そのタイプを確認すると、それが Xcode がプロジェクトに追加したビュー コントローラーのタイプであることがわかります。その属性 (スライダー グラフィックのあるインスペクターの最初のタブ) を見ると、別の nib ファイルがその主な詳細を含むものとして指定されていることもわかります。
説明のために、プロジェクトに「NibTest」という名前を付け、何も変更しなかったとします。
実行時に、デバイスは Info.plist をロードします。そこでは、デリゲートのタイプが NibTestAppDelegate であることがわかります。したがって、クラス NibTestAppDelegate のインスタンスをインスタンス化し、UIApplication の delegate プロパティをそれに設定します。
次に、MainWindow.nib から、NibTestAppDelegate に NibTestViewController 型の viewController という名前のメンバーがあることがわかります。したがって、そのインスタンスを作成し、作成したばかりの NibTestAppDelegate インスタンスの viewController プロパティをそれに設定します。
そうすることで、他の xib が開き、同じ種類の手順が続行されます。
Objective-C は完全にリフレクティブなランタイムを備えているため、実行時にクラス名によってオブジェクトをインスタンス化できます。これは、たとえば Objective-C と C++ の違いの 1 つです。
Xcode は隠しコードを生成したり、隠れた命名規則に依存したりしません。すべては実行時に OS によって判断されます。
編集:たとえば、あなたの例の代わりに次のようにします。
MyViewController *aViewController = [[MyViewController alloc]
initWithNibName:@"MyViewController" bundle:[NSBundle mainBundle]];
実際には次のようにすることができます。
MyViewController *aViewController = [[NSClassFromString(@"MyViewController") alloc]
initWithNibName:@"MyViewController" bundle:[NSBundle mainBundle]];
MyViewController がプログラム内またはより広範なランタイム内に存在する限り、これらは同じように動作します。
あるいは、他の任意の文字列オブジェクトを渡すこともできます。 NSClassFromString
. 。必要に応じて、ユーザーにそれを要求することもできます (ただし、セキュリティ上の理由からは非常に悪い考えです)。