スキップしてメイン コンテンツに移動

Cocoa/Objective-Cの手習い

Objective-Cをちゃんと勉強して来なかったので、ここらでちゃんと勉強しようかと思いたった。まずは手習いとして、結城浩氏の『Java言語で学ぶデザインパターン入門』の各パターンでも移植してみよう。コード自体の意味や内容についてはそちらを参照してほしい。

第一回はIteratorパターン。 Objective-CではFoundationにIteratorを実装したNSEnumeratorが提供されているが、敢て実装してみる。

Objective-C自身は、オブジェクト指向の部分はC++などと違ってSmalltalkに近く、純粋に「らしい」コードを追求すればもっとよいコードがあるだろう。まず、JavaでいうInterfaceのようなものはないし、動的な指向が強く全てのオブジェクトがNSObjectというクラスに辿れるので本当はもう少し柔軟なコードが簡単に書けそうな気がする。が、ここは手習いなのでJavaのコードに準じたコードにしてみた。

まず、Javaのインターフェイスとして定義されているIteratorAggregateはObjective-Cでは少し異端とも思える静的な型付けを意識したProtocolを用いて以下のようなコードとする。

Iterator.h

    @protocol Iterator
    -(BOOL)hasNext;
    -(id)next;
    @end

Aggregate.h

    @protocol Aggregate
    -(id <Iterator>)iterator;
    @end

これら抽象クラスの実体としてBookShelfIteratorBookShelfを用意する。それぞれの宣言は以下の通り

BookShelfIterator.h

    @interface BookShelfIterator : NSObject <Iterator> {
        BookShelf* bookShelf;
            int index;
    }
    -(id)initWithBookShelf:(BookShelf*)shelf;
    @end

Aggregateの中での集合の扱いはNSMutableArrayを使用する。

BookShelf.h

@interface BookShelf : NSObject <Aggregate>
{
    NSMutableArray* books;
    int last;
}

-(Book*) getBookAtIndex:(int) index;
-(void) appendBook:(Book*)book;
-(int)getLength;
-(id <Iterator>) iterator;
@end

で、BookShelfIteratorIteratorとしてインターフェイス部分の実装は以下のような感じ

-(BOOL)hasNext
{
    if(index < [bookShelf getLength]) {
        return TRUE;
    } else {
        return FALSE;
    }
}

-(id)next
{
    Book* book = [bookShelf getBookAtIndex:index];
    index++;
    return book;
}
@end

Javaの例に即したテストコードは以下のようになる。 Book* book;

    book =  [[[Book alloc] initWithString:@"Around the World in 80 Days"] autorelease];
    [bookShelf appendBook: book];
    book =  [[[Book alloc] initWithString:@"Bible"] autorelease];
    [bookShelf appendBook: book];
    book =  [[[Book alloc] initWithString:@"Cinderella"] autorelease];
    [bookShelf appendBook: book];
    book =  [[[Book alloc] initWithString:@"Daddy-Long-Legs"] autorelease];
    [bookShelf appendBook: book];

   id <Iterator> it  = [bookShelf iterator];
   while([it hasNext]) {
        Book* book = [it next];
        NSLog(@"%@",[book getName]);
   }

   [bookShelf release];

恐らくProtocolを使う必要性は低いのだろうが……

デザインパターンの部分は余り考えることもなく終ったが、Javaのプログラマーが嵌りそうなところは、メモリー管理関連。いまではガベージコレクションもサポートされているが、デフォルトではプロジェクトの設定でオフになっている。自身でやるときは、自身でのretain/releaseautoreleaseを上手く意識して使うことが必要。

また、Cocoa/Foundationのクラスでは、[[Hogehoge alloc] init]で初期化すると普通にretain/releaseが必要だが、[Hogehoge hogehoge][Hogehoge hogehogeWithString]などのネーミングの初期化はautoreleaseが掛っている。なので、これらのオブジェクトはそのように扱わなければならない。また、GUIでなくコマンドラインのプログラムの場合、NSAutoreleasePoolが用意されない。Cocoa/Foundationのライブラリでは先の例のようにNSAutoreleasePoolを前提にしているものがあるので、自身で以下のように用意しなけばならない。

   NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

     // プログラムの処理

  [pool drain];

最初これに気付かずに悩んでしまった。
もっとも、XCodeで新規プロジェクトを作成する際、「Command Line Utlity」 のなかから「Foundation Tool」を選んで作成すれば、このあたりのコードは 埋まったテンプレートを用意してくれるのだが。

次はAdapterかな。

増補改訂版Java言語で学ぶデザインパターン入門
結城 浩
ソフトバンククリエイティブ
売り上げランキング: 5728

コメント

このブログの人気の投稿

Google Calaboration

