Cocoaでいこう! Macらしく 第21回
Yoshiki(DreamField)
この記事は、MOSAが発行するデベロッパ向けのデジタルマガジンMOSADeN 第82号(2003年9月16日発行)に掲載された記事です。2〜3ヶ月遅れで、ここに掲載して行きます。

前回に引き続き、カテゴリを使用してNSImageクラスにPICTRepresentationを追加します。前回はインターフェース部まで実装しましたので、今回はインプリメント部の実装です。

カテゴリでNSImageを拡張しよう(後編)

実は今まで、インプリメント部の構造はきちんと説明していませんでした。ですが、構造自体単純ですから、プログラムを通して、だいたいの予想はついていたと思います。クラスのインプリメント部は次の様な構造になっています。

@implementation クラスの名前
メソッドの定義
@end

カテゴリの場合は、次の様に書きます。

@implementation クラスの名前 (カテゴリの名前)
メソッドの定義
@end

カテゴリの名前が増えただけですね。では、ImageProducingData.mを修正しましょう。現在は次の様になっているはずです。

@implementation ImageProducingData

@end

これを次の様に修正して下さい。

@implementation NSImage (ImageProducingData)

@end

これで枠は出来ましたので、この中にメソッドを実装します。今回は、前々回にMyDocumentに実装したPICTRepresentationを、NSImageの方に実装しようとしていますから、まずはMyDocument.mの中にある、PICTRepresentationをコピーして、この間に貼付けて下さい。貼付けたら、次の行を修正して下さい。13行目くらいにあるはずです。

if( ( theTiffData = [ image TIFFRepresentation]) == nil){

MyDocumentでは、所有しているimageからTIFFデータを取り出し、これをPICTに変換していました。今回は、自分自身からTIFFデータを取り出し、PICTに変換します。そこで、imageをselfに変更して下さい。

if( ( theTiffData = [ self TIFFRepresentation]) == nil){

レシーバーをselfにしますと、自分自身にメッセージを送ることになります。これでPICTRepresentation自体の修正は終わりました。

ところで、MyDocumentのPICTRepresentationは、関数を二つ呼び出していたことを覚えていますでしょうか。これもMyDocumentからコピーして来る必用があります。貼付ける場所は、前々回同様、@implementationの上です。そして、前々回同様、QuickTime関係のヘッダをimportする必用もありますので、#import "ImageProducingData.h"の下に書き加えておきましょう。

#import "ImageProducingData.h"
#import <QuickTime/QuickTimeComponents.h>
#import <QuickTime/ImageCompression.h>

以上で、NSImageに対する、PICTRepresentationの追加は完了です。必用なくなったMyDocumentクラスのPICTRepresentationと、そこから呼び出される二つの関数、gworld2pict()とcreateTIFFHandleDataReference()、そしてQuickTimeに関するヘッダを、MyDocument.mから削除してください(関数の削除を怠ると、関数名が重なり、リンクエラーになります)。

後はMyDocumentの中でPICT変換を呼び出していた部分を修正するだけです。dataRepresentationOfType:の中から、次の行を見つけて下さい。

theData = [ self PICTRepresentation];

ここでは自分に対してPICTRepresentationメッセージを投げていましたが、これを自分が所有しているimageに投げるように修正します。

theData = [ image PICTRepresentation];

以上でビルドして実行することはできますが、ビルド時に次のwarningが出てしまいます。

warning: 'NSImage' does not respond to 'PICTRepresentation'

これは元々のNSImage.hには、PICTRepresentationの宣言が無いからです。そこで、ImageProducingData.hをインポートしておきましょう。

#import "MyDocument.h"
#import "ImageProducingData.h"

ただし、これを行わなくても実行はできます。通常の言語でしたら、メソッドの宣言が無ければリンクエラーですが、Objective-Cは動的解決ですので、ビルド時には分からなくても、実行した結果、メソッドが見つかればエラーにならないのです。

さて、どうでしょうか。ビルドはうまくいきましたでしょうか。そして今までと同様、PICTで保存が出来ますでしょうか。今回は、結構複雑な操作を行いましたので、ミスしやすいと思います。どうしたら良いのか分からなくなる場合もあると思いますが、なるべくなら、エラーメッセージを読み、ご自分でソースを眺めて、解決するように努力してみて下さい。その方が理解が深まると思います。それでも、どうにもならなくなった時には、プロジェクトファイルを用意しておきましたので、こちらをダウンロードして中を見比べて下さい。下記URLの中の、「第21回終了後のプロジェクト」がそれです。

http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/downloads/

うまくいきましたら、もう一度ソースを眺めてみましょう。PICT変換はNSImageの方に組み込みましたから、今後はimageに対してメッセージを投げるだけでPICTデータが得られます。これで保存に限らず、色々な場面で使えるようになりました。MyDocumentも、PICT変換を抱え込まなくなった分、構造がシンプルになったと思います。こうなると、JPEG変換もNSImageに組み込んでしまいたくなりますね。余裕がある方は、やってみて下さい。

では、次回は複数フォーマットによる保存の総仕上げとして、今まで積み残した部分の修正や実装を行います。

前頁目次次頁