MOSA Multi-OS Software Artists

MOSAはソフトウェア開発者を支援します

プログラマーに興味がある方なら誰でも入会いただけます。
MOSA Multi-OS Software Artists
===SINCE 1995===

  • iPhone/iPod touch アプリ紹介
  • MOSA掲示板
  • 活動履歴
  • About MOSA(English)

MOSADenバックナンバー 2004年4月発行分

  • MOSA Developer News[MOSADeN=モサ伝]第111号

    2004-04-27

    目次

    • Cocoaでいこう! Macらしく  第48回  Yoshiki(DreamField)
    • 藤本裕之のプログラミング夜話 #44
    • 高橋真人の「プログラミング指南」 第43回
    • ニュース・解説
    • MOSAからのお知らせ

    Cocoaでいこう! Macらしく  第48回 Yoshiki(DreamField)

    パネルを表示しよう(その10)

     前回までで、メインウィンドウが切り替わる度にパネルの表示も切り替わるようになりました。ところで、Cocoaに詳しい方は、そういう場合は、NSWindowDidBecomeMainNotificationを使うのではないか? と思ったのではないかと思います。実は、自分で通知しなくても、フレームワークは様々な通知を行っており、プログラムではこれを自由に活用できます。NSWindowクラスのリファレンスの下の方に、Notificationsという項目がありますので、見てください。NSWindowDidBecomeMainNotificationの説明もここにあります。

     大抵の入門書はこれを使っていますし、私も最初の頃はこれを使っていました。ですが、何故か大抵の入門書では、メインウィンドウが切り替わった時のことは書いてありますが、最初にパネルを開いた時や、メインウィンドウがまったく無くなった時の説明がおざなりになっていることが多いです。もちろん、フレームワークが用意している通知だけを使っても、これに対応することは出来ますが、色々とやっている内に、こっちの方が楽なのではないか? と思うようになりました。それに、情報が変化したという通知ですから、メインウィンドウが切り替わったというのとは、ちょっと意味合いが異なります。今はたまたまメインウィンドウが切り替わった時しか情報が変化していませんが、そうで無い場合でも対応できるというわけです。もちろん、これが正解というわけではありませんので(と、言うより、多分正解は無いのですが)、一般的な入門書に書いてある、(おそらくは)正当である方法も一読することをお勧めします。

     さて、今の話にも出て来ましたが、現在の実装では全ての画像を閉じて、メインウィンドウが無くなった時の事が考慮されていません。その場合は、最後に開いていた画像の値が表示されたままになってしまいます。これをクリアするようにしましょう。この処理はどこに組み込めば良いでしょうか。
     全てのドキュメントが閉じられた時に、それを知ることが出来るのは誰でしょう。一番単純に考えると、それは全てのドキュメントを生成しているオブジェクトですね。この様なオブジェクトが存在することは、第5回の「Document-based Applicationの構造」で説明しましたが、それが何であるのかは今まで説明していませんでした。

     プロジェクトを生成する時にDocument-based Applicationを選んだ場合、これはNSDocumentControllerクラスのインスタンスオブジェクトが行っています。これのリファレンスを見てみましょう。開いているドキュメントの数が0になった時に呼ばれるメソッドがあれば、パネルをクリアする処理を組み込むのは簡単だったのですが、残念ながらそういうのは無いようです。では、ドキュメントを閉じる処理に組み込むことを考えたらどうでしょうか。ドキュメントを閉じる処理は、removeDocument:というメソッドで行っています。と言うことは、これをオーバーライドし、ドキュメントを閉じた後に残りのドキュメントの数を数え、これが0になっていた時にパネルの値をクリアするようにすれば、望みの動作になるはずです。では、これを実装して行きましょう。

     NSDocumentControllerクラスを継承したMyDocumentControllerクラスを作ります。まずはMyDocumentController.hとMyDocumentController.mをTinyViewのプロジェクトに加えてください。そして、MyDocumentController.hを次の様に書き直してください。

    #import <Cocoa/Cocoa.h>
    
    @interface MyDocumentController : NSDocumentController {
    
    }
    - (void)removeDocument:(NSDocument *)document;
    @end

     続けてMyDocumentController.mを次の様に書き直して下さい。

    #import "MyDocumentController.h"
    #import "ImageInfo.h"
    
    @implementation MyDocumentController
    
    - (void)removeDocument:(NSDocument *)document {
        ImageInfo *imageInfo;
    
        [ super removeDocument:document];
        if( [ [ self documents] count] == 0){
            imageInfo = [ ImageInfo sharedImageInfo];
            [ imageInfo setImageSize:NSZeroSize];
            [ imageInfo change];
        }
    }
    
    @end
    


     順番に見て行きましょう。

    [ super removeDocument:document];

     まず、removeDocument:本来の処理を行わなければなりませんから、superクラスにremoveDocument:メッセージを投げています。

    if( [ [ self documents] count] == 0){

     その後、自分にdocumentsメッセージを投げてドキュメントを管理しているNSArrayクラスのインスタンスを教えてもらい、これに対してcountメッセージを投げてドキュメントの数を教えてもらっています。そしてこれが0の時に、以下の処理を行います。

    imageInfo = [ ImageInfo sharedImageInfo];

     imageInfoは第43回に出て来ました。皆が共有して使用する、メインウィンドウのイメージの情報をセットするオブジェクトです。

     [ imageInfo setImageSize:NSZeroSize];

     これに画像の縦横のサイズとして、0サイズをセットしています。

    [ imageInfo change];

     そしてchangeメッセージを投げて、「情報が変わったぞ」という通知を行ってもらいます。これで、ドキュメントの数が0になった時に、パネルに表示される値は0になるはずです。
     ところで、せっかくコーディングしたMyDocumentControllerクラスですが、これをインスタンス化するのはどうすれば良いのでしょうか。フレームワークはアプリの起動時に、勝手にNSDocumentControllerクラスをインスタンス化してしまっています。これをMyDocumentControllerクラスにすげ替えなければなりません。実はこれは、第25回で行ったことの応用で出来ます。その説明は、次回行います。

    藤本裕之のプログラミング夜話 #44

     今の指導要領ではもしかすると男女差別だとか言ってなくなってしまったかも知れぬが,ワタシが中学生の頃には「技術・家庭」という授業があって,男子は製図や木工,ハンダ付けなどをやり,同じ時間に女子が裁縫とか料理とかを勉強していた。ワタシの行ってた中学にはこの科目,しかも男子向けだけに結構でかい建物がひとつあって(昨年11月に帰省してみたら跡形もなくなってたが),そこに何台か旋盤がおいてあった。中学何年生の時だったかは憶えてないが、われわれは授業で旋盤の使い方を教わり、確かタオルハンガーみたいなものを各自一つずつ作ったはずだ。

    あ、もしかすると知らないヒトもいるかも知れないので説明すると、旋盤というのは金属を削る機械である。基本的には削りたい金属を回転する軸に固定し、横から刃物(バイトと言う)をあててシュルシュルシュルと削る。構造としては100円くらいの鉛筆削りと同じだ(高い鉛筆削りは鉛筆の方を固定している)。金属の削りかすがクルクルクルと丸まって光る。なんつうか、これまた叱られるかもしれないが「男の機械」という感じの機械なんである。

    それで思い出したが、「巨人の星」と同じ梶原一騎・川崎のぼるコンビで「男の条件」というマンガがあって、これの主人公が名前は忘れたけど旋盤工だった。自分たちと同じ旋盤工が主人公の根性マンガがあって愛読しているんだが、それに描かれた旋盤の形がウソッパチであることを悲しみ、マンガ家のところに「本物の旋盤を見に来てくれ」と頼みに行く。その旋盤を描いたのは自分と同年代のスカしたアシスタントで「そんな機械、それらしく見えればいいんだ」とぬかす。怒った主人公は「本物を描いてやる」と旋盤工を辞めてマンガ家を志す……って書いてみるとちととんでもない話だが、このマンガの影響もあって、少年フジモトは旋盤の授業が好きであったのです。

    その旋盤工を50年務めた小関智弘というヒトが書いた「職人学」という本があって、「イメージできないから見積もりをふっかける」という話がでて来る。「図面を見て、どんな段取りをするか、どんな治具(製品を作る過程で使われる製品以外の製作物、プログラマが作るツールに近いか)を作って加工すべきか、それにはどれくらいの時間が必要かを適確にイメ−ジできる工場でないと」いけないのだ、という。

    この話、ソフトウェアも全く同じだと思うのだ。クライアントの要求する仕様を聞き、それを実現するためのおおまかな方法を頭の中で組み立てる。まずは可能か可能でないかを判断し、可能であれば自分のスキルやスケジュール、その他諸々を勘案してどのくらいの期間が必要かを考え、最後にそれに対して要求したい報酬の額を計算する。そうでないといけない、というか、そうであるのが当たり前だと思いませんか。
     ところが現実は全然そうぢゃない。プログラミング仕事は基本的に一品料理なのに、マクドナルドみたいな見積もりしかできないSEばっかりだ。あ、データベースですか、データベースの構築でしたらウチでは予想される総件数に応じていくらいくらとお勉強させていただいております。はい、メンテナンスはまた別契約で。あ、インターネットとの連動も必要? でしたら、こちらWEBアンドDBのセットがお得になっております、はい。ええ、それはもう当社には優秀なエンジニアが揃っておりますから。いえいえ情報の流出など絶対にございません。では、WEBアンドDBのセットで最大件数10,000件までのコースですね。定期メンテナンスは月単位、はい。……それで、お飲物はよろしいでしょうか?

     絶対こんなヤツにプログラムを頼んぢゃいけません。
    (2004_04_024)

    高橋真人の「プログラミング指南」第43回

    オブジェクト指向のとっかかり(29)

     こんにちは、高橋真人です。早速、前回新しく書き直したプログラムの解説を始めましょう。
     まずは、今回のプログラムの全体的なコンセプトを説明します。もともとこのプログラムは「改行コードの変換プログラム」ということで作っています。
     改良前のバージョンでは「入力ファイルの改行はMac(CR)でなければならない」ことや「書き出し時の改行コードは、コンパイル時に指定したものに固定」ということで、実用的だとはどうあがいても言い難いものでした(笑)。
     今回の書き直しによって、改行コードに関しては読み込み時も書き出し時も柔軟に対応できるようになりました。(ただし、文字コードに関してはシフトJISに限定)
     まずユーザーにファイル名を指定させることによって入力ファイルを決定します。あとは、プログラム自体がファイルのデータを解析することによって、改行コードを識別するようになっています。ファイルの内容は、TextContentクラスのサブクラスのうちのいずれかの中に格納されるのですが、これらのクラスの違いは「改行コードが何であるのか」だけです。
     前回のプログラムでは書き出す、つまり変換後の改行コードの種類によって生成するサブクラスのインスタンスを切り替えていましたが、今回は読み込み時にも別のインスタンスを生成しています。
     処理の流れを箇条書きにすると、以下のようになります。

    1. ファイルの中身を先読みし、改行コードを判別
    2. 判明した改行コードに従って、インスタンスを生成
    3. インスタンスがファイル内容を読み取る
    4. ユーザーから変換後の改行コードを得る
    5. 変換後の改行コードに従って、新たなインスタンスを生成。この時コンストラクタに変換元のデータを保持したインスタンスを渡して、データを受け渡す
    6. 書き出し処理

     つまり、2と5において別々のサブクラスから(同じサブクラスでは変換する意味がないので)新規にインスタンスが生成され、それらが改行コード以外のファイルの中身を受け渡すのです。
     前バージョンにおいては、実装ファイルがからっぽでサブクラスのためのプレースホルダ的な役割しか果たしていなかったTextContentクラスですが、今回のバージョンにおいてはずいぶん活躍しています(笑)。むしろ、サブクラスの方が単に「改行コードの保持」という役割ぐらいしか担わなくなって、ファイルからの読み込み、書き出し処理に関しては、TextContentクラスが中心となって処理を行っているのです。
     それでは、次回から細部に目を転じて解説していきます。

    ニュース・解説

     今週の解説担当:小池邦人

    Carbon ドキュメント & サンプル & SDK ナビゲーション(2004/04/23)

    【開発環境】

    Apple社からWWDC2004におけるカンファレンスのスケジュールが発表されました。開催までもうしばらく期間があるからなのでしょうか? 例年と比較して、TBA(To be announced …内容未定)と記されているセッションの数が多いような気がします。そうしたセッションが、現状では発表できないような新しい話題を提供するためにキープされているのなら大歓迎ですが、単にネタ不足からそうなっているだけであれば寂しいかぎりです(笑)。さて、実際はどうなのでしょう? 前号でも紹介しましたが、WWDC2004の参加費用の早期割引($300引き)は4月30日までです。参加を予定されている方は忘れないように登録いたしましょう。

    http://developer.apple.com/wwdc/calendar/monday_pm.html

    Absoft 社が、IBM社から発表されていた「IBM XL C/C++ Compiler for Mac OS X」の取り扱いを開始しました。USでの価格は、通常購入者の場合が $400 、政府機関の購入者で$300、教育関係者だと$200だそうです。筆者が予想していたよりも安く提供されるようです(学生に戻りたい…)。しかし、これにより「WWDC2004でXcodeへの無料バンドルが発表!」という筆者の夢は、はかなく消えてしまいました(笑)。コンパイラの仕様には、Apple社のXcodeに対応していることが明記されていますので、USでの購入者が、実際の使用感やベンチマークなどをウェブで紹介してくれると嬉しいですね。早期に日本での販売元が決まることを期待したいと思います。

    http://www.absoft.com/Products/Compilers/C_C%2B%2B/XLC/XLC.html

    【テクニカルドキュメント】

    前回から4月23日の期間中、Apple社のDeveloperサイトにはドキュメントが5つ登録されました。すべて4月に発表された新製品に関するハードウェア仕様書です。今回でアルミ筐体のPowerBook G4は3代目です。前回の機種と比較すると、AirMacなどのオプションもディフォルトとなり、随分と価格が抑えられていることが分かります。チタン筐体のPowerBook G4も3代目は「名品」でしたので(と筆者は思う)、ポータブルマシンの買い換え時期の方は、今回が狙い目かもしれません。PowerBook G5の方は、今のところ発表される雰囲気がないようですしね(油断大敵)。

    「eMac Developer Note」(PDFあり)
    「12-inch PowerBook G4 Developer Note」(PDFあり)
    「15-inch PowerBook G4 Developer Note」(PDFあり)
    「17-inch PowerBook G4 Developer Note」(PDFあり)
    「iBook Developer Note」(PDFあり)

    http://developer.apple.com/documentation/index-rev-date.html

    また、デベロッパ向けの読み物としてFinal Cut Proについての解説が登録されています。

    「Final Cut Pro 4 Opens up with XML Interchange Format」(読み物)

    http://developer.apple.com/appleapplications/fcpxml.html

    前回から4月23日の期間中、新規のテクニカルノートとテクニカルQ&Aはひとつも登録されませんでした。

    http://developer.apple.com/technicalnotes/index-rev-date.html

    http://developer.apple.com/technicalqas/index-rev-date.html

    【サンプルソースコード】

    前回から4月23日の期間中、Apple社のSample Codeサイトにはサンプルソースコードが3つ登録されました。DiscRecording関連が2つ含まれていますが、今回は、3つとも新作のサンプルソースコードとなっています。

    「CFHostSample」(Networking)
    「DRDataBurnCarbonUI」(DiscRecording)
    「DREraseCarbonUI」(DiscRecording)

    http://developer.apple.com/samplecode/index-rev-date.html

    【デベロップメント SDK】

    前回から4月23日の期間中、Apple社のSDKサイトにはひとつもSDKが登録されませんでした。

    http://developer.apple.com/sdk/

    MOSAからのお知らせと編集後記は割愛します

    MOSA Developer News   略称[MOSADeN=モサ伝]
    Apple、Mac OSは米国アップルコンピュータ社の登録商標です。またそのほかの各製品名等はそれぞれ各社の商標ならびに登録商標です。
    このメールの再配信、および掲載された記事の無断転載を禁じます。
    http://www.mosa.gr.jp/
    Copyright (C)2004-2006 MOSA. All rights reserved.

  • MOSA Developer News[MOSADeN=モサ伝]第110号

    2004-04-21

    目次

    • Cocoaでいこう! Macらしく  第47回  Yoshiki(DreamField)
    • 小池邦人の「Carbon API 徒然草」
    • 「Behind the WebObjects」  第18回  田畑 英和
    • ニュース・解説
    • MOSAからのお知らせ

    Cocoaでいこう! Macらしく  第47回 Yoshiki(DreamField)

    パネルを表示しよう(その9)

     前回は、ImageInfoにchangeメソッドを実装しました。これで、ImageInfoにchangeメッセージを投げることにより、ImageInfo自身が「ImageInfoが変わったぞ」という通知を行ってくれます。それでは、MyDocument.mの中で、ImageInfoを変更した後に、changeメッセージを投げる処理を加えましょう。

    - (void)windowDidBecomeMain:(NSNotification *)aNotification {
        ImageInfo *imageInfo;
    
        imageInfo = [ ImageInfo sharedImageInfo];
        [ imageInfo setImageSize:[ image size]];
        [ imageInfo change];
    }
    


     付け加えたのは、下から2行目です。ところで、何でimageInfoにsizeをセットした時に、自動的に通知を行うようにしなかったのでしょうか。その方がオブジェクト指向として正しい気がします。確かに、今回の場合は、sizeしかセットしていませんから、その時点で通知してしまってかまいません。ですが将来、size以外にも色々とセットするようになった時に、それぞれの値をセットするたびに通知されたら、プログラムの効率が悪くなってしまいます。そこで、今回はこういう実装としました。なお、この方法が正解というわけではありません。これ以外に、例えば、通常は値をセットした時点で通知が行われるが、これを連続で行っている間抑止できる機能を付けるという方法も考えられます。その他にも色々な方法があるでしょう。この辺り、どう実装するかは、個人の趣味の範疇になりますので、色々とやり方を考えてみて下さい。こういったロジックを考えるのも、プログラムの楽しみの一つです。

     さて、これでメインウィンドウが切り替わった時にImageInfoが更新され、通知も行われるようになりましたので、後はこの通知をパネルが受け取り、そのタイミングで更新された内容を表示するだけです。まずは、デフォルトのNSNotificationCenterに、「ImageInfoが変わったぞ」という通知を受け取りたいということを伝えましょう。InfoPanelController.mのwindowDidLoadに、その処理を書き加えて下さい。

    - (void)windowDidLoad {
        [ self updateImageInfo];
        [ [ NSNotificationCenter defaultCenter] addObserver:self 
    selector:@selector( updateImageInfoHandle:) name:TNVWImageInfoChangedNotification
     object:nil];
    }
    

     下から2行目が付け加えた行です。まず、デフォルトのNSNotificationCenterを取得するのは通知の時といっしょですね。これに対して、addObserver:selector:name:object:メッセージを投げています。このメッセージを投げることにより、通知の送信先を登録することができます。これをオブザーバと言います。ここでは自分自身に通知して欲しいので、第1引数でselfを指定しています。第3引数は、受け取りたい通知の名前を指定します。ここにnilを指定すると、何でも受け取りたいということになりますが、今回は「ImageInfoが変わったぞ」という通知だけを受け取りたいので、前回出て来たTNVWImageInfoChangedNotificationを指定しています。第4引数は、特定のオブジェクトからの通知だけ受け取りたい時に、そのオブジェクトを指定します。今回は、どこから受け取ってもかまわないので、nilを指定しています。では、第2引数は何でしょうか。NSNotificationCenterは、通知を受け取ると、登録されているオブザーバに対し、NSNotificationクラスのインスタンスを引数とするメッセージを投げます。第2引数は、この時投げて欲しいメッセージを指定します。つまり、上記の様にしてオブザーバを登録した時は、次のメソッドを実装しなければなりません。

    - (void)updateImageInfoHandle:(NSNotification *)notif;
    

     これを実装しましょう。実装と言っても、既にパネルを更新する処理は作ってありますから、たったの一行です。

    - (void)updateImageInfoHandle:(NSNotification *)notif{
        [ self updateImageInfo];
    }
    

     これで通知を受け取る処理はできました。ビルドして実行すれば、メインウィンドウが切り替わるたびに、パネルの表示も切り替わるようになったはずです。でも、それはちょっと待ってください。今のままですと、極稀に終了時に吹っ飛ぶかもしれないプログラムになっています。実を言えば、NSNotificationCenterは、オブザーバを登録する時にretainしていません。従いまして、登録したオブザーバが消滅する前に登録を削除しないと、存在しないオブジェクトにメッセージを投げることになってしまいます。そこで、InfoPanelControllerのdeallocをオーバライドし、オブザーバの削除を付け加えて下さい。

    - (void)dealloc {
        [ [ NSNotificationCenter defaultCenter] removeObserver:self 
    name:TNVWImageInfoChangedNotification object:nil];
        [ super dealloc];
    }
    

     これで問題は無くなりました。ビルドして実行してみてください。
     ところで、何でNSNotificationCenterは登録されたオブザーバのretainを行わないのでしょうか。第10回から第13回で説明したように、本来は自分にとってそのオブジェクトが必要であれば、必ずretainすべきです。そうすれば、知らない間に消滅していることがありません。ところが、第13回でも説明したように、cocoaではメッセージを投げて欲しい先を登録するような時は、retainを行いません。これが何故なのか、私も正確な所は知らないのですが、例えばNSNotificationCenterがretainしてしまうと、今回の様にオブジェクトが消滅する時にオブザーバを登録から削除するようにすることが出来なくなってしまいます。何故なら、NSNotificationCenterがretainしている限り、決してdeallocは呼ばれないからです。この様に、retainするとかえって不便になってしまうことから、メッセージを投げて欲しい先を教える場合は、物としてオブジェクトを渡す場合と区別しているのではないかと推測しています。
     それでは、続きは次回です。

    小池邦人の「Carbon API 徒然草」(2004/04/16)

    コールバックルーチンとメニューの初期化

    今回は、初期化ルーチンのstartApplication()で実行しているsetupDrag()とsetupMenu()の内容を解説します。

    本連載で紹介しているサンプルアプリケーションでは、画像ファイル(アイコン)を直接ウィンドウ上にドラッグ&ドロップすることで、その情報をブラウザに登録することが可能です。setupDrag()では、そのドラッグ&ドロップ処理で使用する2つのコールバックルーチン(Callback Routine)を登録しています。

    void setupDrag(void)
    {
        InstallTrackingHandler( (DragTrackingHandlerProcPtr)myTrackDrag,NULL,NULL );
        InstallReceiveHandler( (DragReceiveHandlerProcPtr)myReciveDrag,NULL,NULL );
    }

    コールバックルーチンとは、APIに制御が渡っている間、一時的に制御をアプリ側に返すためにAPI側から呼ばれるルーチンのことです。例えば、ウィンドウに表示された画像をスクロールしようとします。ユーザはスクロールバーの青い部分(スクローラーと言う)をマウスドラッグで動かすことで画像をスクロールします。もしその間にアプリ側で表示制御ができないと、画像スクロールはマウスボタンを離すまで実行されません。スクローラーをマウスで動かしている間もリアルタイムで画像をスクロールさせたい(ライブスクロールと言う)場合には、SetControlAction() というAPIでコントロールにコールバックルーチンを登録し、そこに表示用の制御を記述する必要があるわけです。

    setupDrag()において、InstallTrackingHandler()は「ドラッグ中」(アイコンをドラッグしている間)に呼ばれるコールバックルーチン(myTrackDrag)を登録しています。もう片方のInstallReceiveHandler()は、「ドロップ時」(アイコンを離した瞬間)に呼ばれるコールバックルーチン(myReciveDrag)を登録しています。それぞれのコールバックルーチンに渡される引数や返り値は、その処理が関係しているヘッダーファイルにすべて定義されています。ドラッグ&ドロップのコールバックルーチンについては、Carbon FrameworkのDrag.cを参照してください。

    pascal void myTrackDrag( DragTrackingMessage mes,WindowPtr window,
                                              long *refcon, DragReference dref);
    pascal short myReciveDrag(WindowPtr window, long *refcon, DragReference dref);

    後は、myTrackDrag()とmyReciveDrag()という2つのルーチンを用意し、その中身(処理)をルールに従い記述さえすれば、目的に応じたドラッグ&ドロップ処理が実装できます。myTrackDrag()とmyReciveDrag()の内容については、後ほど本連載の中で詳しく解説したいと思います。ちなみにMac OS 9環境のコールバックルーチンの登録は、以下のように記述されていました。

    void setupDrag(void)
    {
        DragTrackingHandlerUPP   dupp1;
        DragReceiveHandlerUPP    dupp2;
    
        dupp1=NewDragTrackingHandlerUPP( (DragTrackingHandlerProcPtr)myTrackDrag );
        dupp2=NewDragReceiveHandlerUPP( (DragReceiveHandlerProcPtr)myReciveDrag );
    
        InstallTrackingHandler( dupp1,NULL,NULL );
        InstallReceiveHandler( dupp2,NULL,NULL );
    }
    


    ここで登場しているDragTrackingHandlerUPPやDragReceiveHandlerUPPは、「Universal Procedure Pointer(UPP)」と呼ばれています。これは、MacintoshのCPUがPowerPCに移行した時、内部的にまだ残っていた68Kルーチンと新しいPPCルーチンの参照方法の違いを吸収するために導入された仕組みです。UPPはAppleのサンプルコードなどでもよく登場しますが、Mac OS X環境でMach-O(ネイティブ)Carbonアプリケーションを作成する場合には、いちいち用意する必要はありません。本当はコールバックルーチンの先頭に付いている(DragTrackingHandlerProcPtr)や(DragReceiveHandlerProcPtr)といったキャストも不必要なはずなのですが…どうもDrag.hの定義忘れ(バグ?)で、これだけは記述しないとコンパイルエラーが発生するようです。

    続いて、Nibファイルのメニューオブジェクトを呼び出し初期化するsetupMenu()ルーチンです。メニューは「main.nib」ファイルに「MenuBar」というオブジェクト名で登録されています。CreateNibReference()で対象Nibファイルとしてmainを指定し(ファイル名の拡張子は不要)SetMenuBarFromNib()でMenuBarオブジェクトを呼び込みます。CFSTR()はAPIではなく、C文字列を渡しCFStringRef定数(コンスタント)を返すマクロです。これは、CoreFoundation FrameworkのCFString.hに定義されています。実際にCFStringRefオブジェクトをコピーしたり作成したりしているわけではありませんので注意してください。

    void setupMenu(void)
    {
        IBNibRef    nref;
        MenuRef     mhd;
    
        if( ! CreateNibReference( CFSTR("main"), &nref ) ) // main.nibファイルを指定
        {
            SetMenuBarFromNib( nref,CFSTR("MenuBar") );     // MenuBarを呼び込む
            DisposeNibReference( nref );
        }
        DisableMenuCommand( NULL,kHICommandPreferences );   // 初期設定はハイライト
        CreateStandardWindowMenu( 0,&mhd );                // ウィンドウメニュー作成
        InsertMenu( mhd,0 );                               // ウィンドウメニュー登録
        DrawMenuBar();                                     // メニューバー表示
    }
    


    Mac OS Xのアプリケーションメニュー(アップルメニュー左側)には、「環境設定…」「サービス」「…を隠す」「すべて表示」「終了」といったアイテムが自動で追加されます。本サンプルでは環境設定ダイアログを使わないので、DisableMenuCommand()によりアプリケーションメニューの「環境設定…」アイテムをハイライト(使用不可)にします。引数のkHICommandPreferencesは、CarbonEvents.hにおいて’pref’と定義されています。つまり、Manu Managerに対して「Carbon Eventのコマンドとして’pref’が定義されているメニューアイテムをハイライトにしろ!」と命令しているわけです。次のCreateStandardWindowMenu()は、標準のウィンドウメニュー構築するAPIです。得られたMenuRef(mhd)をInsertMenu()に渡し、ウィンドウメニューをメニューバーの一番最後に追加しています。

    InsertMenu()に渡す引数ゼロは「このタイトルをすべてのメニュータイトルの後に挿入しろ」という意味です。代わりに適切なMenuIDを渡せば、そのタイトルの左側にウィンドウメニューが挿入されます。例えばゼロの代わりに128を代入し、メニュー表示がどうなるか試してみてください。こうして初期化されたメニューバーは、イベントループで最初のCarbon Eventが処理される時に自動描画されます。今回については、直ちに描画させるためにルーチンの最後にDrawMenuBar()を呼んでいます。このDrawMenuBar()を外すことでメニューバー描画のタイミングがどのように変化するかを試してみるのも面白いでしょう。Menu Managerに関する各APIの詳しい内容については、ヘッダーファイルのMenu.hで参照することができます。

    次回は、アプリケーション起動時やファイルオープン時に受け取ったApple Eventをどのように処理するかについて解説いたします。Apple EventとCarbon Eventの違いについても簡単にお話したいと思います。

    つづく

    「Behind the WebObjects」  第18回  田畑 英和

     今回はDirectAction内でのリクエストパラメータのハンドリング方法について解説します。セッションを用いた処理の場合は、wodファイルのバインド情報にもとづいて自動的にリクエストパラメータが適切な変数へと代入されますが、DirectActionの場合は明示的にパラメータをハンドリングする必要があります。これは典型的なCGIプログラミングに似ていますが、WebObjectsではリクエストデータはオブジェクトとして扱われますので、HTTPのデータ形式についてまでは意識する必要はありません。だからといってデータ形式について理解していなくてもよいということにはなりませんので、まずはどのような形式でHTTPのリクエストデータが送信されてくるかをみてみましょう。

    ・HTTPデータのサンプル
    key1=123&key2=abc

     例えばこのようなデータがHTTPのリクエストに含まれています。HTTPのリクエストはkeyとvalueのペアから構成され”key=value”のように’='の左側がkeyで右側がvalueになります。複数のkey-valueのペアが存在する場合は’&'で区切られるようになっています。
     こういった形式のリクエストデータはWebObjectsではWORequestのオブジェクトとして扱われます。DirectAction内でWORequestのオブジェクトを取得する方法ですが、次のAPIを用います。

    ・リクエストオブジェクトの取得
    public WORequest request()

     このメソッドはWODirectActionの親クラスのWOActionで定義されています。リクエストオブジェクトの生成はWebObjectsのフレームワーク側で自動的におこなわれますが、DirectActionでリクエストオブジェクトから必要なデータを取り出すにはプログラミングをおこなう必要があります。リクエストオブジェクトが管理するデータにアクセスするには次のようなAPIが用意されています。

    ・WORequsetのメソッド
    public Object formValueForKey(String aKey)
    public String stringFormValueForKey(String aKey)
    public NSArray formValueKeys()
    public NSDictionary formValues()

     formValueForKeyではkey名を指定することにより、リクエストデータの中から任意のvalueを取り出すことができます。formValueForKeyの場合Object型のオブジェクトが返されますが、stringFormValueForKeyの場合はString型のオブジェクトが返されます。
     リクエストデータに含まれる全てのkeyを調べたいときにはformValueKeysを用いると、NSArrayとしてすべてのキーの一覧を取得することができます。またformValuesではすべてのkeyとvalueのペアをNSDictionaryのオブジェクトとして取得することができます。
     これらのAPIを用いて上記のHTTPデータのサンプルにアクセスするには、例えば次のようなコーディングをおこないます。

    ・サンプルプログラム

     WORequest request = request();
         Object obj = request.formValueForKey("key1");
         System.out.println("key1 = " + obj);
         String str = request.stringFormValueForKey("key2");
         System.out.println("key2 = " + str);


    ・実行結果
    key1 = 123
    key2 = abc

     なおこのようなリクエストデータへの直接のアクセスはDirectAction内にかからわらず、WOComponent内でもおこなうことができます。WOComponet内でリクエストオブジェクトを取得するには以下のようにコーディングします。

    ・WOComponet内でのリクエストオブジェクトの取得

         WORequest request = context().request();
    


     このようにしてDirectAction内で任意のリクエストデータをハンドリングすることができます。HTMLのFormによって入力したデータがリクエストデータとして送信されますが、WebObjectsアプリケーション内でDirectActionを呼び出した場合には自動的に追加されるパラメータがあります。
     前々回にも紹介しましたが、セッションをもったページからDirectActionに対してHTML FormをSubmitした場合、リクエストデータに自動的にセッションIDが追加されます。自動的に埋め込まれるセッションIDは、DirectActionを呼び出したページのセッションIDになります。
     具体的には次のようにURLおよびFormのhiddenタグとしてセッションIDが埋め込まれDirectActionへのリクエストデータとして送信されます。

    ・URL
    …/wa/default?wosid=anfSeeYQHtNBebLfZD9Ae0
    ・hidden tag

     このようにリクエストデータにセッションIDが埋め込まれるため、リクエストを受け取ったDirectActionではどのセッションからリクエストが送信されたかを識別することが可能になります。
     それでは、次回はセッションとDirectActionを組み合わせた処理について解説します。

    ニュース・解説

     今週の解説担当:新居雅行

    ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    ┃FileMaker Pro 7は5月中旬に発売
    ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    すでにアナウンスされているFileMakerの次期バージョン「FileMaker 7」であるが、日本でも製品発表が行われた。FileMaker 7 Proが 39,000で2004年5月中旬、FileMaker Developer 7が 69,00で同じく5月中旬に発売される。
    FileMaker 7 ProへのアップグレードはVer.2.1以降のユーザなら可能で価格は19,000となっている。なお、FileMaker Server 7は 129,000で2004年夏、FileMaker Mobile 7は 8,900で2004年夏、FileMaker Server 7 Advancedは289,000で2004年秋にリリースが予定されている。
    FileMaker 7はMac OS X、Windows 2000/XPの対応となっているため、従来のOS利用者も考慮して、ファイルメーカーPro 6などの現行製品も2004年内は販売し続ける予定である。
    FileMaker Pro 7の大きな変化は、リレーショナルデータベースとしての機能が充実したことがまず挙げられる。これまでもリレーションは可能だったが、ファイル単位にテーブルが1つだけだったので、制約された機能ではあった。
    しかしながら、Ver.7では1つのファイルにテーブルを複数定義でき、そのテーブル間のリレーションもグラフィカルに定義できるなど、リレーショナルデータベースとしての機能が向上した。また、データベースのスケーラビリティも向上した。ファイルサイズは8TBとなるなど、上限はほとんど現状では制約にならないだろう。テキストが64KBまでしか1つのフィールドに入らなかったのが2GBになり、もはや制限は気にしなくてもいいくらいだろう。さらに、オブジェクトフィールドに直接ファイルをインポートしたり、あるいはフォーム内でPDFを参照できるなど、テキスト以外のデータの扱いも向上している。
    開発者にとって便利になる機能もいろいろあるが、まずはフィールド定義の計算式の中で、変数が使えるようになったことだ。事実上、式というよりも、式を求めるプログラムを書けるレベルになったと言えるだろう。テキストの一部の書式をいじるといった関数や、指定した文字以外を取り除くフィルタ関数など、便利な関数が増えている。また、スクリプトにパラメータを指定することが可能になったので、ちょっとずつ設定の違うスクリプトを大量に作るという手間は必要なくなるだろう。1つのデータベースでウインドウを複数開くことができるようになったことも便利になった点だ。さらに、Developer版を使えばカスタム関数の定義ができ、そこで作った関数は通常のFileMaker Pro 7でも実行できる。
    ファイルメーカー社では無償のソリューション配布を行っているが、今後も積極的にソリューション展開を行い、ソリューションにフォーカスしたセミナーなども計画している。また、システムインテグレータ支援にも力を入れるなど、より積極的な展開を進めるとしている。

    ファイルメーカー
    http://www.filemaker.co.jp/

    ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    ┃Rendezvous文書からMac OS Xの機能を探る
    ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    Rendezvous関連のTechnical Q&Aが2つ新たに公開されているので、紹介しておこう。

    Technical Q&A: Rendezvous service types used in Mac?OS?X
    http://developer.apple.com/qa/qa2001/qa1312.html

    Rendezvousが使っているサービス名の一覧がまとめられている。サービス名称はある意味、裏の名前でもあるが、この表を見ると、FTPやssh、telnetといったサービスまでRendezvous対応していることが分かる。逆に言えば、Mac OS Xがクライアントとして、どのプロトコルのブラウズをRendezvousで行っているかを見ることができると言えるだろう。たとえば、Mac OS XやMac OS X Serverのsshのサーバ(sshd)はRendezvous対応しているため、ターミナルで接続先のウインドウを表示すると、サーバを自動認識するといったことができる。

    Technical Q&A: NSL and how it relates to Rendezvous
    http://developer.apple.com/qa/qa2001/qa1299.html

    従来からあるNSL(Network Service Location)とRendezvousの解説である。NSLは古くはSLP(Service Location Protocol)やAppleTalkを使っていたが、基本的にはプロトコルと独立したネットワーク上のサービスを参照するための手法となっている。しかしながら、Mac OS X 10.2よりRendezvousを採用しているため、NSLではなくRendezvousを使ったネットワークサービスのブラウズを行うようにすべきだと説明されている。NSL APIは、ネットワーク対象のブラウズダイアログ以外はRendezvous対応はしていないということである。

    ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    ┃Webアプリケーションを生成するビジュアル開発ツール
    ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    BasesoftがリリースするBaseOneは、Mac OS Xで利用できる開発ツールで、Webベースのアプリケーションを生成することが可能だ。ウインドウにボタンやテキストフィールドなどのコンポーネントを配置し、アプリケーション内でテスト動作が可能である。スクリプトとしてJavaScriptなどを追加できると同時に、データベース接続定義を行うことで、データベース処理を組み込んだアプリケーションが生成される。データベースはMySQL、サーバサイドのテクノロジーはPHPに対応している。生成されるJavaScriptでは、ブラウザ毎に異なるスタイルシートを利用するなど、CSSを利用してレイアウトの再現性を高めている。価格は119ユーロだが、14日間のデモライセンスを利用して試用することができる。

    BaseOne
    http://www.basasoft.com/basaone.php

    ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    ┃Mac OS X ServerのユーザパスワードをWebで変更
    ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    Mac OS X ServerでのユーザのパスワードをWebブラウザから変更できるOSXPASSが正式リリースとなっている。以前から開発はされていたが、Ver.2.0としてアップデートされ、さらにC言語で記述したVer.2.1がリリースされている。オープンソースで開発されているので、ページのデザインなどのカスタマイズもやりやすいだろう。開発はeyebits studios。
    Mac OS X Server 10.3ではLDAPをベースにしたディレクトリサービスのもと、パスワードサーバが稼働してパスワード管理をしている。パスワードの変更はMac OS Xでのログインなどで不可能ではないが、たとえばWindowsクライアントや、メールサーバとしてだけの利用を行う場合などではパスワード変更の方法が提供できないか極めて限定していた。ビルドされたCGIと画像のファイルをサーバに配備し、WebサービスでCGI実行権限を付ければ、すぐに利用できる。パスワードが修正されたかどうかは、オープンディレクトリのパスワードサービスのログで確認もできる。

    OSXPASS
    http://sourceforge.net/projects/osxpass/
    パスワードを変更するページ
    http://msyk.net/mosa/DeN/018.png

    MOSAからのお知らせと編集後記は割愛します

    MOSA Developer News   略称[MOSADeN=モサ伝]
    Apple、Mac OSは米国アップルコンピュータ社の登録商標です。またそのほかの各製品名等はそれぞれ各社の商標ならびに登録商標です。
    このメールの再配信、および掲載された記事の無断転載を禁じます。
    http://www.mosa.gr.jp/
    Copyright (C)2004-2006 MOSA. All rights reserved.

  • MOSA Developer News[MOSADeN=モサ伝]第109号

    2004-04-13

    目次

    • Cocoaでいこう! Macらしく  第46回  Yoshiki(DreamField)
    • 藤本裕之のプログラミング夜話 #43
    • 高橋真人の「プログラミング指南」 第42回
    • ニュース・解説
    • MOSAからのお知らせ

    Cocoaでいこう! Macらしく  第46回 Yoshiki(DreamField)

     前回までで、パネルを開いた時に、メインウィンドウのイメージの横幅と縦幅を表示するようになりました。今回は、パネルを開いた後にメインウィンドウが切り替わった時の処理を実装します。

    パネルを表示しよう(その8)

     メインウィンドウが切り替わった時は、パネルに表示している内容も、そのメインウィンドウのイメージの横幅と縦幅に切り替えなければなりません。では、これをどうやって実現すれば良いでしょうか。
     今まで組んだプログラムを思い出してみましょう。MyDocument.mを見てください。メインウィンドウが切り替わった時には、windowDidBecomeMain:が呼び出されるのでした。この中では全員が共通で使うimageInfoクラスのインスタンスに情報をセットしています。このセットした情報をパネルに反映させるには、どうすれば良かったでしょうか。InfopanelController.mを見て下さい。この中の、updateImageInfoが呼び出されれば、パネルに反映されるのでした。つまり、MyDocument.mのwindowDidBecomeMain:の中で情報をセットした後に、updateImageInfoメッセージをInfopanelControllerクラスのインスタンスに投げるようにすれば良いわけです。これは可能でしょうか。
     メッセージを投げるためには、そのインスタンスのアドレスが分かっていなければなりません。InfoPanelControllerクラスのインスタンスを生成するのは、AppController.mの中の、showInfoPanel:でした。これを見ると、インスタンス変数であるinfoPanelControllerにそのアドレスを格納しています。つまり、AppControllerクラスのインスタンスに教えてもらえば、アドレスを取得することはできそうです。でもちょっと待ってください。パネルは最初から表示されているわけでは無いのです。表示するまでインスタンスは生成されませんから、メッセージは送れません。では、これも判断するようにして・・・。何だかとても複雑になってしまいそうですね。この様な処理を単純にできる、とても便利な方法があります。それは、NSNotificationCenterを使うという方法です。

     NSNotificationCenterクラスのインスタンスは、通知の仲介をしてくれます。何か通知を行いたい人は、受け取る人が誰であるか気にする必要はありませんし、受け取る人が存在しているのかどうかさえ考える必要もありません。ただ、NSNotificationCenterに通知を投げるだけです。一方、通知を受け取りたい人は、通知を投げる人のことを知る必要はありません。受け取りたい旨をNSNotificationCenterに登録しておくだけで、通知が来た時に受け取ることができます。この時、特定のメッセージだけ受けたいという指定もできますし、特定の人から来たメッセージだけ受けたいという指定も可能です。
     ところで、CodeWarriorでPowerPlantを使っていた方は、LBroadcasterとLListenerを思い浮かべるかもしれません。こちらは、メッセージを投げる人に投げられる人を登録し、メッセージを投げる方は誰に投げているのかを意識をしないですむという仕組みです。両者を比べると、NSNotificationCenterの方がずっと結合が粗であることが分かります(LBroadcasterとLListenerは、元々はボタンやメニュー等、コントロールの操作をメッセージのやり取りで実現するためのものですから、そもそも目的が違います。まともにオブジェクト指向で組めないC++で、まともにオブジェクト指向で組みたいがために考え出された仕組みなんですね)。

     それでは、NSNotificationCenterの詳しい説明はreferenceや入門書を読んでもらうこととして、ここでは実際にプログラムを組んで行きましょう。ImageInfo.mに、次のメソッドを実装してください。このメソッドは、ImageInfoの内容に変化があったことを通知します。

    - (void)change{
         [ [ NSNotificationCenter defaultCenter] postNotificationName:
    TNVWImageInfoChangedNotification object:self];
    }
    

     NSNotificationCenterクラスのインスタンスは、生成することもできますが、あらかじめタスクに一つ用意されています。ですから、通常はそれを使います。NSNotificationCenterクラスにdefaultCenterメッセージを投げると、その用意されているインスタンスを返してくれます。そして、それに対してpostNotificationName:object:メッセージを投げることにより、通知を行っています。第一引数は通知の名前を示すNSStringクラスのオブジェクト、第二引数は、実は何でも良いのですが、通常は通知を行うオブジェクト(つまり自分自身)を指定します。通知の名前は直接文字列を書いていません。インプリメント部よりも上に次の一行を入れてください。

    NSString *TNVWImageInfoChangedNotification = @"TNVWImageInfoChangedNotification";

     そしてImageInfo.hのインターフェース部よりも上に、extern宣言を入れて下さい。

    extern NSString *TNVWImageInfoChangedNotification;

     この様に宣言して、通知を受け取る方でもTNVWImageInfoChangedNotificationを使うようすれば、打ち間違えてもビルド時にエラーになるので、すぐに分かります。直接文字列を指定すると、これが分からず苦労することになります。あとは、メソッドの宣言にchangeも加えておいてください。続きは、次回です。

    藤本裕之のプログラミング夜話 #43

     このところちと忙しくてネタを仕込んでいるヒマがないので素材ムキ出し気味の話で失礼したい。こないだ、Objective-Cでプログラミング中、なんとも不可解なバグに遭遇してCocoa-dev MLに質問し、Fritz Anderson氏のアドバイスで解決、目からウロコが3枚くらい落ちた。その顛末。

    ことはあるダイアログボックスを巡るコードで起きた。InterfaceBuilder(以下IBと省略)でテキストの入力域(NSTextField)とボタン(NSButton)が1個ずつあるダイアログを作り、NSObjectをサブクラスしてこれのコントローラを作った(NSControllerを使わないのはJAGUARでも動作させたいから)。コントローラに3つのOutlet(Panel, TextToDo, DoItButton)を定義、インスタンシエイトし、それぞれダイアログそのもの、入力域、ボタンと連結する。ソースファイルをジェネレイトして、controlTextDidChange:をオーバーライド、TextToDoの中身が空っぽだったらDoItButtonを選択不能にするコードを書いた……。
     ここまでは何の問題もなかった。ちゃんと意図した通りに動いてたのね。ところがここに「メイン・ウィンドウへ文字列をドラッグ&ドロップされたら、このダイアログを出し、その文字列をTextToDoにセットしたい」という要求が出て来たのね。で、メイン・ウィンドウの方にそういうコードを書き、ダイアログのコントローラに外から文字列をセットするためのメソッドを追加した。「setTextToDo:」という名前の以下のようなコード……。

    -(void) setTextToDo:(NSString*) inString {
    
      [TextToDo setStringValue:inString];
      [self controlTextDidChange:nil];
    
    }

     これが苦闘の始まり。何が起きたかって? まず、最初に気づいたのはもちろん、このセットが正しく行われないこと。文字列をドラッグ&ドロップするとちゃんとダイアログは出るんだが、そこで終わり、何も起こらない。次に気がついたのは、開いたダイアログのTextToDoにキーボードから文字を入力しても「DoItButton」が選択可能にならないこと……。ヘンでしょ? 
     で、いろいろ調べるウチ、どうもTextToDoというOutletがヘンであることが判明した。このコントローラのawakeFromNib:にデバッグ文を入れてこのObjectのアドレスを確認すると、なんとこいつがゼロだったのだ。
    awakeFromNib: といえばオレがオーバーライドしていない initWithCoder:(Nibファイルの中身からObjectを生成する時にCallされる)の次に送られるメッセージである。ここでこいつのアドレスがゼロなら、そりゃこのObjectに対するメッセージは全部機能しないに決まってる。
     試しにもう一つNSTextFieldをダイアログに追加し、そいつのアドレスもプリントするとそっちはマトモ。では、と今までの領域を消し、そいつを改めてコントローラのOutletに繋ぐ……と、またゼロになってしまうではないか。どーなっとるのだ?

     ここまで調べ、途方に暮れてMLに質問した。Fritzの出してくれた回答はスーパーなもんだった。「おまえ、そのOutletの名前Xを使って『setX:』ってメソッドを定義してないか? そいつが initWithCoder: から呼ばれてOutletをゼロにしちゃってんだよ」と。半信半疑でsetTextToDo: にNSLog()を入れてみると果たしてその通り。awakeFromNib: より前にこいつが呼ばれてた。慌ててawakeFromNib:のドキュメントを読むとなるほどこんな意味のことが書いてある。「initWithCoderはIBで定義できる以上の特別な設定を可能にするため、Outletに連結されたインスタンスをロードする前にその名前にsetがついた「setVariable:」を探し、もしあればこれをCALLする。なければインスタンスを探す……」
     いや、以前一度これを読んだんだが、そんときは具体的なイメージが湧かなかったので読み流しちゃたんだよね。そーだったのか。ぢゃ、オレがいままでこのケースに捕まらなかったのは、(意識してなかったんだから当然ながら)偶然Outlet名そのままにsetをつけたメソッドを定義しなかったからつうことになるぢゃないか。がぁん。目から湧き出るウロコをぬぐいつつ、ちと背筋が寒くなった春4月でありました。
    (2004_04_08)

    高橋真人の「プログラミング指南」第42回

    オブジェクト指向のとっかかり(28)

     こんにちは、高橋真人です。
     さて、前回で一通りの説明を終えたプログラムの例ですが、それに手を加えて少しだけ実用的なものに改造していきます。なぜ「少しだけ」なのかというと、一度に大幅に変更してしまうと理解しづらくなってしまう(特に今までのものとの関連性が見えなくなってしまう)からです。
     オブジェクト指向で書かれた実用的なプログラムソースコードのサンプルであれば、今の時代インターネットでいくらでも入手可能ですから、ここはあえて「プログラミング指南」の原点に戻って、ゆっくりと時に冗長なぐらいに説明を展開していくという方向で行きましょう。
     改良したプログラムは以下のようになります。

    // main.cpp
    #include <iostream>
    #include <fstream>
    #include <cstdlib>
    #include "TextContent.h"
    #include "MacText.h"
    #include "DosText.h"
    #include "UnixText.h"
    
    int main()
    {
         std::cerr << "*** Line terminate character convert program *** n"
              << "Enter source file name: " << std::flush;
    
         std::string inputFile;
         std::cin >> inputFile;
    
         std::ifstream ifs(inputFile.c_str(), std::ios::binary);
         if (not ifs) {
              std::cerr << "file was not found.";
              std::abort();
         }
    
         std::cerr << "Reading....." << std::endl;
    
         std::string termChar;
         TextContent *tc = TextContent::InstanceFactory(ifs);
    
         if (tc == NULL) {
              std::cerr << "No terminate characters found." << std::flush;
              std::abort();
         }
    
         tc->ReadFrom(ifs);
    
         std::cerr << "What character do you convert to? n"
              << "1: MAC  2: DOC  3: UNIX n" << "Select number: ";
    
         int number;
         std::cin >> number;
    
         TextContent *tmp;
         switch (number) {
              case 1:
                   tmp = new MacText(tc);
                   break;
              case 2:
                   tmp = new DosText(tc);
                   break;
              case 3:
                   tmp = new UnixText(tc);
                   break;
              default:
                   std::cerr << "Bad number." << std::endl;
                   std::abort();
         }
    
         delete tc;
         tc = tmp;
    
         std::cerr << "Enter destination file name: " << std::flush;
         std::string outputFile;
         std::cin >> outputFile;
         std::ofstream ofs(outputFile.c_str(), std::ios::binary);
         if (not ofs) {
              std::cerr << "Cannot make destination file." << std::endl;
              std::abort();
         }
    
         tc->WriteTo(ofs);
         std::cerr << "Converting completed." << std::endl;
    
         return 0;
    }
    
    // TextContent.h
    #pragma once
    
    #include <fstream>
    #include <string>
    #include <vector>
    
    class TextContent
    {
    public:
                                  TextContent(const char *inTermChar);
    
         static TextContent  *InstanceFactory(std::ifstream &ifs);
         virtual void        ReadFrom(std::ifstream &ifs);
         virtual void        WriteTo(std::ofstream &ofs);
    
         std::vector<std::string> content;
         std::string                        termChar;
    };
    
    // TextContent.cpp
    #include "TextContent.h"
    #include "MacText.h"
    #include "DosText.h"
    #include "UnixText.h"
    
    TextContent::TextContent(const char *inTermChar) : termChar(inTermChar)
    {
    }
    
    TextContent *TextContent::InstanceFactory(std::ifstream &ifs)
    {
         TextContent *returnInstance = NULL;
    
         char c;
         while (ifs.get(c)) {
              if (c == 0x0d) {    // CR
                   if (ifs.get(c)) {
                        if (c == 0x0a) {    // CR + LF
                             returnInstance = new DosText;
                             break;
                        }
                   }
                   returnInstance = new MacText;;
                   break;
              }
              else if (c == 0x0a) {    // LF
                   returnInstance = new UnixText;
                   break;
              }
         }
    
         return returnInstance;
    }
    
    void TextContent::ReadFrom(std::ifstream &ifs)
    {
         ifs.seekg(0, std::ios::end);
         std::size_t size = ifs.tellg();
         ifs.seekg(0);
    
         std::string buffer(size, ' 0');
         ifs.read(&buffer[0], size);
    
         std::string::size_type p1 = 0;
         std::string::size_type p2 = buffer.find(termChar);
         while (p2 != std::string::npos) {
              content.push_back(std::string(buffer.substr(p1, p2 - p1)));
              p1 = p2 + termChar.size();
    
              p2 = buffer.find(termChar, p1);
         }
    }
    
    void TextContent::WriteTo(std::ofstream &ofs)
    {
         for (std::size_t i = 0; i < content.size(); ++i) {
              ofs << content[i].c_str() << termChar;
         }
    }
    
    // MacText.h
    #pragma once
    
    #include "TextContent.h"
    
    class MacText : public TextContent
    {
    public:
                   MacText();
                   MacText(const TextContent *inTC);
    };
    
    // MacText.cpp
    #include "MacText.h"
    
    MacText::MacText() : TextContent(" x0d")
    {
    }
    
    MacText::MacText(const TextContent *inTC) : TextContent(" x0d")
    {
         content = inTC->content;
    }
    
    // UnixText.h
    #pragma once
    
    #include "TextContent.h"
    
    class UnixText : public TextContent
    {
    public:
                   UnixText();
                   UnixText(const TextContent *inTC);
    };
    
    // UnixText.cpp
    #include "UnixText.h"
    
    UnixText::UnixText() : TextContent(" x0a")
    {
    }
    
    UnixText::UnixText(const TextContent *inTC) : TextContent(" x0a")
    {
         content = inTC->content;
    }
    
    // DosText.h
    #pragma once
    
    #include "TextContent.h"
    class DosText : public TextContent
    {
    public:
                   DosText();
                   DosText(const TextContent *inTC);
    };
    
    // DosText.cpp
    #include "DosText.h"
    DosText::DosText() : TextContent(" x0d x0a")
    {
    }
    
    DosText::DosText(const TextContent *inTC) : TextContent(" x0d x0a")
    {
         content = inTC->content;
    }
    

     例によって、解説は次回からです。

    ニュース・解説

     今週の解説担当:小池邦人

    Carbon ドキュメント & サンプル & SDK ナビゲーション(2004/04/09)

    【開発環境】

    Apple社からはWWDC2004に関する色々な情報が提供されています。まずはカンファレンスセッションに関する詳細ですが、その日本語訳が以下のサイトに登録されました。

    http://developer.apple.com/ja/wwdc/descriptions/

    私としては、ちゃんとCarbon関連のセッションもあり一安心しています(笑)。トラックは「アプリケーションテクノロジー」「開発ツール」「エンタープライズIT」「グラフィックス&メディア」「ハードウェア技術」「OSの基礎」「QuickTime デジタルメディア」の7つに分かれています。セッションのタイトルと内容を見ていただくと理解できると思いますが、バリバリのプログラマでない方にもアピールできるようなセッションが数多く用意されています。最近のWWDCは、プログラマの祭典から、多種多様のユーザやデベロッパを対象にしたカンファレンスへと変貌したことがよく理解できます。

    それから、今年は(昨年もあった?)WWDCが開催される前日の6月27日に、WWDC 2004 Pre-Conference Workshopsと名付けられた事前ワークショップが開催されます。ワークショップには、「Cocoa Programming」「AppleScript Hands-On」「Carbon Programming」「The Unix Connection with Mac OS X」「Effective Debugging and Optimization of Mac OS X Code」という5つのコースが用意されています。Cocoa Programmingなどは一日がかりで行われるようですので、これからMac OS Xのプログラミング環境にチャレンジしようとされている方は、前日からこのワークショップに参加されるのが近道かもしれません。詳細については以下のサイトをご覧ください。

    http://developer.apple.com/wwdc/preconference.html

    また、WWDCと同時に開催される各種イベントについても詳細が載っています。
    Mac OS Xのソフトウェアコンテストである「Apple Design Awards 2004」や、会場で併設される「WWDC 2004 Exhibit Fair」(サードパーティの展示会)についての詳細は、それぞれ以下のサイトを参照してください。

    http://developer.apple.com/wwdc/ada.html

    http://developer.apple.com/wwdc/exhibits.html

    今年も映画上映とApple本社でのパーティは開催されるようです(笑)。現時点では、日本からのツアーに関して公式サイトでの紹介はありませんが、こちらも近々発表されると思われます。WWDC2004の参加費用の早期割引は4月30日までですので、参加を予定されている方は忘れないように登録いたしましょう。WWDC2004に関するQ&Aの日本語訳は、以下のサイトにまとめられています。

    http://developer.apple.com/ja/wwdc/faq/

    【テクニカルドキュメント】

    前回から4月9日の期間中、Apple社のDeveloperサイトにはドキュメントが7つ登録されました。「Porting Drivers to Mac OS X」「Core Audio」「Providing Navigation Dialogs」のそれぞれの内容については、先週号の新居さんの記事を参照してください。

    「Porting Drivers to Mac OS X」(PDFあり)
    「Apple Human Interface Guidelines」(PDFあり)
    「Core Audio」(PDFあり)
    「Providing Navigation Dialogs」(PDFあり)
    「WebObjects 5.2.3 API Differences」
    「WebObjects 5.2.3 API Reference」
    「Mac OS X Assembler Guide」

    http://developer.apple.com/documentation/index-rev-date.html

    また、デベロッパ向けの読み物としてXgridについての解説が登録されていま
    す。

    「High Performance Computing for the Rest of Us」(読み物)

    http://developer.apple.com/hardware/hpc/xgrid_intro.html

    前回から4月9日の期間中、新規テクニカルノートはひとつも登録されませんでしたが、テクニカルQ&Aの方は6つ登録されました。QuickTimeの「Sequence Grabber」(映像やサウンドの取り込みに利用するコンポーネント)に関する内容が2つ含まれています。

    QA1349 「Sequence Grabber – How often should I call SGIdle?」
    QA1348 「Sequence Grabber – Using the SGDataProc for Sound」
    QA1347 「Movie export with AAC or AMR audio formats」
    QA1345 「QuickTime movies require a valid graphics port」
    QA1312 「Rendezvous service types used in Mac OS X」
    QA1299 「NSL and how it relates to Rendezvous」

    http://developer.apple.com/technicalqas/index-rev-date.html

    【サンプルソースコード】

    前回から4月9日の期間中、Apple社のSample Codeサイトにはサンプルソースコードが8つ登録されました。久しぶりにサンプルソースコードの復活です(笑)。このうちの7つがOpenGLに関連したサンプルです。サンプル内容は再録に近いのですが、すべて新しく書き換えられています。「Core Graphics」「AGL」「GLUT」という3つのライブラリのどれかを使い、CarbonやCocoaのウィンドウやユーザインターフェースと連動させる方法が解説されている良質のサンプルです。アプリケーションの目的や移植方法の違いにより、OpenGL APIとのリンクに「Core Graphics」「AGL」「GLUT」の使い分けが必要な時にはぜひ参考にしてみてください。「FSCopyObject」の方は再録で、いくつかのバグフィックスがなされているようです。

    「GLCarbon1ContextPbuffer」(OpenGL)
    「GLCarbonAGLFullScreen」(OpenGL)
    「GLCarbonCGLFullScreen」(OpenGL)
    「GLCarbonSharedPbuffer」(OpenGL)
    「GLUTBasics」(OpenGL)
    「GLUTSurfaceTexture」(OpenGL)
    「GLCarbonAGLWindow」(OpenGL)
    「FSCopyObject」(Core Foundation)

    http://developer.apple.com/samplecode/

    【デベロップメント SDK】

    前回から4月9日の期間中、Apple社のSDKサイトにはひとつもSDKが登録されませんでした。

    http://developer.apple.com/sdk/

    MOSAからのお知らせと編集後記は割愛します

    MOSA Developer News   略称[MOSADeN=モサ伝]
    Apple、Mac OSは米国アップルコンピュータ社の登録商標です。またそのほかの各製品名等はそれぞれ各社の商標ならびに登録商標です。
    このメールの再配信、および掲載された記事の無断転載を禁じます。
    http://www.mosa.gr.jp/
    Copyright (C)2004-2006 MOSA. All rights reserved.

  • MOSA Developer News[MOSADeN=モサ伝]第108号

    2004-04-06

    目次

    • Cocoaでいこう! Macらしく  第45回  Yoshiki(DreamField)
    • 小池邦人の「Carbon API 徒然草」
    • 「Behind the WebObjects」  第17回  田畑 英和
    • ニュース・解説
    • MOSAからのお知らせ

    Cocoaでいこう! Macらしく  第45回 Yoshiki(DreamField)

     今日は、いよいよパネルに情報を表示します。

    パネルを表示しよう(その7)

     前回はInfoPanelController.mにupdateImageInfoというメソッドを実装しました。これを実行すれば、パネルにイメージの横幅と縦幅を表示することができます。では、いつ誰がこれを呼び出せば良いのでしょうか。まず、考えられるのは、パネルを表示した直後です。パネルを表示すると同時に、既に表示されているイメージの情報を表示しなければなりません。パネルを表示した直後ですから、実行するのは自分自身ですね。
     それでは、InfoPanelController.mに、次のメソッドを実装してください。場所は、initとupdateの間にしてみてください。

    - (void)windowDidLoad {
        [ self updateImageInfo];
    }

     NSWindowControllerのリファレンスを見てみましょう。最初の方にSubclassing NSWindowControllerという項目がありますから、見つけてください。ここの一覧の中に、windowDidLoadがあります。説明には「Override to perform tasks after the window nib file is loaded.」と書いてあります。
    つまり、nibファイルをロードした後の処理はこれをオーバライドして記述しろ、ということですね。nibファイルをロードする前は、ウィンドウもそれに乗っている部品も実体がありませんから、これに対してメッセージを投げることはできません。そこで、nibファイルをロードした後に実行されるように、これを使うわけです。さらに、windowDidLoadの詳細なリファレンスを見てみましょう。説明の中に「The default implementation does nothing.」と書いてありますね。つまり、元々の実装は空ですから、superクラスのwindowDidLoadを呼び出す必要は無いというわけです。このメソッドの中では、updateImageInfoを呼び出しています。これでパネルを表示した直後に、情報が表示されるはずです。
     では、ビルドしてみましょう。すると、[ self updateImageInfo];の所にワーニングが出ていると思います(fig.01)。とりあえずはこれを無視して、実行してみましょう。何か適当な画像を開いて、それからEditメニューのShow Infoでパネルを開いてみてください。無事に情報が表示されたと思います(fig.02)。

    [fig.01] ビルドするとワーニングが出る
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/45/images/fig01.gif

    [fig.02] パネルに縦幅と横幅が表示された
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/45/images/fig02.jpg

     ところで、先程のワーニングは何だったのでしょうか。TinyViewを終了させて、Xcodeに戻ってみてください。エラーと警告からInfoPanelController.mを選んでみると、次の2つのワーニングが表示されます。

    cannot find method `-updateImageInfo'; return type `id' assumed
    `InfoPanelController' may not respond to `-updateImageInfo'

     つまり、InfoPanelControllerはupdateImageInfoを実装していないかもしれないと言っているわけですね。何でこんなワーニングが出るかと言うと、updateImageInfoの実装がこれより後にあるからです。コンパイラは上から順番に評価して行きますから、この時点では実装していることが分からなかったのです。ですから、実装の順番を入れ替えればこのワーニングは出なくなります。でも、いつもこんなことを考えて配置をしていたら面倒ですよね。それよりもインターフェース部できちんと宣言しておけば、順番なんて考える必要がなくなります。
     実は今まで、説明を短くするために、インターフェース部のメソッドの宣言はおざなりにしてきました。でも、本来はこれはきちんと宣言すべきです。今回の様なワーニングが出なくなりますし、どんなメソッドを実装しているのか見やすくもなります。それに、もしミスをしていれば、ワーニングではなく、きちんとエラーになってくれます。ビルド時に解決できることは、ビルド時に解決しておいた方が後々楽ですから、これは重要です。
     それでは、InfoPanelController.hに、次のメソッドの宣言を加えましょう。

    - (void)updateImageInfo;

     これでビルドすれば、ワーニングは消えます。ついでに、他のメソッドの宣言も加えておきましょう。これを行った後のインターフェース部は、次の様になります。

    @interface InfoPanelController : NSWindowController {
        IBOutlet NSForm *infoForm;
    }
    - (id)init;
    - (void)windowDidLoad;
    - (void)updateImageInfo;
    @end

     さて、これでパネルを表示すれば、その時点のメインウィンドウが表示しているイメージの横幅と縦幅を表示することができるようになりました。でも、このパネルの表示はそれだけではいけないですよね。後から他の画像を開いた時は、その画像の情報表示に変わらなければいけませんし、メインウィンドウが切り替わった時にも、そのウィンドウの画像の情報表示に切り替わらないといけません。この実装は、次回です。

    小池邦人の「Carbon API 徒然草」(2004/04/02)

    メインオブジェクトを確保する-その2

    今回はサンプルアプリケーションのソースコードから一時的に離れ、アプリケーション開発におけるメモリに関する問題点を考えてみます。また、オブジェクト操作の仕組みを自分では実装せず、Frameworkの汎用APIに頼ってしまうやり方(ヒント)についてもお話ししたいと思います。

    Carbon Frameworkのメモリ領域確保用APIは、NewPtr()とNewHandle()です。NewPtr()ではPtr(ポインタ)で参照する静的メモリ領域が、NewHandle()ではHandle(ハンドル)で参照する動的メモリ領域が確保できます。メモリ領域確保と同時にその内容をゼロで埋めたい場合には、NewPtrClear()やNewHandleClear()の方を使います。確保した領域を開放するのは、DisposePtr()とDisposeHandle()の役目です。また、領域のサイズ(容量)を得るためにGetPtrSize()とGetHandleSize()が、Handle同士やHandleとPtr間でデータの複製や結合をするために、HandToHand()、PtrToHand()、PtrAndHand()、HandAndHand()などのAPIが用意されています。Handleとして確保した領域のサイズ変更や再配置を実行するAPIも幾つかあるのですが、筆者は使用したことがありません。上記APIに加え、2つのメモリ領域間でデータのブロック転送を行うBlockMoveData()と、メモリ領域内をすべてゼロで埋めるBlockZero()が筆者が利用しているメモリ関連のAPIです。

    Carbon Frameworkのメモリ関連APIを詳しく調べたい方は、CoreServices FrameworkのMacMemory.hを参照してください。このヘッダを調べると、Mac OS X採用で消えてしまったAPIが沢山あることが分かります。
    それこそが、Mac OS 9とMac OS Xでメモリ管理の仕方が大きく異なる証拠なのです。前回、Mac OS 9においてNewPtr()を使い確保したメモリ領域はフラグメンテーション(メモリ領域の断片化)を発生させる可能性が高いと説明しました。加えて、NewPtr()で大量のメモリを確保しようとすると、非常に時間がかかる欠点があったため、筆者の場合には、なるべく大きなメモリ領域はアプリケーションの起動時に先んじてNewHandle()で確保し、それをHLock()して使うという「癖」が付いてしまいました。確かにHLock()したHandleもフラグメンテーションを引き起こす可能性はあるのですが、この手法を取ればその確率は最小に押さえられます。

    先んじて構造体を指定個数だけ確保する手法の最大の欠点は、利用できるオブジェクト個数を限定してしまうという点です。予想できる範囲内で最大数を確保しておくべきなのでしょうが、そうすると多数の未使用メモリ領域を保持することになり、メモリの使用効率を悪くするのも難点です。しかし、開発するアプリケーションの種類にもよるでしょうが、筆者がこの欠点により問題(ユーザからのクレームを含め)に遭遇したことは一度もありません。現実的には、そうした欠点をそれほど問題視することはないようです。逆に利点としては、オブジェクトの最大使用量が読めるということ、オブジェクトの解放忘れによるメモリリークを気にする必要がないこと、アクセス、確保、解放といった処理が非常に高速であることなどでしょうか。また、オブジェクトの消費により利用可能な「個数」は減りますが、メモリ領域の変動を起こすことがないのも強みです。

    今回のサンプルは、オブジェクトの確保や解放の仕組みを勉強するという意味もあるので、あえて自分自身でその仕組みを用意しています。しかし、自分自身で作るまでもなく、Mac OS XのCarbon Frameworkには、オブジェクトの確保や保存をサポートしているAPI群がいくつも用意されています。その中でも一番古株なのはResource Managerでしょう。Resource Managerのオブジェクト(リソース)は、すべてHandleとして保持されています。Resource Managerは、Mac OS Xが登場する時点で抹殺されてしまうという噂も流れたのですが、ドッコイしぶとく生き残っています(笑)。その役目自体はNib関連のAPIに取って代わられようとしていますが、Resource ManagerのほとんどのAPIは今でもちゃんと利用できます。残念ながら、ツリー構造(多階層構造)でオブジェクトを保持するような目的には向いていませんが、使い道によっては今でも大きな利便さと手軽さを持ち合わせています。

    次に紹介するのはCollection Managerです。「コレクション」とはあまり聞いたことがない名称ですが、QuickDraw GX(憶えてますか?)で図形データやプロパティを管理するために用いられていた仕組みです。QuickDraw GX自身はすでに消滅し存在しませんが(ソースコードはQuartz 2Dに引き継がれている)、そのオブジェクト管理の仕組みは独立して生き残っているという訳です(笑)。APIの種類やその使い方については、CoreServices FrameworkのCollections.hを参照してください。ヘッダファイルには、NewCollection()、DisposeCollection()、ReleaseCollection()など、名称を見れば何をするのかすぐに分かるAPIが並んでいます。いにしえのQuickDraw GXとQuickDraw 3Dは、オブジェクト指向を土台に構築された先進的なソフトウェア・モジュールだったのですが、それがMac OS Xでは採用されず、代わりにQuartz 2DとOpenGLという「原始的」な方が採用されていると言うのは皮肉な結果です(ソフト業界ではよくある話)。

    続いてQuickTimeで用いられているオブジェクト管理用APIを紹介します。QuickTimeの様々なオブジェクトは、「コンテナ(QTAtomContainer)とアトム(QTAtom)」という仕組みで管理されています。これらもリソース同様にHandleとして保持されています。コンテナとアトムでは各オブジェクトをツリー構造で保持できることから、一時はこの仕組みを土台にしHyperCardの新版を開発しようという試みがありました(昔のWWDCでQuikTimeチームがよくデモしていた)。しかし、どうも頓挫してしまったようですね(涙)。Movieのプロパティ、エフェクトのデータ構造、QuickTime用の各種コンポーネントのプロパティ、Wired Movieのデータ構造などなど、コンテナとアトムはQuickTimeのありとあらゆる場所で使われています。自作アプリケーションにQuickTimeに依存した機能を実装しようとすれば、必ずこれらに遭遇することになります。関連ヘッダファイルはQuickTime FrameworkのMovies.hとなりますので、まずはそちらを参照してみてください。

    最後に紹介するのは、CoreFoundation Frameworkに属するCFTree、CFArray、CFStringといったAPI群です。CoreFoundationはNEXTStepから引き継がれたFrameworkですので、すべてのモジュールがオブジェクト指向を土台に構築されています。今からCarbonでMac OS Xネイティブアプリケーションを開発しようと考えている方は、オブジェクト管理の主役としてCoreFoundation APIを採用するのが近道かもしれません。こうして色々と調べてみると、「システムのオブジェクト管理方法を何かひとつに統一しろよ!」とApple社には言いたいところです(彼らはCoreFoundationに一本化したいのだろう…)。しかし、今となってはもう手遅れなのかもしれませんね(笑)。

    次回は、サンプルアプリケーションのソースコードに話を戻し、引き続き各初期化ルーチンの内容を見ていくことにします。

    つづく

    「Behind the WebObjects」  第17回  田畑 英和

     今回はDirect Actionの解説の続きの予定でしたが、WebObjectsのUpdateがリリースされましたので、ここでVer 5.2からこれまでのUpdateの流れをまとめてみたいと思います。各Updateではそれぞれ動作環境が異なっていますので単純に最新版を使えばよいというものでもありません。そこでVer 5.2から最新のUpdateである5.2.3までをまとめておきます。

    WebObjects 5.2

     まずAppleStoreなどで現在販売されているWebObjectsはVer 5.2です。このバージョンがリリースされたのが2002/11ですから、もう1年以上前になります。その後OSやJava環境のアップデートに合わせて計3つのUpdateがリリースされ、それぞれ以下のURLからのUpdateをダウンロードすることができます。

    [[UpdateのURL]]
    ・5.2.1
    http://til.info.apple.co.jp/cgi-bin/WebObjects/TechInfo.woa/wa/showTIL?id=75433
    ・5.2.2
    http://til.info.apple.co.jp/cgi-bin/WebObjects/TechInfo.woa/wa/showTIL?id=107649
    ・5.2.3
    http://til.info.apple.co.jp/cgi-bin/WebObjects/TechInfo.woa/wa/showTIL?id=107873

     ここではWebObjectsがサポートしている各プラットフォームごとの説明や開発環境と運用環境それぞれに関する解説があります。Macの場合はソフトウェアアップデートの機能を使ってUpdateを入手することもできます。各Updateのインストール方法ですが、OS/Java/開発環境のバージョンをあらかじめUpdateに合わせて調整しておく必要がありますので詳しくは上記のTILページを参照してください。それでは各Updateについて詳しくみていきます。

    WebObjects 5.2.1

     Mac上でJava 1.4.xが利用できるようになるまで長い時間がかかりましたが、このUpdateで、WebObjectsもようやく部分的にJava 1.4.1への対応がおこなわれました。ただし、Java 1.3.1と1.4.1の間にある非互換性が一部解消されたとアナウンスされており、この時点でもサポートされる正式なJava環境はJava 1.3.1でした。また1.3.1を正式にサポートする最後のUpdateがこの5.2.1でもあります。
     さいわいMac上では1.3.1と1.4.1が共存するようになっていますので、1.4.1をインストールしてしまった場合でも、1.3.1上でアプリケーションを動作させることができ、その方法が以下のURLで公開されています。

    http://til.info.apple.co.jp/cgi-bin/WebObjects/TechInfo.woa/wa/showTIL?id=75505

     5.2.1の開発環境は以下のようになっています。

    OS : Mac OS X 10.2.4以降
    Java : 1.3.1
    Dev Tools : Dev Tools December 2002

    WebObjects 5.2.2

     Pantherリリース後にリリースされたのがこのUpdateです。このUpdateによりWebObjectsもPantherに対応しました。Pantherでは最初からJava 1.4.1がインストールされていますが、このUpdateによってWebObjectsもようやく1.4.1を正式にサポートするようになりました。逆にこのUpdateでは1.3.1はサポート外となっています。
     Pantherでは開発ツールがProject BuilderからXcodeに移行しましたが、このUpdateによってXcodeへの対応もおこなわれています。ただし、Xcodeでは使用する言語によって機能的な違いがあり、Objective-Cで使える機能がJavaでは使えない場合もあります。開発環境は以下のようになっています。

    OS : Mac OS X 10.3以降
    Java : 1.4.1
    Dev Tools : Xcode 1.0

     このバージョンの運用環境については少し注意が必要です。Panther Serverにはあらかじめ5.2.2のDeploymentがプレインストールされています。Jaguar時代にもMac OS X ServerにはWebObjectsのDeploymentが付属していましたが、使用するには別途インストールをおこなう必要がありました。
     Panther ServerではOSをインストールするとWebObjectsのDeploymentも同時にインストールされるようになりましたが、OSをインストールしただけではWebObjectsの実行環境(wotaskd)は自動的に起動しません。実行環境を起動させるためにはWebObjects用のStartupItemsを編集する必要があります。
     またデフォルトの状態ではCGIタイプのHTTPアダプタが使用されますので、Apache用のHTTPアダプタを使用するのであればhttpd.confを編集する必要があります。StartupItemsとhttpd.confの詳しい編集方法については上記の5.2.2のTILに解説があります。

    WebObjects 5.2.3

     2004/3にリリースされた現時点でのUpdateの最新版になります。このUpdateではJava 1.4.2を正式な動作環境としており、同時にいくつかのバグフィックスもおこなわれています。開発環境は以下のようになっています。

    OS : Mac OS X 10.3.3以降
    Java : 1.4.2
    Dev Tools : Xcode 1.1

     新規にWebObjects 5.2.3の開発環境を用意するのは少し手間がかかります。まずOSを10.3.3にアップデートし、Xcodeを1.1にアップデートし、WebObjectsのUpdateをインストールするには5.2.2をインストールしてから5.2.3をインストールします。またJava環境も1.4.2にアップデートしておく必要があります。
     運用環境についてこのバージョンでも注意が必要です。最初にリリースされた5.2.3のDeployment Update(3/18以前に配布されたもの)にはWebObjects用のStartupItemsを削除してしまうという問題がありました。この問題については次のURLで解決方法が紹介されています。

    http://docs.info.apple.com/article.html?artnum=107909

     ただし現在は修正済みのものが公開されています。ちなみに5.2.3の運用環境はWebObjects単体ではなくApplication Server Updateという名称でJBossやTomcatのUpdateといっしょに配布されています。

     以上がWebObjects5.2から5.2.3までの流れになります。使用中の環境に応じて適切なUpdateをインストールしていただければと思います。また今回説明しましたようにUpdateのリリース直後に問題が発生したこともありますので、新しいUpdateをインストールする場合はまずテスト環境でインストールするなどの対応をおすすめします。またメーリングリストなどで情報収集することも重要でしょう。それでは次回はあらためてDirect Actionの続きを解説したいと思います。

    ニュース・解説

     今週の解説担当:新居雅行

    ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    ┃Navigation Servicesの利用方法を解説する文書が公開
    ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    ファイルを開いたり保存するときに表示されるダイアログやシートを管理するNavigation Servicesの解説ドキュメントが公開されている。これらのダイアログボックスは単に表示するだけでなく、その中にコンポーネントを追加したり、動作をカスタマイズしたいこともよくあるため、プログラミングが必要な場面でもある。Carbonアプリケーションでの利用方法をプログラミング例を示して解説している。

    Introduction to Providing Navigation Dialogs
    http://developer.apple.com/documentation/Carbon/Conceptual/ProvidingNavigationDialogs/

    ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    ┃ファイルメーカーProの新版Ver.7でのAppleScriptの違いを解説
    ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    .com Solutionsは、FileMaker Pro 6と7でのAppleScriptの違いをまとめたPDF文書を公開した。
    7ページの文書であるが、FileMakerを使う上でのいろいろな場面で、Ver. 6と7でのスクリプトの作り方の違いを対比させて記載しており、FileMakerデベロッパは非常に参考になる文書だろう。文書自体はフリーで入手できる。

    .com Solutions: Download and Demo Software
    http://www.fmpromigrator.com/downloads/demo_software/index.html

    ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    ┃OpenBase 8.0.2がリリース、自動的にフェイルオーバーする機能が追加
    ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    Mac OS Xなどで稼働するSQLデータベースエンジンのOpenBaseがVer.8.0.2となった。新しいバージョンでは、データベースのミラーリングやクラスタリングの機能が向上し、問題が発生しても自動的に復活する。クライアントからの切断のない利用が可能となり、可用性が向上した。またストアドプロシージャのスクリプト言語OpenScriptがVer.2となって例外処理などが組み込まれている。他に、Cocoaフレームワークとの互換性を高めることで、Cocoaアプリケーションからの利用がやりやすくなった。

    OpenBase
    http://www.openbase.com/

    ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    ┃REALbasicでユニットテストを実行するフレームワーク
    ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    LogicalVue Softwareは、REALbasicでユニットテストを行うフレームワーク「RBUnit 1.0」をリリースした。フレームワークをREALbasicのプロジェクトの中に含めておくことでユニットテストを実行できる。また、実行結果を参照するユーザインタフェースも提供されている。無償のStandard版と、$39.95のProfessional版がある。違いは、テストの数がStandardでは10項目までだが、Professionalは無制限であるということと、Pro版ではソースコードも公開されているということ。また、Pro版ではコンパイル結果でのユニットテストも可能になっている。REALbasic 5.5以降で利用でき、Mac OS XとWindowsに対応する。Classic版は今後にリリースが予定されている。

    RBUnit
    http://www.logicalvue.com/Products/RBUnit.htm

    ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    ┃Core Audioの解説文書が公開
    ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    サウンドやMIDIを扱うシステム機能であるCore Audioのドキュメントが公開されている。これまでも限定的には公開されているようであるが、Core Audioは先にAPIが公開されており、解説ドキュメントは待ち望まれていたものである。Core Audioの全体像から、各種APIの解説や利用方法を含んでいる。解説はすべてC言語ベースのもので、Javaでの解説は含まれていない。

    Core Audio
    http://developer.apple.com/documentation/MusicAudio/Reference/CoreAudio/

    ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    ┃Mac OS X向けドライバの作成方法を解説した文書が公開
    ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    Mac OS Xのドライバの作成方法を解説した文書が公開されている。Mac OS XではI/O Kitという独自のアーキテクチャで稼働するドライバが必要になるが、他のOSなどでのドライバを移植するための知識としてまとめられているが、I/O Kitの基礎的なことやドライバの基本的なこと、そしてC++言語でのプログラミングなどがまとめられている。

    Porting Drivers to Mac OS X
    http://developer.apple.com/documentation/Porting/Conceptual/PortingDrivers/

    ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    ┃Apple Design Awardsの募集を開始
    ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    Apple Design Awardsの募集が始まっている。Mac用の製品やQuickTimeコンテンツに対するコンテストで、WWDC 2004で発表が行われる。今年から、パフォーマンスを競う部門が新たに設けられた。締め切りは、5月17日となっている。

    Apple Design Awards 2004
    http://developer.apple.com/wwdc/ada.html

    MOSAからのお知らせと編集後記は割愛します

    MOSA Developer News   略称[MOSADeN=モサ伝]
    Apple、Mac OSは米国アップルコンピュータ社の登録商標です。またそのほかの各製品名等はそれぞれ各社の商標ならびに登録商標です。
    このメールの再配信、および掲載された記事の無断転載を禁じます。
    http://www.mosa.gr.jp/
    Copyright (C)2004-2006 MOSA. All rights reserved.