Spotlight インポータの作成
Spotlight インポータは、独自の書類フォーマットをサポートしているすべてのアプリケーションが提供するべきものです。Spotlight インポータは、対象となる情報を探すために書類フォーマットを解析して、その情報を適切なメタデータキーに割り当てます。
独自書類からメタデータを抽出するサンプルのメタデータインポータが、「/Developer/Examples/Metadata/ImporterExample」 にあります。このサンプルを、この記事全体を通して引用していきます。
このセクションの内容:
メタデータインポータプロジェクトの作成
インポート関数への一意の ID の割り当て
インポータと書類タイプの関連付け
メタデータの属性の指定
メタデータの抽出
メタデータインポータプロジェクトの作成
Xcode は、Metadata Importer という、インポータによってよく使用される共通の機能を提供するプロジェクトテンプレートを提供しています。
このテンプレートは、必要なフレームワーク、「Info.plist」のテンプレート、スキーマファイルのテンプレート、ローカライズ可能な「schema.strings」ファイルのテンプレート、必要な CFPlugin の実装が含まれている「main.c」のテンプレート、そして必要なコールバック関数のスケルトン実装である「GetMetadataForFile.c」を含んだプロジェクトを作成します。ターゲットは、mdimporter 拡張子の付いた CFPlugin バンドルを作成します。
抽出コードの記述のほかに、テンプレートに変更を加えて、インポータが扱う書類タイプを指定し、インポータが提供するキーの一覧をリストする必要があります。
インポート関数への一意の ID の割り当て
メタデータをインポートできる各プラグインファクトリに、一意の識別番号を関連付ける必要があります。1 つの関数で多くの書類タイプを扱うことができるため、通常は、メタデータインポータごとにプラグインファクトリが 1 つだけあります。
新規メタデータインポータプロジェクトを作成すると、Xcode によってインポータ用の UUID が作成されます。以下は、サンプルのメタデータインポータ用に生成された UUID を示します。
8AED83B3-C412-11D8-85A3-000393D59866
| |
|
この値は、インポータの「Info.plist」と「main.c」ファイルの中で使用しています。リスト 1 に、Xcode によって生成された「Info.plist」テンプレートを示します。
リスト 1: メタデータインポータの「Info.plist」テンプレート
<?xml version="1.0" encoding="UTF-8"?>
| | <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
| | <plist version="1.0">
| | <dict>
| | <key>CFBundleDevelopmentRegion</key>
| | <string>English</string>
| | <key>CFBundleDocumentTypes</key>
| | <array>
| | <dict>
| | <key>CFBundleTypeRole</key>
| | <string>MDImporter</string>
| | <key>LSItemContentTypes</key>
| | <array>
| | <string>SUPPORTED_UTI_TYPE</string>
| | </array>
| | </dict>
| | </array>
| | <key>CFBundleExecutable</key>
| | <string>MyCustomImporter</string>
| | <key>CFBundleIconFile</key>
| | <string></string>
| | <key>CFBundleIdentifier</key>
| | <string>com.apple.yourcfbundle</string>
| | <key>CFBundleInfoDictionaryVersion</key>
| | <string>6.0</string>
| | <key>CFBundlePackageType</key>
| | <string>BNDL</string>
| | <key>CFBundleSignature</key>
| | <string>????</string>
| | <key>CFBundleVersion</key>
| | <string>1.0</string>
| | <key>CFPlugInDynamicRegisterFunction</key>
| | <string></string>
| | <key>CFPlugInDynamicRegistration</key>
| | <string>NO</string>
| | <key>CFPlugInFactories</key>
| | <dict>
| | <key>8AED83B3-C412-11D8-85A3-000393D59866</key>
| | <string>MetadataImporterPluginFactory</string>
| | </dict>
| | <key>CFPlugInTypes</key>
| | <dict>
| | <key>8B08C4BF-415B-11D8-B3F9-0003936726FC</key>
| | <array>
| | <string>8AED83B3-C412-11D8-85A3-000393D59866</string>
| | </array>
| | </dict>
| | <key>CFPlugInUnloadFunction</key>
| | <string></string>
| | </dict>
| | </plist>
| |
|
CFPlugInFactories エントリは、メタデータインポータのホスト ID と、インポータに必要なプラグインファクトリ関数の UUID を関連付けるディクショナリです。CFPluginInTypes ディクショナリには、ファクトリ関数の UUID を関数に関連付けるキーが含まれています。どちらにも新しく生成された UUID が Xcode によって挿入されました。
以下は、Xcode によって作成された、「main.c」内の該当する行の抜粋です。
リスト 2:「main.c」でのインポータ ID の設定
#define PLUGIN_ID "8AED83B3-C412-11D8-85A3-000393D59866"
| |
|
インポータと書類タイプの関連付け
インポータは、それがインポートできる書類タイプと関連付ける必要があります。これを行うには、サポートする書類の UTI(Uniform Type Identifiers)を指定します。
サポートする UTI は、インポータの「Info.plist」の LSItemContentTypes 配列に指定します。リスト 1 のテンプレートには、プレースホルダとして SUPPORTED_UTI_TYPE が含まれており、これをインポータが扱う UTI で置き換える必要があります。複数の書類タイプをサポートする場合は、追加の文字列エントリを「Info.plist」の LSItemContentTypes 配列に追加します。サンプルのインポータでは、SUPPORTED_UTI_Type は、com.apple.mycocoadocumentapp.mycustomdocument となります。
メタデータの属性の指定
プロジェクトの「schema.xml」ファイルに変更を加えることによって、メタデータインポータから返すメタデータの属性を指定する必要があります。schema.xml ファイルは、返す属性の詳細を指定する XML スキーマ書類であり、独自メタデータキーもこのファイルで指定できます。
リスト 3 は、Xcode によって生成される「schema.xml」テンプレートを示します。
リスト 3: メタデータインポータの「schema.xml」テンプレート
<?xml version="1.0" encoding="UTF-8"?>
| |
| | <schema version="1.0" xmlns="http://www.apple.com/metadata"
| | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
| | xsi:schemaLocation="http://www.apple.com/metadata
| | file:///System/Library/Frameworks/CoreServices.framework/Frameworks/Metadata.framework/Resources/MetadataSchema.xsd">
| | <note>
| | このメタデータインポータがサポートする独自属性。以下は、
| | 以下は、多値型の文字列属性の例です。その他の型としては、
| | CFNumber、CFDate、CFBoolean、CFData があります。
| | </note>
| | <attributes>
| | <attribute name="com_Foo_YourAttrName" multivalued="true" type="CFString"/>
| | </attributes>
| |
| | <types>
| | <type name="SUPPORTED_UTI_TYPE">
| | <note>
| | このメタデータインポータが扱うキー。
| | </note>
| | <allattrs>
| | com_Foo_YourAttrName
| | </allattrs>
| | <displayattrs>
| | com_Foo_YourAttrName
| | </displayattrs>
| | </type>
| | </types>
| | </schema>
| |
|
このテンプレートを自分のメタデータインポータに合うように編集する必要があります。
SUPPORTED_UTI_TYPE プレースホルダを、書類を表す適切な UTI タイプで置き換えます。
attributes 要素を編集し、必要に応じて attribute 要素を編集または削除します。
メタデータキーには、キー値コーディングとの互換性確保のために、ドメイン名逆指定方式を使い、“.” を “_” に置き換えたプレフィックスを付けます。これらの独自メタデータ値のそれぞれは、attribute 要素の type 属性によって指定される、単一の CFString を返します。
メタデータインポータから返せるのは、次の CF タイプだけです:CFString、CFNumber、CFBoolean、CFDate。あるキーが値の配列を返す場合には、type 属性に CF タイプを指定し、attribute 要素に値を true に設定した multivalued 属性を含める必要があります。
インポータが独自のメタデータキーを必要としない場合は、attributes 要素を完全に削除することができます。
allattrs 要素を編集して、すべてのメタデータキーを含めます。
displayattrs 要素を編集して、プレビュー用に推奨するメタデータキーのサブセットを含めます。
「schema.strings」ファイルを編集して、独自メタデータキーの表示名と説明の文字列を指定します。
リスト 4 は、サンプルのメタデータインポータプロジェクトに含まれている「schema.xml」ファイルを示します。
リスト 4: サンプルのメタデータインポータの「schema.xml」ファイル
<?xml version="1.0" encoding="UTF-8"?>
| |
| | <schema version="1.0" xmlns="http://www.apple.com/metadata"
| | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
| | xsi:schemaLocation="http://www.apple.com/metadata
| | file:///System/Library/Frameworks/CoreServices.framework/Frameworks/Metadata.framework/Resources/MetadataSchema.xsd">
| | <note>
| | このメタデータインポータがサポートする独自属性。以下は、
| | 以下は、多値型の文字列属性の例です。その他の型としては、
| | CFNumber、CFDate、CFBoolean、CFData があります。
| | </note>
| | <attributes>
| | <attribute name="com_apple_myCocoaDocumentApp_myCustomDocument_notes" multivalued="false" type="CFString"/>
| | </attributes>
| |
| | <types>
| | <type name="com.apple.mycocoadocumentapp.mycustomdocument">
| | <note>
| | このメタデータインポータが扱うキー。
| | </note>
| | <allattrs>
| | com_apple_myCocoaDocumentApp_myCustomDocument_notes
| | </allattrs>
| | <displayattrs>
| | com_apple_myCocoaDocumentApp_myCustomDocument_notes
| | </displayattrs>
| | </type>
| | </types>
| | </schema>
| |
|
サンプルのメタデータインポータでは、com_apple_myCocoaDocumentApp_myCustomDocument_notes という新しい属性キーを 1 つ宣言しています。キー名には、キー値コーディングとの互換性確保のために、ドメイン名逆指定方式を使い、“.” を “_” に置き換えたプレフィックスを付けています。これらの独自メタデータ値のそれぞれは、attribute 要素の type 属性によって指定される、単一の CFString を返します。
リスト 5 は、サンプルのメタデータインポータの「schema.strings」ファイルを示します。
リスト 5: サンプルのインポータの「schema.strings」ファイル
"com_apple_myCocoaDocumentApp_myCustomDocument_notes" = "Notes";
| | "com_apple_myCocoaDocumentApp_myCustomDocument_notes.Description" = "What it is you're supposed to remember.";
| |
|
コマンドラインツール mdcheckschema を使用して、スキーマに対して簡単な有効性検査を実行できます。インポータのスキーマが有効かどうかをテストするのに役立ちます。
メタデータの抽出
ファイルからメタデータを抽出するときには、GetMetadataForFile 関数が呼び出されます。この関数には、プラグインインタフェース、メタデータの属性キーと値を追加する対象となる更新可能なディクショナリ、ターゲットファイルの UTI タイプ、ターゲットファイルの完全パスが渡されます。
リスト 6 は、Xcode によって提供される GetMetadataForFile のスケルトン実装を示します。
リスト 6: GetMetadataForFile のテンプレート実装
Boolean GetMetadataForFile(void* thisInterface,
| | CFMutableDictionaryRef attributes,
| | CFStringRef contentTypeUTI,
| | CFStringRef pathToFile)
| | {
| | /* 指定のパスにあるファイルから抽出可能なすべてのメタデータを抽出 */
| | /* 属性キーと属性値をディクショナリに返す */
| | /* 成功した場合は true、データが提供されなかった場合は false を返す */
| |
| | #警告 インポータを完成するには、「GetMetadataForFile.c」内の GetMetadataForFile 関数を実装してください
| | return false;
| | }
| |
|
この関数の実装では、ファイルからメタデータを抽出し、適切なキーと値としてディクショナリに追加します。メタデータが正常に返された場合、この関数から値 true を返します。メタデータが抽出されなかった場合は、false を返します。
サンプルの独自書類フォーマットは、著者、作品名、備考を含んだプロパティリストです。リスト 7 は、サンプルのメタデータインポータの GetMetadataForFile の実装を示します。
リスト 7: サンプルのメタデータインポータの GetMetadataForFile の実装
Boolean GetMetadataForFile(void* thisInterface,
| | CFMutableDictionaryRef attributes,
| | CFStringRef contentTypeUTI,
| | CFStringRef pathToFile)
| | {
| | /* 指定のパスにあるファイルから抽出可能なすべてのメタデータを抽出 */
| | /* 属性キーと属性値をディクショナリに返す */
| | /* 成功した場合は true、データが提供されなかった場合は false を返す */
| | Boolean success=NO;
| | NSDictionary *tempDict;
| | NSAutoreleasePool *pool;
| |
| | // この関数の呼び出しの周りに自動解放プールがあると想定しないこと。
| | pool = [[NSAutoreleasePool alloc] init];
| | // 書類を指定の場所にロードする
| | tempDict=[[NSDictionary alloc] initWithContentsOfFile:(NSString *)pathToFile];
| | if (tempDict)
| | {
| | // kMDItemTitle 属性にタイトルの値を設定する
| | [(NSMutableDictionary *)attributes setObject:[tempDict objectForKey:@"title"]
| | forKey:(NSString *)kMDItemTitle];
| |
| | // kMDItemAuthors 属性に、単独の著者の値を含んだ配列を設定
| | // する
| | [(NSMutableDictionary *)attributes setObject:[NSArray arrayWithObject:[tempDict objectForKey:@"author"]]
| | forKey:(NSString *)kMDItemAuthors];
| |
| | // 独自書類の notes 属性に、備考の値を設定する
| | // (実際には、kMDItemTextContent 属性を使う可能性が高いですが、
| | // それでは独自キーを使った例を示すのが難しくなります!)
| | [(NSMutableDictionary *)attributes setObject:[tempDict objectForKey:@"notes"]
| | forKey:@"com_apple_myCocoaDocumentApp_myCustomDocument_notes"];
| |
| | // YES を返すとことで、属性がインポートされるようにする
| | success=YES;
| |
| | // ロードした書類を解放する
| | [tempDict release];
| | }
| | [pool release];
| | return success;
| | }
| |
|