|
|
Log In | Not a Member? |
Contact ADC |
Core Data は、文字列、日付、および数値など、一連の一般的なタイプの属性値をサポートしています。しかし、カラーオブジェクトや C 構造体など、直接サポートされていないタイプの属性値が必要になる場合もあります。本書では、管理対象オブジェクトでこのような「非標準」の値タイプの属性を使用する方法について説明します。
はじめに
永続属性
オブジェクト属性
非オブジェクト属性
重要:本文書は、暫定的な文書です。技術面の正確性については確認されていますが、確定した文書ではありません。アップルコンピュータは、本書で説明する技術とプログラミングインターフェイスの採用計画立案の支援を目的としてこの情報を提供します。本書の改訂版を、今後提供する可能性もあります。本書および他の開発者向けの文書の最新情報については、Reference Library の今後のリリースの「New & Updated」サイドバーを参照してください。
Core Data は、文字列、日付、および数値など、一連の一般的なタイプの属性値をサポートしています(詳細については、NSAttributeDescription を参照)。しかし、カラーや C 構造体など、直接サポートされていないタイプが必要になる場合もあります。たとえば、グラフィックアプリケーションでは、それぞれ NSColor および NSRect 構造体のインスタンスである color 属性および bounds 属性を持った Rectangle エンティティを定義する必要があるかもしれません。
永続プロパティは、永続ストアに適切に格納したり、そこから取り出したりできるように、Core Data フレームワークで認識されるタイプでなければなりません。管理対象オブジェクトモデルでエンティティを定義するときには、すべての永続属性に「具体的な」タイプ(未定義でない何か)を指定する必要があります(指定しない場合、すなわち永続属性のタイプを未定義と指定すると、当該モデルでコンパイル時にエラーが発生します)。
しかし、一時プロパティのタイプは未定義と指定することができます。なぜなら、Core Data はこれらのプロパティを格納したり取り出したりする必要がないからです。もっとも、Core Data は一時プロパティもオブジェクトグラフ管理(アンドゥやリドゥなど)の対象となれるように、それらのプロパティの状態を追跡します。このことを利用して、非標準属性に永続性を実装することができます。
以下のセクションでは、オブジェクトとスカラー値の実装について説明します。しかし、どちらも同じ作業から始まります。すなわち、永続属性を指定する必要があります。
未サポートのタイプを使用するには、管理対象オブジェクトモデルで 2 つの属性を定義します。1 つは、実際に必要としている属性です(その値は、たとえばカラーオブジェクトや矩形構造体などです)。この属性は一時的なものです。もう 1 つはその属性の「シャドウ」表現です。この属性は永続的なものです。一時属性のタイプは未定義(NSUndefinedAttributeType)として指定します。シャドウ属性のタイプは、サポートされている「具体的な」タイプの 1 つでなければなりません。その後、永続属性を対象に値を取り出したり格納したりする、一時属性に適したアクセサメソッドを持つカスタムの管理対象オブジェクトクラスを実装します。オブジェクトとスカラー値の基本的なアプローチは同じですが(未サポートのデータタイプを、サポートされているデータタイプの 1 つとして表現する方法を見つける必要があります)、スカラー値の場合はさらに制約があります。
作成するアクセサメソッドの要件の 1 つは、キー値コーディング(およびキー値監視)対応でなければならないということです。キー値コーディングは、限られた数の構造体(NSPoint、NSSize、NSRect、および NSRange)をサポートしています。
Core Data で直接サポートされていないスカラータイプまたは構造体、およびキー値コーディングでサポートされていない構造体を使用する場合は、管理対象オブジェクトにオブジェクト(通常は NSValue のインスタンスですが、独自にカスタムクラスを定義することもできます)として格納する必要があります。この場合は、本稿で後述するようにオブジェクト値として扱います。値を取り出すときに NSValue(またはカスタム)オブジェクトから必要な構造体を抽出するかどうか、値を設定するときに構造体を NSValue(またはカスタム)オブジェクトに変換するかどうかは、オブジェクトのユーザ次第です。
非標準属性タイプを使用する場合は、値の格納に使用するサポートされている属性タイプを選択する必要があります。どのサポートされているタイプを選択するかは、対象非標準タイプと、それをサポートされているタイプに変換するためにどのような手段があるかによります。多くの場合、未サポートオブジェクトはアーカイバを使用して簡単に NSData オブジェクトに変換することができます。たとえば、以下のコードサンプルに示すように、カラーオブジェクトをアーカイブできます。属性を NSValue またはカスタムクラスのインスタンスとして表現する場合も、同じテクニックが使用できます(もちろん、カスタムクラスで NSCoding プロトコルを採用するか、サポートされているデータタイプに変換する他の手段を提供する必要があります)。
|
KVC に準拠した構造体の場合は、まず値をラップする NSValue オブジェクトを作成し、値オブジェクトをアーカイブすることができます。たとえば、次のコードサンプルに示すように、NSRect をデータオブジェクトに変換することができます。
|
変換を行うには、どのような手段でも使用することができます。たとえば、NSRect を永続ストアで使用できる文字列オブジェクトに変換することも可能です。
|
ただし、変換プロセスが頻繁に起こる可能性があるので、できるかぎり効率的なものにするように留意してください。
通常、永続属性に対してカスタムのアクセサメソッドを実装する必要はありません。永続属性は実装の詳細なので、その値には対象エンティティ以外がアクセスするべきではありません。この値を直接変更すると、エンティティオブジェクトが矛盾した状態になる可能性があります。
未サポート属性がオブジェクトの場合、管理対象オブジェクトモデルでは、そのタイプを未定義かつ一時的なものとして指定します。エンティティを対象とするカスタムクラスを実装するときに、属性に対応するインスタンス変数を追加する必要はありません。管理対象オブジェクトの個別内部ストアを使用できます。後述する実装に関する注意のポイントは、実装では一時的な値がキャッシュされるということです。これにより値を効率的にアクセスできます。これは変更管理にも不可欠です。
一時的な値の取得と設定のどちらにも 2 つの方法があります。一時的な値は「後で」(オンデマンドで。「オンデマンド取得アクセサ」で後述)または awakeFromFetch 中に(「事前計算取得」で後述)取り出すことができます。値が大きい場合には(たとえば、ビットマップの場合は)、値を後で取り出す方が都合のよい場合があります。永続値については、一時的な値が変更されるたびに更新するか(「即時更新設定アクセサ」で後述)、オブジェクトが保存されるまで更新を保留することができます(「遅延更新設定アクセサ」で後述)。
取得アクセサでは、管理対象オブジェクトの個別内部ストアから属性値を取り出します。値が nil の場合は、キャッシュされていないと考えられるため、対応する永続値を取り出します。取り出した値が nil でなければ、値を適切なタイプに変換してキャッシュします。次の例に、カラー属性のオンデマンド取得アクセサを示します。
|
このアプローチを使用して、awakeFromFetch の中で永続値を取り出してキャッシュします。
|
取得アクセサでは、キャッシュされた値を返すだけです。
|
このテクニックは、属性に頻繁にアクセスしそうな場合に役立ちます。取得アクセサでは、条件文を避けます。
この設定アクセサでは、一時属性および永続属性の値を両方同時に設定します。未サポートタイプをサポートされているタイプに変換して、永続値として設定します。管理対象オブジェクト(管理対象オブジェクトコンテキストを含む)を監視するオブジェクトに変更を知らせるために、キー値監視の変更通知メソッドを呼び出せるようにする必要があります。次の例に、カラー属性の設定アクセサを示します。
|
このアプローチには 2 つのデメリットがあります。まず、一時的な値を更新するたびに、永続値が再計算されます。次に、永続値を更新すると、余分なアンドゥアクションが生成されます。デスクトップアプリケーションを作成していて、すべての変更を 1 つのイベントサイクルの中で行う場合、(1 つのイベント内のアンドゥアクションはすべてまとめられるので)これは重要でないかもしれません。しかし、イベントループの外で変更を行う場合は、アンドゥ操作の「二重変更」に注意する必要があります。
このテクニックでは、設定アクセサで一時属性の値のみを設定します。オブジェクトを保存する直前に永続値を更新する willSave メソッドを実装します。
|
このアプローチを採用した場合は、オプショナリティルールを指定する際に注意する必要があります。カラーが必須の属性である場合、(他の手段を講じないかぎり)カラー属性は任意でなく、カラーデータ属性を任意として指定する必要があります。さもなければ、最初の保存操作で検証エラーが発生する可能性があります。
オブジェクトが最初に作成されたとき、colorData の値は nil になります。カラー属性を更新しても、colorData 属性は影響を受けません(つまり、nil のままです)。保存するときに、willSave の前に validateForUpdate: が呼び出されます。検証段階でも、colorData の値は nil のままであるため、検証は失敗します。
未サポート属性がキー値コーディングでサポートされている構造体(NSPoint、NSSize、NSRect、または NSRange)のいずれかである場合、管理対象オブジェクトモデルの中で、もう一度そのタイプを未定義かつ一時的なものとして指定します。エンティティに対するカスタムクラスを実装する際には、通常、属性にインスタンス変数を追加します。たとえば、NSRect を使って表現したい bounds という属性があるとき、クラスインターフェイスは次の例に示すようになります。
|
あるいは、インスタンス変数に属性名以外の名前を付けたい場合は、次の例に示すように、プリミティブな取得アクセサと設定アクセサも実装する必要があります。
|
プリミティブなメソッドは、次の例に示すように、インスタンス変数を取得および設定するだけです。キー値監視の変更通知メソッドまたはアクセス通知メソッドを呼び出すものではありません。
|
どちらの方法を採用するにしても、後は、おおむねオブジェクト値について述べたようにアクセサメソッドを実装します。取得アクセサについては、遅延取得または事前計算のテクニックを採用することができます。また、設定アクセサの場合は、即時更新または遅延更新のテクニックを採用することができます。以下のセクションでは、それぞれの後者についてのみ説明します。
取得アクセサでは、管理対象オブジェクトの個別内部ストアから属性値を取り出します。値がまだ設定されていなければ、キャッシュされていないと考えられるため、対応する永続値を取り出します。取り出した値が nil でなければ、値を適切なタイプに変換してキャッシュします。次の例に、矩形の取得アクセサを示します。
|
設定アクセサでは、一時属性および永続属性の値を設定する必要があります。未サポートタイプをサポートされているタイプに変換して、永続値として設定します。管理対象オブジェクト(管理対象オブジェクトコンテキストを含む)を監視するオブジェクトに変更を知らせるために、キー値監視の変更通知メソッドを呼び出せるようにする必要があります。次の例に、矩形の設定アクセサを示します。
|
Preliminary Last updated: Tiger
|
Get information on Apple products.
Visit the Apple Store online or at retail locations. 1-800-MY-APPLE Copyright © 2007 Apple Inc. All rights reserved. | Terms of use | Privacy Notice |