GoogleがCalDAVプロトコルを完全サポートさいた Calaboration を発表した。 まだ、Google Codeの扱いだが一部では大変な騒ぎになっている。 Calaboration を使用すると、設定をするだけでGoogle Calendarのスケジュー ルをiCalにエクスポートでき、そして双方向に同期させることができるという Macユーザーにとっては大変便利な機能を提供してくれるユーティリティ。 騒ぎになっているのは、 Spanning Sync のユーザーフォーラム。 なにせこのソフトはGoogle CalendarとiCalを同期させるというもの。全くバッ ティングしている。多くのユーザーが「Spanning Syncと何が違うんだ? どっ ちがいいんだ? Spanning Synはどうなるだ?」という質問の書き込みを始め た。 Spanning Sync Blogでは、「 How Does Google CalDAV Compare to Spanning Sync? 」という記事が掲載されたが、そこで主張されている違いは以下のような点。 大きな違いはコスト。 Googleは無料だが、Spannning Syncは年間利用料が必要であること。でも、わ たしは永久ライセンスを購入してしまったので関係ない。 iPhoneサポート。 GoogleのCalDAVを使った同期では、iPhone上で予定がread onlyとなって編集 できないとのこと(わたしは設定していないので未確認)。Spanning Syncで はGoogle Calender、iCal、iPhone上すべてで予定を編集できる。 カスタマーサポート。 たしかにGoogleが何かやってくれそうな気はしない。Spanning Syncはお金払っ ているしね。 コンタクトリストの同期。 Googleが提供していない機能として、Spanning SyncはMacのアドレス帳と Gmailのコンタクトを同期してくれる。アドレス帳の画像まで含めて同期して くれるのは驚きだ。もっとも日本語の場合は姓と名が逆転してしまうが、これ は姓名を分けて持っているアドレス帳と姓名を1フィールドで持っている Googleの違いから仕方がないだろう。Googleではないが

Scrivener 日本語チュートリアル

(2022-01-11) 以前からコメントをいただいていましたが、反応できていなく申し訳ありません。 問い合わせが多いので、以下のブログに転載してチュートリアルもダウンロードできるようにしました。 転載先 先日から[試していたScrivenerだが、すっかり気に入り勢い余ってチュートリアルの日本語訳版を作ってしまった。 作者にコンタクトしたところ、「どうぞ、公開しておくれ!」と快く承諾をもらえたので公開しておく。 チュートリアル自体はわたしが慣れないBritish Englishで書かれているため、微妙なニュアンスは違っている箇所があるかもしれあない。また、チュートリアル自体に関係ない言い回しなどは、端折ったり日本語に合うようにゆがめたりしている。誤りがあれば指摘ください。 Scrivener-Tutorial-Japanese.dmg(リンクを切りました。転載先をごらんください。) ちなみに作者のKeithは豪気にもライセンス進呈を申し出てくれたが、入れ違いで購入してしまっていたわたし…… (2010-09-20) 「 design non design 」で紹介いただきました。

EagleFiler is the best organizer software on MacOS X

しばらく放置気味だった Journler をまじめに使おうかと検討していましたが、どうも昨年の7月くらいから開発が止まっている節が感じられます。たくさん文書はリソースを保管した挙げ句に、製品として終わってしまうとかなり悲惨な痛手を被りそうな予感がします。 そこで、以前のバージョンを購入した MacJournal がアップグレード可能なので検討しました。が、 Journler のようにDocumentフォルダでなくデータを~/Library/Application Support/MacJournalに置くのが問題です。これではSpotlightに引っかからないし、バックアップも面倒です。このため、 MacJournal は選択肢から落としました。 いろいろと考えて行くと、 Journler には大きく2つの役割を期待していたようです。 日誌 日々ネットで入手した情報のアーカイブ 前者については別にブログもあるので、問題を棚上げにしました。その上で、後者をサポートできるアプリケーションを探すことにしました。 以前からこの分野では Yojimbo が有名です。 少し触ってみましたが、どうもインターフェイスがしっくり来ません。ソフトのネーミング("Yojimbo"="用心棒")もどうもフィーリングが…… 次に検討したのは、 Together 。 以前はKIT("Keep It Together"の意)と称していたようです。アップデートも頻 繁で勢いを感じます。インターフェイスも一般受けしそうで優れたものだと思 いますが、どうもこちらもネーミングでルー大柴を思い浮かべてしまって…… 結局、C-Commandの EagleFiler というソフトに落ち着きました。 EagleFiler は、F1キーでとにかくブラウザに表示されているものを取り込んでしまえます。標準ではWebArchive形式ですが、スタイルシートなどが外部に依存したままとなるのでわたしはPDF形式で取り込むようにしています。標準でRTF、Plain Text, HTML,PDFなどがサポートされています。また、他の同様のソフトにない機能としてメールがeml形式でそのまま取り込めのは非常に便利な点です。