Interface Builderを使わずにMacアプリケーション作成 - nib検証篇 2
MainMenu.xibには何が定義されているのか
Xcode 4で作成したプロジェクトに最初から用意されているMainMenu.xib
には何が定義されているのか。それがわかれば、nibの読み込み時の処理がつかめるかもしれない。
xibの基礎構造
xibファイルはそもそもXMLである(xib = XML Interface Builderの頭文字)。必要な定義が全て記述されており、そのままでは解析するにも膨大であることから、分解して小分けにした。
まず、Interface Builder上のDocument Outlineから以下のオブジェクトを取り除いていく。
- MainMenu(
NSMenu
のインスタンス) - window(
NSWindow
のインスタンス) - AppDelegate(
NSObject
のサブクラスAppDelegate
のインスタンス) - Font Manager(
NSFontManager
のインスタンス)
この状態にすると142KBもあったMainMenu.xibが4KBになっており、いかに定義が多かったかがわかる。
この状態でMainMenu.xib
を開くと次のXMLが記述されている。(要約と整形をしています)
<?xml version="1.0" encoding="UTF-8"?>
<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="8.00">
<data>
<int key="IBDocument.SystemTarget">1080</int>
<string key="IBDocument.SystemVersion">11D50</string>
<string key="IBDocument.InterfaceBuilderVersion">2457</string>
<string key="IBDocument.AppKitVersion">1138.32</string>
<string key="IBDocument.HIToolboxVersion">568.00</string>
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">…</object>
<array key="IBDocument.IntegratedClassDependencies">…</array>
<array key="IBDocument.PluginDependencies">…</array>
<object class="NSMutableDictionary" key="IBDocument.Metadata">…</object>
<array class="NSMutableArray" key="IBDocument.RootObjects" id="1048">…</array>
<object class="IBObjectContainer" key="IBDocument.Objects">…</object>
<object class="IBClassDescriber" key="IBDocument.Classes"/>
<int key="IBDocument.localizationMode">0</int>
<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
<int key="IBDocument.defaultPropertyAccessControl">3</int>
<dictionary class="NSMutableDictionary" key="IBDocument.LastKnownImageSizes">…</dictionary>
<bool key="IBDocument.UseAutolayout">YES</bool>
</data>
</archive>
Versionsに関する記述はさほど重要では無いので、IBDocument.IntegratedClassDependencies
以降の行で何を定義しているかを調べてみる。
IBDocument.IntegratedClassDependencies
<array key="IBDocument.IntegratedClassDependencies">
<string>NSCustomObject</string>
</array>
直訳するとIntegrated Class Dependenciesは統合クラスの依存関係。Interface Builder内で定義された各インスタンスのクラスについて記述しているのだろうか。これはMac Developer Libraryには載っていない。
数々のオブジェクトを取り除く前はこう。
<array key="IBDocument.IntegratedClassDependencies">
<string>NSWindowTemplate</string>
<string>NSView</string>
<string>NSMenu</string>
<string>NSMenuItem</string>
<string>NSCustomObject</string>
</array>
ここで確認できるNSWindowTemplate
やNSCustomObject
といったクラスも公開されていない。
IBDocument.PluginDependencies
<array key="IBDocument.PluginDependencies">
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
</array>
次はプラグインの依存関係。CocoaPlugin
はInterface Builder Pluginのことで/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Interface Builder/Plug-ins
に格納されていた。おそらくウインドウ右下のObject libraryパレットに表示されている内容のことだろう。
IBDocument.Metadata
<object class="NSMutableDictionary" key="IBDocument.Metadata">
<string key="NS.key.0">PluginDependencyRecalculationVersion</string>
<integer value="1" key="NS.object.0"/>
</object>
これは様々なメタデータが格納されるようだが、あまり重要では無さそうだ。
IBDocument.RootObjects
ここからどうも具体的な定義に入っているようだ。冒頭でオブジェクトを取り除かない場合、ここには非常の多くの記述が集中する。今回は全て取り除いたのでとても短い。
<array class="NSMutableArray" key="IBDocument.RootObjects" id="1048">
<object class="NSCustomObject" id="1021">
<string key="NSClassName">NSApplication</string>
</object>
<object class="NSCustomObject" id="1014">
<string key="NSClassName">FirstResponder</string>
</object>
<object class="NSCustomObject" id="1050">
<string key="NSClassName">NSApplication</string>
</object>
</array>
NSApplication
が2度記述されていたりと、まだここだけではよくわからないが、この記述をごっそり削除してからXcode上で開いてみるとその正体がわかる。
Xcodeは次のようなエラーを出してきた。
The document "MainMenu.xib" could not be opened. This archive contains a reference to an object with the identifier "1048" but does not contain an object with a matching identifier.
ここで'the identifier "1048" but does not contain'と言っている点に注目。どこかに対応する記述があるということか。
IBDocument.Objects
<object class="IBObjectContainer" key="IBDocument.Objects">
<array class="NSMutableArray" key="connectionRecords"/>
<object class="IBMutableOrderedSet" key="objectRecords">
<array key="orderedObjects">
<object class="IBObjectRecord">
<int key="objectID">0</int>
<array key="object" id="0"/>
<reference key="children" ref="1048"/>
<nil key="parent"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">-2</int>
<reference key="object" ref="1021"/>
<reference key="parent" ref="0"/>
<string key="objectName">File's Owner</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">-1</int>
<reference key="object" ref="1014"/>
<reference key="parent" ref="0"/>
<string key="objectName">First Responder</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">-3</int>
<reference key="object" ref="1050"/>
<reference key="parent" ref="0"/>
<string key="objectName">Application</string>
</object>
</array>
</object>
<dictionary class="NSMutableDictionary" key="flattenedProperties">
<string key="-1.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="-2.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="-3.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="unlocalizedProperties"/>
<nil key="activeLocalization"/>
<dictionary class="NSMutableDictionary" key="localizations"/>
<nil key="sourceID"/>
<int key="maxID">535</int>
</object>
いた。 <reference key="children" ref="1048"/>
という記述がある。ここが互いに対応している。
ここでは、Interface Builder上では削除できないFile's Owner, First Responder, Applicationという見慣れた表記が見つかる。File's OwnerはNSApplication
クラス、Application自体ももちろんNSApplication
クラスなので、上で2度記述されていたのも納得できる。
flattenedProperties
以下にはInterface Builder特有であろう表記が見える。
疑問
ここでInterface Builder上でオブジェクトを追加したらxibにはどう反映していくのだろうか?
次回は、Interface Builder上の操作にxibがどう反映していくか調べていきます。
Discussion