MOSA Multi-OS Software Artists

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

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

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

MOSADenバックナンバー 2005年2月発行分

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

    2005-02-22

    目次

    • SqueakではじめるSmalltalk入門   第31回  鷲見 正人
    • 藤本裕之のプログラミング夜話 #63
    • 高橋真人の「プログラミング指南」  第62回
    • ニュース・解説

    SqueakではじめるSmalltalk入門   第31回  鷲見 正人

     本連載では、名前は知っていてもなかなか触れる機会のないSmalltalkについて、最近話題のSqueakシステムを使って紹介しています。今回から新しく「コレクション」と呼ばれる、配列や文字列の仲間のオブジェクトについて触れるつもりだったのですが、もう一回だけ、ブロックにからめた処理制御について追加させてください。

     前回、処理をフォークさせて、かつ待ち合わせするために便宜的に用いた#forkAndWaitというメソッドがありました。その定義は次のようなものです。「forkAndWait」とタイプした後に選択してbrowse it (cmd + B)することで、いつでも閲覧できます。

    BlockContext >> forkAndWait
       | semaphore |
       semaphore _ Semaphore new.                    "セマフォを作成"
       [self ensure: [semaphore signal]] fork.
       "レシーバの評価が終わり次第signalを送信する処理としてフォーク"
       semaphore wait                      "signal送信までここで待機"

     この内容に関連してセマフォ、そして#ensure:などの例外関係の処理について紹介します。

    前回も触れましたがセマフォは英語でsemaphore、日本語で腕木信号機とでもいうべきオブジェクトで、主にsignalとwaitというメッセージを送って使います。waitを受信したとき、すでにsignalを受け取っていれば、そのまま処理は進みますが、signalを受け取っていなければ別途signalを受け取るまでその処理を中断します。したがって、

    Semaphore new signal; wait

    はすぐに処理を終えますが、

    Semaphore new wait

    とすると、誰が送るわけもないsignalを永遠に待ち続けることになるので、結局、制御は戻ってこずハングアップします(cmd + ピリオドで中断してください)。

    先の#forkAndWaitでは、まず最初にセマフォを作り、続く式で、これからフォークさせる処理(forkAndWaitのレシーバであるブロック。selfに束縛されている)の最後に、そのセマフォへのsignal送信を追加(#ensure:は最後に触れます)してから改めてフォークしています。最後にセマフォにwaitを送って待ちに入り、フォークした処理でセマフォがsignalを受け取ると、その待ち状態が解除され処理が続行する…というからくりになっています。

    さて、話は変わって例外処理についてです。まず、例外を生じさせてそれを捕捉してみましょう。

    | result |
    result _ 3 / #(0 1) atRandom.
    ^ result

     このスクリプトは#(0 1) atRandom、つまり0か1かの選択の結果次第では完了しません。二分の一の確率で0が選ばれると3に「/ 0」というメッセージが送られることになり、その時点で「ZeroDivide」という例外が生じてとまってしまいます(ノーティファイアが出現)。

    ここでいったん、例外が生じる可能性のある処理をブロックで括ってみることにします。お馴染みのvalueを送信すれば直ちに評価できるので、上のスクリプトと同じことになります。

    | result |
    result _ [3 / #(0 1) atRandom] value.
    ^ result
    


     もちろん、これだけでは何も解決しないのですが、ここでvalueの代わりにifError: [...]というメッセージを送ることで、次のような対処が可能になります。

    | result |
    result _ [3 / #(-1 0 1) atRandom] ifError: [Float infinity].
    ^ result

     #ifError:はレシーバを評価し、例外が生じたときはパラメータとして添えられたブロックの評価値を代わりに用いるメソッドです。パラメータとして添えるブロックには2つまでのブロック変数を持たせることが可能で、それぞれから例外の種類と、例外を生じさせたメッセージのレシーバを知ることもできます。くわしくは#ifError:をbrowse it (cmd + B)して定義を眺めてみてください。なお、Float infinityは、浮動小数点数として振る舞う正の無限大値を返します。

    さて。例外が生じたときだけでなく、生じなかったときにでも、共通してきちんと済ませておきたい処理、というのもあります。先ほどの処理待ちセマフォへのsignal送信や、いったん開いたファイルをcloseする作業がよい例です。そんなときは、ifError: [...]の代わりに#forkAndWaitの定義で出てきたensure: [...]を送ります。

    次のスクリプトはtest1.txtというファイルを開いた後、「3 / 0」の結果の文字列表現を書き込んで、最後にファイルをcloseしています。

    | file |
    file _ FileStream fileNamed: 'test1.txt'.
    file nextPutAll: (3 / 0) printString.
    file close.
    


     もちろん、3に「/ 0」というメッセージを送った時点で例外が生じますので以降の処理は続行できず、スクリプトはノーティファイアを出して止まってしまいます。このとき、ファイルは開いたままなので、続けて、

    (FileStream fileNamed: ‘test1.txt’) edit

     などとした場合、このファイルを再び開くことができず、期待された作業ができない可能性があります。

    そこで最初のスクリプトを、

    | file |
    file _ FileStream fileNamed: 'test2.txt'.
    [file nextPutAll: (3 / 0) printString] ensure: [file close].

    というように#ensure:を使って記述しておけば、何らかの原因でブロック内の処理が正常に終了できなくとも、ファイルへのclose送信だけは確実に行なわれ、以後の同ファイルの取扱いに支障はない…というわけです。続けて次の式を評価しても、問題は起こらないはずです。

    (FileStream fileNamed: ‘test2.txt’) edit

     ブロックは、まだまだいろいろなところに出てきますが、ひとまずこれで終わります。次回からは予告通り、コレクションについてです。

    バックナンバー:
    http://squab.no-ip.com:8080/mosaren/

    お詫びと訂正:前回、Processor yieldという式の解説のところで、「Processはa ProcessSchedulerを束縛するグローバル変数で、」と書いてしまいましたが、これは「Processorは…」の誤りです。続けてa Processについても触れているので紛らわしかったかと思います。申しわけありません。

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

     今回は楽しいデリゲートの話。え、そのデリゲートって何だって? ではそこから解説しよう。デリゲート、英語のスペルはdelegateである。これを辞書で調べると、名詞としては「代表者、使節、(米州議会の)下院議員」、動詞としては「代理として送る、委任する」である。ちうことは、NSApplicationのインスタンスであるグローバル変数(これは前回までにやったことなのでもう解説しない)、NSAppに対してあるオブジェクト……なんでもいいんだが委託されるんだから仮にAgentとしようか、をそのデリゲートとしてセットする、つまり

     [ NSApp setDelegate: Agent ];

    とやると、AgentはめでたくNSAppにその仕事の一部を委託されたことになるんである。

    いったんNSAppのデリゲートになれば、NSAppはあらかじめ決められたいくつかの事態が発生したとき、デリゲートとしてセットされているAgentに対してその事態への対処をまかせてくれる。例えばAgentが

     -(void) applicationDidBecomeActive: (NSNotification*) notification;

    というメソッドを持っていれば、NSAppはユーザーの操作によってアプリケーションがアクティブになったとき、このメソッドを呼んで、「アクティブになったときにしておかなければならないこと」をやらせてくるし、

     -(void) applicationDidResignActive: (NSNotification*) notification;

    も定義しておけば、アクティブでなくなったときにも何かを行なうチャンスが貰えるわけである。便利でしょ?

     ここまで来ると、ちょっと経験のあるヒトはこう思うかも。「そんぢゃデリゲートと通知(Notification)は同じもんなんか」と。答えは「ほぼYES」である。上の2つのような、ただ知らせをもらって必要な処理を行なうだけであればデリゲートはそれを必要とするいくつかのオブジェクトのための専属オブザーバーと言ってそうハズレていない。実際問題、デリゲートにこのくらいのことしかさせないでコト足りてしまうアプリケーションだってあるだろう。
     でもあなた、わざわざ言葉を変え、「委託」されているんだからもそっとなんかあるのである。そのひとつ、まずデリゲートはコトの可否判断を任される。よく使いそうなのが、

     -(NSApplicationTerminateReply)
                    applicationShouldTerminate: (NSApplication*) sender;

    であろうか。デリゲートにこのメソッドがあれば、NSAppはアプリケーション終了の前にこれを呼んでお伺いをたててくる。答えは「すぐ終了してよし」「終了しちゃ駄目」「あとで終了」の3種類である。ほかに「Windowが全部閉じられたら終了しちゃっていいか」てなお伺いもある。

     さて、NSApplicationの話はまだ続く。次回はNSAppのデリゲートを使ってヤるコトの中でも最も重要な初期化と終了に関わる部分を重点的に。
    (2005_02_17)

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

    UNIXとしてのMac OS X
    〜Perlについて(8)〜

     こんにちは、高橋真人です。
     今回は「コンテキスト」という考え方について説明します。
     今まで配列というものを何度か扱ってきましたが、Perlで配列の長さを調べるにはどうしたらよいのでしょうか。Perlのリファレンスにlengthという演算子があるので見てみますと、これは文字列用であることが分かります。
     実は、Perlでは「配列はある特定の状況下では、そのまま長さを表す整数として評価される」ことになっています。つまり、配列は「特定の状況下では長さを返す」ということです。
     で、その「特定の状況」を「スカラーコンテキスト」と言います。連載の57回で「リストコンテキスト」という言葉を使いましたが、この二つのコンテキストはよく対比的に語られる、Perlにおける重要な要素です。
     コンテキストという言葉を辞書で調べますと「文脈」とか「前後関係」などという訳語が見つけられます。Carbonプログラマの皆さんにはQuartz 2Dで使われるCGContextというのがおなじみですよね。
     Perlの場合、コンテキストという言葉は「何を求めているか」ということだと考えると分かりやすいと思います。
     スカラーコンテキストとリストコンテキスト。個々に解説するよりも、この二つを対比させて説明した方が違いが際立って分かりやすいので、比較しながら説明していきましょう。

     以前お話ししたように、printという演算子はリストコンテキストを要求するということになっています。従って以下のコードでは配列@arrayはリストコンテキストで解釈されます。

    @array = (1, 2, 3);
    print @array;

     出力結果は「123」となります。
     ところが、この配列をスカラー変数に代入してからprint演算子に渡すと、

    @array = (1, 2, 3);
    $length = @array;
    print $length;
    


    配列の長さである「3」が出力されます。
     print演算子はリストコンテキストを求めていますが、与えられたものがスカラー変数なので変数の内容がそのまま出力されているわけです。
     今、さらっと流してしまいましたが、配列はスカラー変数に代入される時には「長さを表す整数値になる」のです。これをコンテキストの側面から言うと、$lengthという変数に代入される状況はスカラーコンテキストであり、「配列変数@arrayは要素数を返す」となります。
     少し整理しましょう。スカラー、リストの両コンテキストのいちばん典型的な例は、スカラー変数、配列変数、それぞれへの代入です。

    $length = @array;
    @items = @array;
    


     最初の$lengthという変数への代入が行われているところでは、@arrayはスカラーコンテキストで解釈され、保持している要素数である3が入ります。
     対して@itemsという配列変数への代入は、リストコンテキストなので@itemsの各要素は@arrayの中身と同じになるというわけです。
     「何だ、配列同士で代入しているだけじゃないか」と言われれば、確かにその通りなのですが、例えば以下のような書き方も可能です。

    ($a, $b, $c) = @array;

     ここでは、スカラー変数を3つ、カンマで区切ってリストとしていますが、Perlではリストに対しての代入はリストコンテキストとなり、$a、$b、$cにはそれぞれ@arrayの要素が先頭から順番に入るのです(あふれた要素は捨てられる)。もちろんこの代入もリストコンテキストです。

     ところで、配列をスカラーコンテキストで使った場合にはその要素数を返すわけですが、スカラーコンテキストで“リスト”を使ったらどうなると思いますか?

    $value = ('Hello', 256, 'world');

     実際に走らせてみれば分かりますが、この場合、$valueの値は、’world’ になります。実は、「スカラーコンテキストでリストを使うと、最後の要素を返す」ことになっているのです。
     連載の58回でも「配列とリストは同じではない」というお話をしましたが、両者にはこんな違いもあるのです。

    ニュース・解説

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

    Carbon ドキュメント & サンプル & SDK ナビゲーション(2005/2/18)

    【開発環境】

    Apple社が正式に「WWDC 2005」の開催日程を発表しました。今年は、6月6日から6月10日までの5日間の日程でサンフランシスコ(昨年と同じ場所?)で開催されます。

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

    今回は、新規OSのプレビュー版配布といった大きな目玉はなさそうですが、デベロッパー側の興味としては、「この時期までにMac OS X 10.4(Tiger)が正式に発表されているのか?」につきると思われます。どこそこのネット販売サイトでTigerの予約が開始されたり、カッコイイ製品パッケージの写真がリークされたり、Tiger登場近しの雰囲気が漂っている中、筆者としては「開発順調で3月末までには完成!」という噂を信じたいのですが、「6月30日までが前期なのだ!」という「闇の声」もあるようで(笑)まったく予断を許しません。そんなかんなで、WWDC 2005の基調講演において、Jobsの「Today!」の声と共に正式発表となれば、いにしえのSystem 7以来の快挙(?)となるわけです(これだけは避けて欲しい…)。

    今回も、早期参加費用割引や、4チケット同時購入で1チケットは無料というサービスが行われます(4/22まで)。今のところ、当日開催されるセッションの詳細や日本からのツアー紹介などは掲載されていませんが、そのうち追加されると思われます。しばらくの間はこまめにサイトをチェックいたしましょう。

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

    前回から2月18日の期間中、Apple社のDocumentationサイトには新規ドキュメントが8つ登録されました。初版ドキュメントは、最近発表された3機種の新型PowerBook G4のハードウェア仕様書のみで、それ以外はマイナーな改訂版です。また、デベロッパー向けに2つの読み物が登録されています。
    「Introduction to MPI Distributed Programming on Mac OS X」では、分散コンピューティングの世界では標準システム (APIも含む)として広く認知されているMPI(Message Passing Interface)と、Mac OS Xとの関係を詳しく解説しています。分散コンピューティングに興味がある方には、Apple社がTiger Serverで提供するXgridと共に、これから目が離せない話題のひとつでしょう。「Working with Xcode 2.0」」の詳しい内容については、前号の木下さんの解説も参考にしてください。

    「Introduction to MPI Distributed Programming on Mac OS X」(読み物)

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

    「Tiger Developer Overview Series: Working with Xcode 2.0」(読み物)

    http://developer.apple.com/macosx/tiger/xcode2.html

    「17-inch PowerBook G4 Developer Note」(PDFあり)
    「15-inch PowerBook G4 Developer Note」(PDFあり)
    「12-inch PowerBook G4 Developer Note」(PDFあり)
    「Address Book Reference for Objective-C」(PDFあり)
    「Kernel Programming」(PDFあり)
    「Runtime Configuration」
    「WebObjects Overview」(PDFあり)
    「Writing Drivers for Mass Storage Device」(PDFあり)

    http://developer.apple.com/internet/dotmackit.html

    前回から2月18日の期間中、新規テクニカルノートはひとつだけ登録され、新規テクニカルQ&Aの方は6つ登録されました。TN2131では、Mac OS X 10.3におけるOpenGLの変更やバグ修正の履歴がまとめられています。ただし、このテクニカルノートには最新の10.3.8に関する記載がありません。10.3.8のリリースノートを読んでみると、されに追加された変更点があるものと予想されますので、OpenGLを利用されている方は注意してください。QA1410では、QuickTime APIがモダンなAPIへ変身するための課題や問題点が見え隠れしております(笑)。QA1408については、前号の木下さんの解説も参考にしてください。

    TN2131「OpenGL Release Highlights – Mac OS X 10.3 Panther」

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

    QA1364「Where are the LiveConnect classes on Mac OS X?」
    QA1406「Public UTIs supported by Mac OS X v10.3」
    QA1373「CFBundleIdentifier and user application access」
    QA1410「Using language-tagged QuickTime UserData text APIs with CFStrings」
    QA1248「Context Sharing Tips」
    QA1408「Determine the version of an Audio Unit」

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

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

    前回から2月18日の期間中、Apple社のSample Codeサイトには、新しいサンプルソースコードがひとつだけ登録されました。以前に登録された「OSXAdapter」のマイナーな改訂版です。

    「OSXAdapter」(Java関連)

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

    【デベロップメント SDK】

    前回から2月18日の期間中、Apple社のSDKサイトには新しいSDKが2つ登録されました。
    「.Mac 1.1 SDK」とBluetooth SDKの最新版となる「Bluetooth SDK 1.5.3」です。「.Mac 1.1 SDK」については、以前にはADCメンバーサイト経由のみで入手可能でしたが、一般SDKサイトからもダウンロードが可能になりました。

    「.Mac 1.1 SDK」
    「Bluetooth SDK 1.5.3」

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

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

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

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

    2005-02-15

    目次

    • SqueakではじめるSmalltalk入門  第30回  鷲見 正人
    • 小池邦人の「Carbon API 徒然草」
    • 「Behind the WebObjects」    第37回  田畑 英和
    • ニュース・解説   木下 誠

    SqueakではじめるSmalltalk入門   第30回  鷲見 正人

     本連載では、名前は知っていてもなかなか触れる機会のないSmalltalkについて、最近話題のSqueakシステムを使って紹介しています。

     ブロックは、手続きをオブジェクトとして扱うためのものとして存在し、処理結果ではなく手続きごと受け渡しを可能とすること。また、Smalltalkではその特性を利用し、ブロックをメソッド(関数)のパラメータ(引数)に添えることで様々な制御構造を実現していること、について書きました。今回はブロックの扱いの最後として、Smalltakにおける並列処理について簡単に触れます。

     まず、次のようなスクリプトを考えてみましょう。行頭にはコメントのかたちで行番号を振ってあります。

    "01"   | array size |
    "02"   size _ 10.
    "03"   array _ Array new: size.
    "04"   1 to: size do: [: idx |
    "05"      array at: idx put: #a].
    "06"   ^ array

     このスクリプトは、sizeに束縛したサイズの配列を作り、その要素を#aで埋めます。print it (cmd-P) で評価し、結果を得ることが可能です。

    #(#a #a #a #a #a #a #a #a #a #a)

     三行目から四行目、1に対して送信されるto: size do: [...]というメッセージ式は、前回紹介したように、1からsizeまでを繰り返す、いわゆるfor-nextループ処理をシミュレートしています。#at:put:は、配列の指定した要素に指定したオブジェクトを束縛するためのメソッドです。

     この式の前後を[ ]で括るとブロックにできることと、ブロックは、value(ブロック変数のあるときは、value: arg、value: arg1 value: arg2、…)というメッセージを受けることで、自身に記述された手続きを評価して結果を返すことはすでに何度かご説明したとおりです。そこで、次のように書いても上のスクリプトと同じことになります。

    | array size |
    size _ 10.
    array _ Array new: size.
    [1 to: size do: [: idx |            "<= 行頭に[を追加"
       array at: idx put: #a]] value.   "<= 行末に] valueを追加"
    ^ array   " => #(#a #a #a #a #a #a #a #a #a #a) "

     このvalueの代わりに「fork」を送信することで、ブロックに記述した手続きを別のスレッドにフォークする、つまりプロセスを“枝分かれ”させることが可能です。拍子抜けするほど簡単ですね。

    | array size |
    size _ 10.
    array _ Array new: size.
    [1 to: size do: [: idx |
       array at: idx put: #a]] fork.   "<= valueをforkに変更"
    ^ array   " =>  #(nil nil nil nil nil nil nil nil nil nil) "

     要素を#aで埋める作業は、別スレッドで行なわれるので、print it (cmd-P)の結果では、まだ、配列は作られた直後の状態、つまりすべての要素はnil(未定義値)のままです。余談ですが、print itの代わりにinpect it (cmd+I)すると、不思議なことに今度は中身が埋まった状態になります。これは、インスペクタを起動している間にフォークした処理が終わるからです。

     これはこれでおもしろいのですが、何かと不便なので、フォークした処理が終わるまで待ってから結果を表示させるようにしましょう。

    | array size |
    size _ 10.
    array _ Array new: size.
    [1 to: size do: [: idx |
       array at: idx put: #a]] forkAndWait.  "<= forkをforkAndWaitに"
    ^ array   " =>  #(#a #a #a #a #a #a #a #a #a #a) "

     #forkAndWaitは、フォークする処理が終わるまで待つセマフォ(a Semaphore。腕木信号機)を内部的に介在させ、自動的に同期をとってくれるメソッドです。興味があるかたは、forAndWaitを選択しbrowse it (cmd + B)で定義を見てください。

     では、このスクリプトに、今度は#aではなく、#Aで要素を埋める手続きを追加してみましょう。もちろんブロックとして記述し、プロセスはフォークさせます。

    | array size |
    size _ 10.
    array _ Array new: size.
    [1 to: size do: [: idx |           "<= 追加"
       array at: idx put: #A]] fork.   "<= 追加"
    [1 to: size do: [: idx |
       array at: idx put: #a]] forkAndWait.
    ^ array   " =>  #(#a #a #a #a #a #a #a #a #a #a) "

     しかし結果は追加以前と変わりません。Squeakシステムの並列処理は優先順位が同じなら、フォークされた順に待ち合わせ、逐次実行されるからです。順番待ちしている別のスレッドに実行のチャンスを与えるには、Processor yieldというメッセージ式を処理の途中に挿入しておく必要があります。

    | array size |
    size _ 10.
    array _ Array new: size.
    [1 to: size do: [: idx |
       array at: idx put: #A.
        Processor yield]] fork.
    [1 to: size do: [: idx |
       array at: idx put: #a.
       Processor yield]] forkAndWait.
    ^ array   " => #(#a #A #a #A #a #A #a #A #a #A) "

     Processはa ProcessSchedulerを束縛するグローバル変数で、プロセスの監視役です。yieldを受信すると、実行中のプロセスをいったん中断し、待ちプロセスに機会を与えます。これで仲良くスレッド間で譲り合って要素を埋めてゆくので、結果は#A、#aの交互になります。

     valueとほぼ同じ感覚で利用できるforkですが、評価結果を返すvalueと違い、forkはフォークした処理本体(a Process)を返します。これをグローバル変数などに束縛しておけば、任意のタイミングで、suspendやresumeを送信して一時停止や再開、あるいは、terminateを送信することで失効させることが可能です。次のスクリプトは画面左上に現在時刻を表示します。

    Smalltalk at: #TIMER put: nil.   "グローバル変数TIMERの定義"
    TIMER _ [
        [Time now print24 displayAt: 10 @ 10.
        (Delay forSeconds: 0.1) wait] repeat] fork

     ここでフォークされるプロセスは、repeatを使った永久ループになっているので、先の例のように自動的には停止しません。止めるには、次のメッセージ式を評価します。

    TIMER terminate

    バックナンバー:
    http://squab.no-ip.com:8080/mosaren/

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

    Navigation Service APIの活用(その4)

    今回は、「フォルダ選択」や「ファイル読み込み」に用いられるNavigation Service APIを説明します。具体的には、ダイアログのブラウザからファイルやフォルダを選択することができる、NavChooseFolder()とNavGetFile()についての解説となります。

    まず最初に、ユーザが選択したフォルダのFSSpecを得るためのnavMyChooseFolder()ルーチンを紹介します。ダイアログを表示するまでの手順は、navMyPutFile()の時とほぼ同じですが、異なるのは、opt.preferenceKeyに別の識別値’IMGE’を代入している点と、複数ファイルの選択を禁止するために、opt.dialogOptionFlagsのkNavAllowMultipleFilesビットをクリアしている点です。代入する識別値をnavMyPutFile()の時と変えているのは、作業の対象となるファイルの種類が異なるためです。前回はドキュメントファイルが対象でしたが、今回は画像ファイルが対象であり、作業内容に準じたディフォルト表示位置をシステム側に憶えておいてもらうために、異なる識別値を設定しているわけです。

    short navMyChooseFolder( FSSpec *fsc )
    {
        NavReplyRecord      reply;
        short               ret=1;
        DescType            rtype;
        NavDialogOptions    opt;
        Size                len;
        AEKeyword           key;
    
        NavGetDefaultDialogOptions( &opt );     // ダイアログのオプションを初期化
        opt.preferenceKey='IMGE';               // 使用形態を識別するための値を設定
        opt.dialogOptionFlags+=kNavNoTypePopup; // 種類ポップアップメニューを外す
        opt.dialogOptionFlags-=kNavAllowMultipleFiles; // 複数フォルダの選択を禁止
        GetIndString( opt.clientName,128,1 );   // クライアント名をリソースから得る
        if( ! NavChooseFolder( NULL,&reply,&opt,NULL,NULL,NULL ) ) //ダイアログ表示
        {
            if( reply.validRecord )     // OKボタンが押された場合...
                ret=AEGetNthPtr( &(reply.selection),1,typeFSS,&key,&rtype,(Ptr)fsc,
                                                            sizeof(FSSpec),&len );
                                        // 選択フォルダのFSSpecを得る
            NavDisposeReply( &reply );  // NavReplyRecordを削除する
        }
        return( ret ); // ret==noErrであればOKボタンが押されたことになる
    }
    


    続いて「ファイル読み込み」に用いられるnavMyGetFile()ルーチンです。こちらは、「ドキュメント読み込み」と「画像ファイルの登録」という2つの用途に使われるため、最初の引数(kind)の内容により、ダイアログ表示までの準備手順を分岐しています。具体的には、kindがゼロならばドキュメントオープン用として、kindが1であれば画像ファイル登録用として働きます。また、このルーチンからは複数のFSSpecやファイルタイプが返されますので、それらを格納するための配列と、その個数の格納場所である*ctも同時に引数として渡します。この時の配列の最大数(読み込みファイル最大数)については、ヘッダーファイルにMAX_BUF(200個まで)として定義されています。

    #define   MY_SIG   'MosA'   // アプリケーションのシグネイチャ
    #define   MY_DOC   'MosD'   // ドキュメントのファイルタイプ
    #define   MAX_BUF  200      // 一度で読み込む最大のファイル数
    
    short navMyGetFile( short kind,OSType type[],FSSpec fsc[],unsigned long *ct )
    {
        OSType              type1[200];
        long                i,max;
        NavReplyRecord      reply;
        DescType            rtype;
        short               ret=1;
        short               nb=1;
        unsigned long       nn=0;
        NavTypeListHandle   list;
        FSSpec              fsc1;
        NavDialogOptions    opt;
        Size                len;
        AEKeyword           key;
        FInfo               ff;
    
        *ct=0;
        len=sizeof(FSSpec);
    
        NavGetDefaultDialogOptions( &opt );     // ダイアログのオプションを初期化
        GetIndString( opt.clientName,128,1 );   // クライアント名をリソースから得る
        opt.dialogOptionFlags+=kNavNoTypePopup; // 種類ポップアップメニューを外す
    
        if( kind==0 )           // ドキュメントファイルをオープンするための設定
        {
            opt.preferenceKey=MY_SIG;         // 使用形態を識別するための値を設定
            type1[0]=MY_DOC;
        }
        else                    // 画像ファイルをオープン(登録)するための設定
        {
            opt.preferenceKey='IMGE';          // 使用形態を識別するための値を設定
            navGetImportTypeList( type1,&nb ); // QuickTime読み込み可能タイプ
            type1[nb++]=NULL;                  // タイプが設定されていない場合
            type1[nb++]='????';
            type1[nb++]='****';
            type1[nb++]='    ';
        }
        navMakeTypeList( nb,type1,&list ); // 表示対称となるType Listを作成する
    
        if( ! NavGetFile( NULL,&reply,&opt,NULL,NULL,NULL,list,NULL ) ) // 表示する
        {
            if( reply.validRecord )    // OKボタンが押された場合...
            {
                AECountItems( &(reply.selection),&max ); // 選択ファイル数を得る
                if( max > MAX_BUF )                      // 最大数で制限をかける
                    max=MAX_BUF;
                for( i=1;i<=max;i++ )
                {
                    if( ! AEGetNthPtr( &reply.selection,i,typeFSS,&key,&rtype,
                                               (Ptr)&fsc1,sizeof(FSSpec),&len ) )
                                                  // 選択ファイルのFSSpecを得る
                    {
                        FSpGetFInfo( &fsc1,&ff ); // ファイル情報を得る
                        navCheckImportExtention( fsc1.name,&ff.fdType );
                                                  // ファイルの拡張子を調べる
                        type[nn]=ff.fdType;       // 得られたファイルタイプを格納
                        fsc[nn++]=fsc1;           // 得られたFSSpecを格納
                        ret=0;
                    }
                    else
                        break;
                }
                NavDisposeReply( &reply );        // NavReplyRecordを削除する
            }
        }
        DisposeHandle( (Handle)list );            // 作成したNavTypeListHandleを削除
        *ct=nn;                                   // 選択ファイル個数を返す
        return( ret );
    }
    


    用途により分岐させている箇所の目的は、ブラウザに表示させるファイル種類を切り替えることです。その準備として、表示対象とするファイルタイプを配列list1(OSType)へと順次代入していきます。ドキュメントの場合にはMY_DOCをひとつだけセットしていますが、画像ファイルの場合は、まず第一にQuickTime Importerが読み込み可能な画像ファイルタイプ(JPEG,PICT,TIFFなど)をnavGetImportTypeList()ルーチンを使い代入します。しかし、これだけですと、ファイルタイプが設定されていない(NULLの)画像ファイルはブラウザへは表示されません。やっかいなことに、Mac OS X環境では、ファイルタイプが設定されていないため、その種類をファイル名の拡張子から判断しなければならない画像ファイルが沢山存在します。それらをちゃんと表示するためには、NULLを含めたいくつかの特殊なファイルタイプも配列へ追加しておく必要があります。こうして配列へ代入したファイルタイプは、navMakeTypeList()ルーチンによりNavTypeListHandleへと作り直されて、NavGetFile()に渡されます。

    画像ファイルのFSSpecを得る処理が、navMyChooseFolder()の場合と大きく異なるのは、ユーザにブラウザ上での複数ファイルの選択を許しているためです(最大数の制限はある)。まずは、AECountItems()によりファイル選択数を調べ、その個数分のファイルタイプとFSSpecを順次配列に格納します。ファイルタイプの方は、先んじてFSpGetFInfo()で得ておき、その値がNULLであるかどうかをnavCheckImportExtention()ルーチンに渡して調べるようにします。もしそれがNULLであれば、navCheckImportExtention()がファイル名の拡張子を調べることで正しく作り直します。例えば拡張子が.jpgであれば、ファイルタイプは'JPEG'と設定し直されるわけです。

    次回は、navMyGetFile()で呼ばれているnavGetImportTypeList()、navMakeTypeList()、navCheckImportExtention()の3つの自作ルーチンを解説することで、ファイル選択時の悩みの種である「ファイルタイプ」と「拡張子」の共存問題について考えてみます。

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

     いよいよMac OSに対応したOracleの発売が開始されます。ニュースリリースによれば2/25より「Oracle Database 10g for Apple MAC OS X」の出荷開始が開始され、対応OSは「Mac OS X Server」となっています。これでまたMac上で利用できるデータベースが増えたことになります。またデータベースだけではなく開発環境の「Oracle JDeveloper 10g for MAC OS X」も同じく2/25から提供開始となります。
     2/24, 2/25に東京国際フォーラムで開催される「Oracle 10g World」では、Mac版のOracleに関するセッションも予定されており、オラクル技術者向けのサイトでは試用版の提供が開始されています。

    ・Oracle社ニュースリリース
    http://www.oracle.co.jp/news_owa/NEWS/news.news_detail?p_news_code=1301
    ・Oracle Technology Network Japan
    http://otn.oracle.co.jp/

     WebObjectsといえばデータベースと連携したシステムを構築することがなにかと多く、どのようなデータベースを選択するのがよいか考えていかなければなりません。そこで今回はWebObjectsから利用可能なデータベースについて紹介いたします。

    WebObjectsが公式に対応しているデータベース

    ・Microsoft SQL Server 2000
    ・MySQL 3.23.51
    ・OpenBase 7.0.8
    ・Oracle 8.1.7 and 9.2.0.1
    ・Sybase ASE 12.5

     これらが正式にサポートされているデータベースになります。ご覧になっていただいてお分かりのように、けして各データベースの最新版をサポートしているわけではなく、中には今となっては最新版のMac OS Xに完全に対応していないものもあります。
     MySQLは4.1系列のバージョンがリリースされており、WebObjectsのパッケージにもバンドルされているOpenBaseは現在8.0.4(b20)がリリースされています。今回新しくリリースされるOracleは最新版の10gになり、Sybaseについては正式にサポートされているASE 12.5が現在でも最新のバージョンとなっています。必ずしも最新バージョンを使えばよいというわけでもないですが、古いバージョンを使用することのデメリット(例えばサポートの対象外になるなど)を考えれば、積極的な最新環境への対応が望まれます。
     また公式サポートには含まれていませんが、PostgreSQLやFrontBaseといったデータベースも利用することができます。

    ・WebObjects Compatibility Guide
    http://docs.info.apple.com/article.html?artnum=72598
    ・FrontBase
    http://www.frontbase.com

    OpenBase

     それでは、これらのデータベースからOpenBaseとMySQLの概要を簡単に解説したいと思います。まずはOpenBaseですが、こちらはNeXT時代から開発が続けられているデータベースであり、WebObjectsにバンドルされていることもあってWOの開発者であればなにかとおなじみのデータベースです。
     簡単にデータベースの管理がおこなえるツール「OpenBase Manager」が付属していて、さほど高度なスキルがなくともデータベースの管理をおこなうことができます。トランザクション制限があるPsersonal版は無料で使用することができ、トランザクション無制限であっても$1,999からと比較的低価格なデータベースです。昨年はマウイ島でOpenBase Developers Conferenceが開催され、日本から参加された方もいらっしゃったようです。
     前回紹介しましたWebObjectsに付属するサンプルがOpenBaseを使用していたりもしますので、これからWebObjectsを始めるかたはまずはOpenBaseを利用してはいかがでしょうか。

    ・OpenBase
    http://www.openbase.com

    MySQL

     オープンソースのデータベースであり高速性を特長としています。Mac OS X Serverにも搭載されていまして、専用の管理ツールも付属するのですが、初期化と起動/停止程度の機能しかなく、通常は「Terminal」を用いてコマンドライン上での操作が必要になります。
     GUIでの管理をおこなう場合は「CocoaMySQL」を利用することができます。このツールを用いればGUI上でMySQLの管理ができます。データベースやテーブルの編集機能があり、データベースに格納されているデータをブラウズすることもできます。
     もともとMySQLはMac OS X用にビルドされたバイナリーも標準で提供されていますが、MySQL用のシステム環境設定やJDBCドライバをセットにしたパッケージ「Complete MySQL」を利用することもできます。

    ・MySQL
    http://www.mysql.com/
    ・CocoaMySQL
    http://cocoamysql.sourceforge.net/
    ・Complete MySQL
    http://www.serverlogistics.com/mysql.php

    JDBC接続

     WebObjects 5.0以降はリレーショナルデータベースへの接続としてJDBCを用いていますが、JDBCではURLを指定することによりデータベースへの接続情報を設定します。
     基本的なURLの形式は同じなのですが、データベースごとに適切なパラメータを用いる必要があり、特に特定のエンコーディングを指定するときには注意が必要です。TILでJDBCのURLに関する情報が公開されていますので、こちらを参考にしてください。

    ・WebObjects 5.xから各種データベースへの接続
    http://til.info.apple.co.jp/techinfo/100473
    ・JDBC URL を指定してデータベースサーバの文字エンコードを選択する方法
    http://til.info.apple.co.jp/techinfo/107856

     さて、今回はデータベースについて簡単に解説いたしましたが、いかがでしたでしょうか。TigerになるとすべてのMac OS XにSQLiteというデータベースが付属するようにもなりますし、Cocoaベースのオプジェクト永続化フレームワークCoreDataも利用できるようになり、そのリリースが待ち遠しいです。それではまた次回。

    ニュース・解説

    今週の解説担当:木下 誠

    ----------------------------------------------------------------------
    Oracle Database 10gとOracle JDeveloper10gが出荷予定
    ----------------------------------------------------------------------
    日本オラクルが、最新データベース「Oracle Database 10g」とJavaアプリケーションIDE「Oracle JDeveloper 10g」を、Mac OS X Serverに対応させ、2月25日より出荷すると発表していました。これにより、オラクルのデータベースをMac OS X Serverで利用でき、サポートも受けられることになります。
    「Oracle Technology Network Japan (http://otn.oracle.co.jp/)」より、試用版がダウンロードできます。

    Appleは「Oracle Database 10g on Mac OS X Server」というページを公開し、X Serverとオラクルの紹介を行っています。また「Using Oracle JDeveloper on Mac OS X」というページで、JDeveloperのチュートリアルを公開しています。

    2月24日〜25日に東京国際フォーラムで開催される、Oracle 10g World(セッションB-6)にて「いよいよ登場!Oracle Database 10g on Mac OS X全貌」と題したセミナーを行い、製品の紹介を行うそうです。

    Oracle Technology Network Japan
    http://otn.oracle.co.jp/

    Oracle Database 10g on Mac OS X Server
    http://www.apple.com/server/resources/oracle/

    Using Oracle JDeveloper on Mac OS X
    http://developer.apple.com/tools/jdeveloper.html

    OracleとApple、ともに新規市場へ - Oracle 10g、OS X Serverをサポート
    http://pcweb.mycom.co.jp/news/2005/01/31/008.html

    Oracle 10g World
    http://www.oracle.co.jp/events/10g_2005/top.html

    ----------------------------------------------------------------------
    Xcode 2.0の紹介
    ----------------------------------------------------------------------
    Appleが、Tiger Developer Overview Seriesの最新作、「Working with Xcode 2.0」を公開していました。Tigerで導入される、新しいバージョンのXcodeを紹介しています。

    Xcode 2.0の目玉は、コードの可視化機能になるようです。UMLライクな図で、コード全体を眺めることができます。可視化モデルには、クラスモデルとデータモデルの2つがあります。クラスモデルは、クラス階層およびクラス情報を表示するモデルで、Objective-C、C++、Javaに対応しています。編集中のソースコードとの、ダイナミックな同期もサポートされます。データモデルは、Core Dataと連携するモデルで、モデルのオブジェクトグラフを作成、管理します。おそらく、WebObjectsを使っている方には、馴染みやすいでしょう。

    その他には、Search Kitやネットワーク上のリソース同期にも対応した新しいドキュメントブラウザ、レイアウトの自由度が高くなったワークスペース、最新版であるGCC 4.0、などが含まれます。

    Working with Xcode 2.0
    http://developer.apple.com/macosx/tiger/Xcode2.html

    ----------------------------------------------------------------------
    テクニカルQA: Audio Unitのバージョンを調べる
    ----------------------------------------------------------------------
    「Technical Q&A QA1408: Determine the version of an Audio Unit」が公開されていました。現在のシステムで使用可能なAudio Unitのバージョンを調べる方法が解説されています。GetComponentVersion を使うようです。

    最近は、Core Audioの活動が活発ですね。

    QA1408: Determine the version of an Audio Unit
    http://developer.apple.com/qa/qa2005/qa1408.html

    ----------------------------------------------------------------------
    Property List Editorの機能強化版シェアウェア
    ----------------------------------------------------------------------
    Brian Webster's Home Pageより、PlistEdit Proが配布されています。これは、Property Listを編集するためのエディタで、Appleが配布しているProperty List Editorの機能強化版になっています。

    主な機能は、ドラッグ・アンド・ドロップとコピー・ペーストのサポート、アンドゥサポート、フルキーボードナビゲーション、アウトラインとテキストでの編集、Apple Script対応、などとなっています。$24.95 のシェアウェアです。

    AppleのProperty List Editorは機能が貧弱なので、有用だと思います。また、Property Listのエディタは、必要な機能が標準でそろっているので、プログラミングの練習の課題としてもいいのではないでしょうか。

    PlistEdit Pro
    http://homepage.mac.com/bwebster/plisteditpro.html

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

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

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

    2005-02-08

    目次

    • SqueakではじめるSmalltalk入門   第29回  鷲見 正人
    • 藤本裕之のプログラミング夜話 #62
    • 高橋真人の「プログラミング指南」  第61回
    • ニュース・解説

    SqueakではじめるSmalltalk入門   第29回  鷲見 正人

     本連載では、名前は知っていてもなかなか触れる機会のないSmalltalkについて、最近話題のSqueakシステムを使って紹介しています。前回に引き続き、ブロックの効用と絡めながら一般的な制御構造がどのようにメッセージ送信式で表現されるのかを見てゆきましょう。

    ▼永久ループ
     ブロックに対してrepeatを送信すると永久ループになります。停止するには、cmd-ピリオドでユーザー割り込みをかける必要があります。

    | pen |
    pen _ Pen new.
    pen defaultNib: 1.
    pen color: Color red.
    pen place: Display center.
    [pen turn: 360 atRandom; go: 2] repeat

    ▼回数を指定した繰り返し
     有限回数の単純繰り返しは、繰り返したい数を表わす自然数に対して、timesRepeat: [...]というメッセージを送信します。繰り返したい手続きは、ブロックでパラメータ(引数)として与えます。

    | pen |
    pen _ Pen new.
    pen defaultNib: 1; color: Color blue; place: Display center.
    10000 timesRepeat: [pen turn: 360 atRandom; go: 2].
    Display restore

    ▼インデックス付き繰り返し
     いわゆるfor-nextループのようなものを意識したメッセージ式としては、#to:do:というメソッドが使用できます。レシーバは始点、第一パラメータは終点の整数で、第二パラメータとして繰り返す処理のブロックを与えます。繰り返し処理のブロックは、ひとつのブロック変数が必要で、これを介して繰り返し時のインデックスが参照可能です。

    World findATranscript: nil.
    1 to: 10 do: [:idx | Transcript cr; show: idx printString]

     降順にするときは、#to:by:do:を使います。

    World findATranscript: nil.
    10 to: 1 by: -1 do: [:idx | Transcript cr; show: idx printString]

     ただ、#to:do:や#to:by:do:は、本当にfor-nextの焼き直し的な意味しかないメソッドなので、メッセージ送信の体裁は整えられていても、けっしてSmalltalkらしい表現とは言えません。通常はCollection >> #do:を使います。

    World findATranscript: nil.
    (1 to: 10) do: [:each | Transcript cr; show: each printString]

     字面では括弧で括っただけなのですが、メッセージ式としては意味がずいぶんと違ってきます。#to:do:の場合との違い(レシーバやメッセージの意味)を改めてじっくり考えてみるのもおもしろいと思います。(1 to: 10)というのは、インターバル(an Interval)と呼ばれる範囲の定まった等差数列オブジェクトを生成する式です。この#do:に象徴される文字列や配列の仲間をレシーバとした、きわめてSmalltalkらしい繰り返し処理の方法については、この後、引き続きご紹介する予定です。

    ▼条件付き繰り返し
     条件に対して、whileTrue: [...]あるいは、whileFalse: [...]というメッセージを送信することで、実現しています。パラメータに繰り返したい処理をブロックで与えるほかに、終了もしくは継続条件であるレシーバもブロックである点に留意する必要があります。

     次のスクリプトでは、キーボードのシフトキーの押し下げを感知して繰り返しを終了します。

    | pen |
    pen _ Pen new.
    pen defaultNib: 1; color: Color yellow; place: Display center.
    [Sensor shiftPressed]
       whileFalse: [pen turn: 360 atRandom; go: 2].
    Display restore

     条件をnotを送信することで反転させれば、whileTrue:で同じことが可能です。

    | pen |
    pen _ Pen new.
    pen defaultNib: 1; color: Color yellow; place: Display center.
    [Sensor shiftPressed not]
       whileTrue: [pen turn: 360 atRandom; go: 2].
    Display restore

     Sensorは、an EventSensorを束縛するグローバル変数で、入力デバイスの状態を手軽に知りたいときに用います。ただ、Squeakの前身であるSmalltalk-80システム時代から使われているレガシーなサービスなので、簡単なスクリプトで便利に使う程度にとどめておくのがよいようです。キーボードの状態の他にも、マウスボタンの押し下げ状態などを知りたいときにも使えます。

     EventSensorのスーパークラスに当たるInputSensorのmodifier key、mouse、cursorなどのプロトコル(メソッドカテゴリ)をブラウズすると、マウスやキーボードのどういった状態を取り出すことができるのかを知ることができます。

    ▼and/or
     制御構造ではありませんが、条件を記述する際に用いる論理積、論理和の表現でもブロックは活用されます。お馴染みの論理演算二項式をシミュレートした二項メッセージ式としては、

    true | false ” => true (OR) ”
    true & false ” => false (AND) ”

     というのがありますが、これとは別にキーワードセレクタとして#or:、#and:が用意されています。

    true or: [false] ” => true ”
    ture and: [false] ” => false ”

     もちろん評価結果は同じになりますが、キーワードセレクタを使ったメッセージでは、二項セレクタの#|や#&の場合と違って、パラメータがブロックでなければなりません。これは、レシーバの内容によって、パラメータの処理が省略できる場合に対処するためのものです。たとえば、#or:の場合、レシーバがfalseならパラメータの評価の結果で結論は左右されますが、レシーバがtrueならばパラメータの評価は不要…というような状況を想定しています。

     先のスクリプトで、繰り返しの終了条件として「シフトキーの押し下げと同時に画面のクリックする」というものを表現したい場合には、レシーバである条件のブロック内に次のように記述します。

    | pen |
    pen _ Pen new.
    pen defaultNib: 1; color: Color yellow; place: Display center.
    [Sensor shiftPressed and: [Sensor redButtonPressed]]   " ← ココ "
       whileFalse: [pen turn: 360 atRandom; go: 2].
    Display restore

    バックナンバー:
    http://squab.no-ip.com:8080/mosaren/

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

     さて、予告通りNSApplicationというクラスの使い方に話を進めて行こう。
     普通、あるクラスの使い方を説明する場合、まずはコンストラクションから始まって、メソッドのあれこれを説明し、とやるわけだが、このNSApplicationを使うに先立って、我々はこれをインスタンシエイトする必要がない。前回みた、NSApplicationMain()という関数の「やること」の1を思い出して欲しい。そうなのだ、NSApplicationというのはmain()から呼ばれるこの関数によって必ずインスタンシエイトされちゃうのである。そしてそのインスタンスは、プログラム中のどっからでもNSAppというグローバルとして参照できる(この変数はNSApplication.hのなかに宣言されている)。

     NSApplicationのメソッドのうち、最も解りやすいのがアプリケーションに付随する各種オブジェクトにアクセスするためのものだろう。例えばウィンドウメニューのようにメニューのアイテムを動的に変更したい場合、アプリケーションのメインメニューにはどうアクセスすればいいか。

     NSMenu* aMenu = [NSApp mainMenu];

    とやればよい。その他に自分自身のアイコンイメージも獲得できる。……これはどんなときに使うのかな?

     NSImage* anImage = [NSApp applicationIconImage];

    マルチ・ドキュメントのアプリケーションであれば必ず使うのがorderedDocumentsだろう。

     NSArray* documents = [NSApp orderedDocuments];

    とやれば、documents に最前面から順番にアプリケーションが開いているドキュメントのオブジェクトを並べてくれる。同じことはウィンドウに対しても可能だ(orderedWindowを使う……昨年のMOSA湘南ミーティングで私が見せたデモはこれを使ってたね)。keyWindow、mainWindowを使えば現在のキーウィンドウ(キーボードからのイベントを受けるウィンドウ)やメインウィンドウ(最前面のウィンドウ)へのポインタを獲得できる。そしてなかでも大事なのが currentEvent だろう。

     NSEvent* anEvent = [NSApp currentEvent];

    これで、アプリケーションが現在処理中のイベントの中身を知ることができる。例えばあるViewに割り当てたコンテキストメニューを選択されたときなどに、マウスボタンが押されたのがそのViewのなかのどこなのか、正確なポジションが必要な時がある。そういうときはこれを使って処理中のイベントを獲得し、そこからマウスポインタの位置を調べる。この他にもいろいろとあるので自分でドキュメントを参照のこと。とにかくグローバルのNSAppにメッセージ送れば試せるんだから使ってみればいいのである。
     さて、これら「参照系メソッド」(今突然ワタシが名付けましたが)のなかに、現在NSAppのDelegateに指定されているオブジェクトを参照するお馴染みdelegateというメソッドがある(これがあるからには当然setDelegate: もあるんだけどね)。で、NSApplicationの機能の真骨頂はどっちかというとこのDelegateを使った方なのである。……というところで本日の予定終了、続きは次回。
    (2005_02_02)

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

    UNIXとしてのMac OS X
    〜Perlについて(7)〜

     こんにちは、高橋真人です。
     さて、前回お話ししたコード例、

    for (ord ' ' .. ord '~') {
        print chr;
    }

    ですが、Perlではまた違った書き方をすることが可能です。以前にもお話ししたように、Perlは作者であるLarry Wall氏自らが「『やり方はいくらでもある』がPerlのスローガンだ」と言っているように、上記のような単純なループ文を全く別の書き方で実現することもできるのです。
     最近、PythonやRubyなど、Perlに対するアンチテーゼとして「オブジェクト指向スクリプト言語」がいくつか出ていますが、時々これらの言語をPerlと対比して「こっちの方がいい」という文章を見かけます。
     私は「道具は用途によって使い分ける」がポリシーであるため、あえて自分を「○○派」という立場に置かないことにしていますが、もともと自称言語フェチ(笑)なのでPythonにもRubyにも興味はあります。ただ、最近はMac OS本体の勉強だけで手一杯でこれらの言語の勉強にはなかなか時間が割けないため、結果、最も使用経験の長いPerlにいちばん親しんでいるということになります。
     で、PythonやRubyをPerlとの比較で「Perlのオブジェクト指向は後付けじゃないか」というのは、私も全くの同意見です。以前にこの連載でも「Perlにはオブジェクト指向の仕組みはない」と言い切っていますが、もちろん現行Perlがオブジェクト指向の仕組みを備えていることは知っています。ただ、「何が悲しくてPerlでオブジェクト指向をしなければならないの?」というのが私の感じ方でして、Perlのオブジェクト指向を勉強する暇があったら、その分PythonやRubyの勉強に時間を割きたい、ということです。
     ところで、こと「構文比較」という観点から見ると、例えばRubyとPerlを比較して「Perlではこんな書き方しかできないけれども、Rubyならこんなに簡単に書ける」なぁ〜んていう解説を見ることがあります。特にその比較が余りに「表面的」である場合には、私は「ああ、この筆者はRubyに対する愛情の余り、Perlのことを憎んでいるのだな」などと感じて悲しくなります。何故なら、Perlにだってもっと簡単に書く方法はあるのですから!
     まあ、そんな話はどうでもいいのですが、例えば先のコード例の場合こんな書き方をすることもできます。

    print map { chr } (ord ' ' .. ord '~');

     ところで、Perlは時として、かつてのHyperTalkのように「自然な表現でコードを書ける」と思わせる(ただの私の錯覚です)ことがあります。
     例えば、

    if (/^$/) {
        print "Empty line¥n";
    }

    なんてコードがあったとします。まだ正規表現の説明をしていないのでごく簡単に解説しますが、このコードは現在$_という変数の中身が空文字列、もしくは改行文字のみの場合にメッセージを表示するというものです。しかし、このような書き方は時として冗長に見えることがあります。そんな時に、

    print "Empty line¥n" if (/^$/);

    なんて、1行でさらっと書いてしまうことができるのです。どうです? スマートだと思いませんか?
     このように、Perlでは条件部分を修飾的に記述することができるのです。こんな感じでいちばん肝心の処理の部分を先頭に出すことでコード表現がストレートにできる、というのが今回説明しているやり方です。
     それで先ほどのコードですが、ここでも先頭に出ているのはprint演算子で、そのあとにmapやらカッコがゴタゴタと並んでいますね。こういう記述の場合は後ろから読んでいくと分かりやすいのです。処理が後ろから前に順に渡されていくと思ってください。
     最初に、丸カッコで囲まれた部分は前回のコードと同じなのでお分かりですね。範囲演算子を使って0×20から0x7Eまでの値のリストを生成しています。
     次に、このリストはmapという演算子に渡されます。mapという演算子は、リストを引数に取り、リストの各要素に対して{}内の式を適用します。そしてその結果を再びリストとして返します。今回のケースでは、0×20から0x7Eのそれぞれに chr が適用され(暗黙のうちに$_が使われています)、それぞれ ” “から “~” の文字列のリストになって返されるわけですね。
     で、最後にprint演算子がリストを受けて各要素を出力するという具合です。

     さて、今回紹介したような「中・上級者向け」(?)の書き方は、巷にあふれるPerlの入門書ではまず見られないでしょう。Perlを基本から、順序だてて解説する場合には、このような「知らなくてもよい」書き方はとかく「特殊視」され、触れられないことが多いのです。
     しかし、体系的に順序だてて説明していくだけの時間もスペースもないモサ伝の連載だからこそ、このような「おいしい」部分の紹介にも意味があるのではないかということで、あえてこのような書き方の説明をいたしました。

    ニュース・解説

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

    Carbon ドキュメント & サンプル & SDK ナビゲーション(2005/2/4)

    【開発環境】

    サンフランシスコ Expoの基調講演で取り残されていた新型PowerBook G4がついに発表されました。噂通りにG5やDual Core G4の搭載は見送られており、CPUに関しては若干のクロックアップのみにとどまっていますが、スペックを詳しくチェックしてみると大変魅力的な製品に仕上がっています。さっそくADCの割引制度による購入を検討しようと思い立ち、ADCサイトから入手した購入可能製品リストを眺めてみると、何故だかJISキーボードのPowerBook G4しか載っていません(涙)。以前は、英語版キーボードの機種もちゃんと存在していたはずなのに…?

    これはどうしたことかと電話で確認したところ、手続き上リストに載せるのにはもう少し時間がかかるそうですが、今まで通り販売するという方針には変更はないそうです。まずはひと安心ですが、同じことを考えているデベロッパーの皆さんはもう少し待つ必要があるようです。ちなみに、この制度では英語版キーボードのiBook G4の方は販売されていません。多くのデベロッパーは英語版キーボードのマシンが欲しいわけですから、ついでにこちらも購入可能にしてもらえないでしょうか? >アップル社

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

    前回から2月4日の期間中、Apple社のDocumentationサイトには新規ドキュメントがひとつだけ登録されました。新型Xserve G5 のハードウェア仕様書です。G5を空冷で冷却しようとすると2.3MHzまでが限界なのでしょうか? だから2.5GHz版のXserve G5は登場しないのでしょうか…。また、デベロッパー向けに2つの読み物が登録されています。「.Mac SDK」の本体については、ADCのメンバーサイトからダウンロードすることが可能です。詳しい内容については、前号の木下さんの解説も参考にしてください。それにしても、これ…Carbon APIからは使えるようにはならないのでしょうかね?

    「Xserve G5 Developer Note」(PDFあり)

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

    「Turning Up the Volume with Audio Units」(読み物)

    http://developer.apple.com/audio/audiounits.html

    「Using the .Mac SDK」(読み物)

    http://developer.apple.com/internet/dotmackit.html

    前回から2月4日の期間中、新規のテクニカルノートはひとつも登録されませんでしたが、新規テクニカルQ&Aの方は2つ登録されました。QA1386については、前号の木下さんの解説を参考にしてください。

    QA1407「Printer Queue vs. Printer Name」
    QA1386「Core Audio & Xcode – Ensuring the latest Core Audio Headers are installed」

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

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

    前回から2月4日の期間中、Apple社のSample Codeサイトには、新しいサンプルソースコードが2つ登録されました。「AppleScriptRunner」は、AppleScriptを実行するアプリケーションの例題で、以前に登録されていたサンプルの改訂バージョンとなっています。「Audio Unit Effect Templates」の方は、デベロッパー向け読み物の「Turning Up the Volume with Audio Units」の内容と連動しているかもしれません。興味のある方は調べてみてください。

    「Audio Unit Effect Templates」(Core Audio関連)
    「AppleScriptRunner」(AppleScript関連)

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

    【デベロップメント SDK】

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

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

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

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

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

    2005-02-01

    目次

    • SqueakではじめるSmalltalk入門  第28回  鷲見 正人
    • 小池邦人の「Carbon API 徒然草」
    • 「Behind the WebObjects」    第36回  田畑 英和
    • ニュース・解説        ★新執筆者★ 木下 誠

    SqueakではじめるSmalltalk入門   第28回  鷲見 正人

     本連載では、名前は知っていてもなかなか触れる機会のないSmalltalkについて、最近話題のSqueakシステムを使って紹介しています。

     すでに耳タコ状態かもしれませんが、Smalltalkではすべてをメッセージ送信により表現します。前回解説したブロック、つまり「手続きをオブジェクトとして扱えるようにしたもの」は、制御構造などの通常の言語では構文として用意されている挙動もメッセージ送信で実現する際に役立てられています。実際の例で確認してみましょう。

    ▼条件分岐
     これはもう何度も出てきていますので説明は不用ですね。レシーバがtrueあるいはfalse、それぞれの場合に評価したい手続きをパラメータ(引数)として添えたメッセージ送信式になっています。#ifTrue:ifFalse:の二つのパラメータ、つまり手続きは、いずれもブロック変数を持たないブロックでなければいけません。

     名前を尋ねた後、入力文字列の有無を判断して声を掛けてくるスクリプトを示します。

    | nameString |
    nameString _ FillInTheBlank request: 'your name:'.
    nameString isEmpty
       ifTrue: [PopUpMenu inform: 'Nobody knows your name...']
       ifFalse: [PopUpMenu inform: 'Hi, ', nameString, '!']

     FillInTheBlankは、request: aStringというメッセージを受けると、aStringをラベルにした入力欄を表示します。Acceptボタンをクリックしたとき、入力済みの文字列を返値とします。Cancelボタンを押すと”、つまり、長さゼロの文字列が返ります。

     isEmptyは、文字列や配列など、要素を持つオブジェクトに対して送信することで、それらに要素があればfalseを、要素なしならばtrueを返させるメッセージです。

    ” isEmpty ” => true ”
    ‘This is a pen.’ isEmpty ” => false ”
    #() isEmpty ” => true ”
    #(‘this’ is $a 10) isEmpty ” => false ”

     PopUpMenuは、inform: aStringというメッセージを受けとることで、aStringというキャプションの付いた、「OK」というメニュー項目をひとつだけ持つポップアップメニューを作って表示します。

     ところで、この制御構造も「式」なので、通常のメッセージ式同様に評価後には「値」を返します。#ifTrue:ifFalse:の場合、レシーバに対応したブロックの評価の結果がその返値です。つまり、レシーバがtrueなら第一パラメータにvalueを送信した結果が、falseなら第二パラメータにvalueを送信した結果が返ります。

     このことを利用して、たとえば、上のスクリプトの場合、#ifTrue:ifFalse:のパラメータで共通するPopUpMenuへのメッセージ送信部分を括りだすことによる、記述の簡素化も可能です。

    | nameString |
    nameString _ FillInTheBlank request: 'your name:'.
    PopUpMenu inform:
       (nameString isEmpty
          ifTrue: ['Nobody knows your name...']
          ifFalse: ['Hi, ', nameString, '!'])

     ここでPopUpMenuは、#ifTrue:ifFalse:の返値をパラメータにした#inform:を起動するメッセージを受信しています。意味や処理の順番は変わりますが、挙動は前のスクリプトとまったく同じです。

     レシーバがtrueあるいはfalseの場合のみ処理を指定する#ifTrue:、#ifFalse:、パラメータの順序が逆の#ifFalse:iFTrue:も用意されています。

    ▼case-switch文のシミュレート
     SqueakシステムのSmalltalkでは、#caseOf:あるいは#caseOf:otherwise:と独自のカーリーブレイス表記を組み合わせて用いることで、Smalltalk処理系としては珍しいcase-switch表現が実現されています。

    (‘abc’ atRandom)
    caseOf: {[$a] -> [1]. [$b] -> [2]. [$c] -> [3]}

     atRandomは、文字列や配列など要素を持つコレクションオブジェクトから、任意の要素を取り出すメッセージです。この式では、atRandom送信によって’abc’から取り出された文字オブジェクト(a Character)の場合によって、1、2、3いずれかあらかじめ決められた数値を返します。

     カーリーブレイス「{ }」は、リテラルで表現できない要素を持つ配列を直接作りたいときに用いる表現です。この例では[$a] -> [1]、[$b] -> [2]、[$c] -> [3]という三つの式の評価結果を要素とする配列の生成に使われています。

     一見、特殊な表記のように見える#->もメソッドです。#@が「3 @ 4」などとすることでポイント(a Point)を作成したり、#/が「3 / 4」などで分数(a Fraction)を作成するのと同様に、レシーバを「キー(key)」に、パラメータを「値(value)」に据えた「関連(an Association)」というオブジェクトを作成します。case-switchでは、たまたま双方ともブロックが使われていますが、関連オブジェクト一般にはキー(レシーバ)と値(パラメータ)はどんなオブジェクトでも構いません。

     関連オブジェクトのキーと値は、それぞれkey、valueというメッセージを送信することで参照できます。

    (#one -> 1) key ” => #one ”
    (#two -> 2) value ” => 2 ”

     関連オブジェクトを単独で用いるようなことはあまりしませんが、辞書オブジェクト(a Dictionary)におけるキーと値の関係のように、二つのオブジェクトを関連付けるときに内部的によく利用されるので、名前や扱いは覚えておくとよいでしょう。

     #caseOf:あるいは#caseOf:otherwise:は、キーと値それぞれにブロックを束縛した関連オブジェクトを要素に持つ配列をある種の辞書代わりに用い、キーを評価した結果がレシーバと一致した場合に、対応する値ブロックの評価を行なう…という仕組みでcase-switch文をシミュレートしています。
    #caseOf:otherwise:では、第二パラメータにはいずれのケースにも当てはまらない場合の処理をブロックとして与えます。

     このcase-switch表現を用いたスクリプトを次に示します。血液型を尋ねるポップアップが現われるので、項目を選択して答えると、おおざっぱな性格判断の結果を返してきます。

    | menu bloodGroup |
    menu _ SelectionMenu fromArray:
       #(('A'  #a)
         ('B'  #b)
         ('AB' #ab)
         ('O'  #o)).
    bloodGroup _ menu startUpWithCaption: 'blood type:'.
    PopUpMenu confirm:
       (bloodGroup caseOf:
          {[#a]  -> ['nervous!'].
           [#b]  -> ['selfish!'].
           [#ab] -> ['volatile!'].
           [#o]  -> ['optimistic!']} otherwise: ['fishy!'])

    バックナンバー:
    http://squab.no-ip.com:8080/mosaren/

    小池邦人の「Carbon API 徒然草」(2005/01/28)

    Navigation Service APIの活用(その3)

    今回は、FSSpec、FSRef、AliasHandle、CFURLRefを用いたファイルアクセスの仕組みについてもう少し深く解説し、その例題として、FSSpecの代わりにFSRefを得ることが可能な「ファイル名入力ダイアログ」(シートウィンドウ版)を紹介します。

    Mac OS Xでは、FSSpecの代わりにFSRefを用いてファイルアクセスすることで、Unicodeのロングファイル名(255文字)のサポート、大容量ファイル(4Gバイト以上)へのアクセス、ファイル処理のパフォーマンス向上などのメリットが得られます。Mac OS X 10.3からのCarbon FrameworkやQuickTime 6では、ファイルアクセスをFSSpecのみに依存しているAPIは拡張され、FSRefの併用もOKとなりました。ですから、これからのCarbonアプリケーションでは、積極的にFSRefを利用することが可能です。

    まず最初に、FSSpecとFSRefの両構造体を示して比較してみます。

    struct FSSpec {
                      short         RefNum;  // ボリュームリファレンス番号
                      long          parID;   // ディレクトリ ID番号
                      StrFileName   name;    // 63バイトパスカル文字列(Str63)
                  };
    
    struct FSRef  {
                      UInt8         hidden[80];  // File Managerプライベート変数
                  };

    上記のように、FSSpec構造体でのファイル名格納場所はパスカル文字列で63バイト分しかありませんので、Unicodeで255文字(510バイト)のファイル名に対応できないのは明らかです。このままだと、Navigation Serviceで得られたロングファイル名のFSSpecは利用不可のように思われますが、何と「A long long long long file#23A4」といった具合に、名称の最後に「謎の参照値」(笑)が付加されて機能を維持しています。片やFSRef構造体の方は、内容が明示されていない(内緒の…)80バイトのデータ配列を持つだけです。こちらも構造体内にはロングファイル名は格納できないので、配列内に保存された何らかのリファレンス値で別構造体を参照し、ファイルを特定していると考えられます。

    前回も言及しましたが、FSSpecは参照先ファイルが無くても定義できますが、FSRefの方はファイルが存在しないと定義できません。つまり、FSCreateFileUnicode() APIなどでファイルを作成する場合には、そのファイルが入るフォルダのFSRefと、Unicodeでエンコードされたファイル名が必要となるわけです。加えて、その構造体内だけではファイルへのリファレンス情報を保持できないので、定義したFSRef構造体をドキュメントに記録し、それを再度読み込んで同じファイルへアクセスしようとすると失敗します。つまりFSRef構造体は、その名前のとおりアプリケーション内で一時的に用いられる「ファイルへのリファレンス」として働いているわけです。

    こうした理由から、本サンプルがドキュメント内に記録しているのは、再度読み込んでもファイルアクセスが再現できるFSSpec構造体の方です。もし、Unicodeのロングファイル名が必要になれば、FSSpecからFSRefを作り入手できます(今回のリスト表示では行っていませんが…)。また、FSRefをCFURLRefに変換してから記録しておくという手段もあります。CFURLRefは指定ファイルまでの「パス」をUTF8エンコードとして保存していますので、これだけで完全にファイル位置を把握可能です。加えて、CoreFoundation Frameworkには、ファイル参照のためにCFURLRefしか受け取らない「わがままなAPI」もありますので(笑)、それらを手なずけるのには都合が良いでしょう。ちなみにパスを記憶するだけならば、FSRefMakePath()でUTF8エンコードのパスを作成するという手段もあります。

    ただし、FSSpecもCFURLRefもターゲットファイルの保存場所が変わる(パスが変更される)と、その時点で参照できなくなる欠点があります。そうしたケースが想定される場合には、FSSPecやFSRefからAliasHandleを作り、こちらをドキュメントへと記憶することで対処します。Alias Managerは受け取ったAliasHandleの中身を解析し、そのファイルを探し出すために「最大限の努力」をします。AliasHandle内にはファイルのID番号も記録されていますので、同じボリューム内ならば、保存場所が変えられても発見することができます。加えてネットワークボリュームのマウントを要求し、その中をサーチすることまで可能となっています。こうしたファイルの検索順序や方法については、Alias Managerのオプション設定により、ユーザ側で色々とコントロールすることが可能です。

    続いて、FSRefを活用する例題として、ファイル名入力用のシートウィンドウを表示するnavPutFileSheet()ルーチンを紹介します。シートウィンドウは親ウィンドウ(通常は保存するドキュメントが表示されているウィンドウ)のタイトルバーの下から降りてきますので、ルーチンの引数には親ウィンドウのWindowRefを渡すことが必要です。

    #define   MY_SIG   'MosA'   // アプリケーションのシグネイチャ
    #define   MY_DOC   'MosD'   // ドキュメントのファイルタイプ
    
    short navPutFileSheet( WindowRef window,Str255 title )
    {
        short                       ret=1;
        NavDialogRef                dptr;
        NavDialogCreationOptions    opt;
        Str255                      str;
    
        if( ! NavGetDefaultDialogCreationOptions( &opt )  )
                                                // ダイアログのオプションを初期化
        {
            opt.parentWindow=window;            // シートの親ウィンドウを代入
            opt.preferenceKey=MY_SIG;           // 使用形態を識別するための値を設定
            opt.optionFlags+=kNavNoTypePopup;   // 種類ポップアップメニューを外す
            opt.modality=kWindowModalityWindowModal;  // シートであることを設定
    
            GetIndString( str,128,1 );
            opt.clientName=CFStringCreateWithPascalString( NULL,str,
                                                    CFStringGetSystemEncoding() );
                                                // クライアント名をリソースから設定
            opt.saveFileName=CFStringCreateWithPascalString( NULL,title,
                                                    CFStringGetSystemEncoding() );
                                                // ディフォルトファイル名を設定する
            if( ! NavCreatePutFileDialog( &opt,MY_DOC,MY_SIG,navPutEventSheetProc,
                                                         (void *)window,&dptr ) )
                                                // シートウィンドウを作成する
             {
                if( ret=NavDialogRun( dptr ) )  // シートウィンドウを表示する
                    NavDialogDispose( dptr );
            }
            if( opt.saveFileName )
                CFRelease( opt.saveFileName );  // ファイル名をリリース
            if( opt.clientName )
                CFRelease( opt.clientName );    // クライアント名をリリース
        }
        return( ret );
    }
    


    オプション設定の方法については、前回のNavPutFile()とあまり変わりません。ただし、NavGetDefaultDialogOptions()の代わりにNavGetDefaultDialogCreationOptions()を用い、文字列としてパスカルストリングスの代わりにCFStringRef(Unicode文字列)を代入します。
    NavCreatePutFileDialog()でシートウィンドウを作成し、NavDialogRun()で表示させます。navMyPutFile()との違いは、シートウィンドウを表示し終わると、そのままルーチンから抜け出てしまうことです。では、保存ボタンなどが押された時の処理は、どこに記述すれば良いのでしょうか?

    ユーザ操作に対応するための処理は、NavCreatePutFileDialog()に引数として渡されるイベント処理ルーチンのnavPutEventSheetProc()に記述します。

    pascal void navPutEventSheetProc( NavEventCallbackMessage sel,
                                          NavCBRecPtr parm,NavCallBackUserData ud )
    {
        NavReplyRecord   reply;
        FSRef            fsref;
        WindowRef        wptr;
        DescType         type;
        AEKeyword        key;
        Size             len;
    
        if( parm->context  )
        {
            wptr=(WindowRef)ud;  // 親ウィンドウのWindowRefを得る
            switch( sel )
            {
                case kNavCBUserAction:  // ユーザが何か操作を実行した
    
                    switch( parm->userAction )
                    {
                          case kNavUserActionSaveAs: // 保存ボタンが押された
    
                              if( ! NavDialogGetReply( parm->context,&reply ) )
                                                     // NavReplyRecord構造体を得る
    
                              {
                                  AEGetNthPtr( &reply->selection,1,typeFSRef,
                                      &key,&type,(Ptr)&fsref,sizeof( FSRef ),&len );
                                  // ファイルを保存するフォルダのFSRefを得る
    
                                  myDocumentSave( wptr,fsref,reply->saveFileName );
                                  // ドキュメント保存用の自作ルーチン
                                  // ファイルを保存するフォルダのfsrefと
                                  // ファイル名のreply->saveFileNameを使い
                                  // ドキュメントファイルの保存を実行する
    
                                  NavDisposeReply( &reply );
                                                      // NavReplyRecord構造体を破棄
                               }
                               break;
    
                         case kNavUserActionCancel:   // キャンセルボタンが押された
    
                             break;
                    }
                    break;
    
                case kNavCBTerminate:  // 作業が終了
    
                    NavDialogDispose( parm->context ); //シートウィンドウを削除
                    break;
            }
        }
    }
    


    ユーザがシートウィンドウ上でどんな操作をしたかは、引数で渡されるNavCBRecPtr経由で判断することが出来ます。この例では、保存ボタンがクリックされた時点でドキュメントを保存するフォルダのFSRef(ドキュメント自身のFSRefではないので注意!)を得て、それを入力ファイル名のreply->saveFileName(CFStringRef)と共に自作ルーチンに渡し、ドキュメントファイルを保存する処理を実行しています。

    FSRefとCFURLRefの使用方法については以下の2つのテックノートが大変参考になりますので、興味がある方はぜひ参照してみてください。どちらも日本語訳が存在しています。

    TN2078「Migrating to FSRefs & long Unicode names from FSSpecs」(日本語版)

    http://developer.apple.com/ja/technotes/tn2078.html

    TN2022「The Death of typeFSSpec:moving along to typeFileURL」(日本語版)

    http://developer.apple.com/ja/technotes/tn2022.html

    次回は、「フォルダ選択」や「ファイル読み込み」時に使うNavigation ServiceのAPIを説明します。具体的には、ファイルやフォルダを選択するためのダイアログを表示するNavChooseFolder()とNavGetFile()の使用方法や注意点についての解説となります。

    つづく

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

     今回も前回に引き続き、これからWebObjectsを始めるデベロッパー向けの情報をまとめてみました。WOの情報が少ないというのはよく聞く話です。たしかに雑誌などで取り上げられることはあまりありませんが、それでも探してみると情報は色々あるものです。

    Appleのドキュメント

     まずはなんといってもAppleのドキュメントがあります。最新版の全てのドキュメントが日本語訳されてはいませんが、基本的なドキュメントは日本語版も用意されています。

    ・英語
    http://developer.apple.com/referencelibrary/WebObjects/index.html
    ・日本語
    http://www.apple.com/jp/webobjects/wo_docs_j.html

    ◇Getting Started
     英語のほうのサイトの情報に基づいて解説を続けて行きますが、こちらのドキュメントを初めて見る方はまず上記URLの”Getting Started”を参照してください。ここでは目的別に各ドキュメントの簡単な説明があり、これから開発をおこなうデベロッパーはまず”WebObjects Overview”を読んで概要を把握するところから始めましょう。

    ◇WebObjects Overview
    このドキュメントは日本語訳もあり、英語版では2002/1にWO5.1向けに改訂されたものをもとに翻訳されています。その後、英語版ではWO5.2で加わったWeb Servicesの記述が追加されるなどしていますが、WOの基本的な概要を理解するには日本語版でも十分でしょう。

    ◇Web Applications/Discovering WebObjects for HTML
     HTMLベースのアプリケーションを開発する場合、次に読むドキュメントとして”Web Applications”が紹介されています。ここではアプリケーションの開発手順がサンプルをまじえて解説されており、サンプルのプロジェクトもWebからダウンロードすることができます。
     このドキュメントは、もともと”Discovering WebObjects for HTML”として公開されていたものが、WO5.2のリリース時に改訂されてタイトルが現在のものに変更されています。また、そのさいバックトラッキングとキャッシュ管理に関する章が追加されています。一方、日本語版のほうは最初のバージョンに対応した翻訳ですので、タイトルも元にままになっており、注意が必要です。その他のドキュメントとしては、Direct To Webの解説や、データベースアクセス関連の、EOModelerの使い方やEnterprise Objectsの解説があります。

    ◇API Reference
     API ReferenceとしてはJavaDoc形式のものがWeb上で参照可能であり、tgz形式にアーカイブされたものをダウンロードすることもできます。また、各バージョン間でのAPIの差分情報も5.1と5.2、5.2と5.2.2、5.2と5.2.3の組み合わせが用意されています。
     現時点でのWebObjectsの最新版は5.2.3ですがGetting Startedページからのリンクは5.2.2のままになっていますのでご注意ください。
     こういったドキュメントは開発時に頻繁に参照するため、できることなら日本語で用意されていたほうが便利でしょうが、残念ながら英語でしか提供されていません。

    ・WO5.2.3 Java Doc
    http://developer.apple.com/documentation/WebObjects/Reference/API/index.html

    ◇その他の開発用ドキュメント
     WebObjectsではHTMLベース以外のアプリケーションも開発することができますが、Web Servicesのドキュメントや、デスクトップアプリケーションを開発するためのJava Clientのドキュメントも用意されています。また、J2EE関連では、EJB、JSP、Servletsに関するドキュメントも用意されています。

    ◇運用ドキュメント
     運用のためのドキュメントとしては”Deploying Applications”が用意されており、運用環境の解説から、具体的な運用時の操作方法まで詳しく解説されています。しかしAPI Referenceと同様にこちらも英語の情報のみとなります。
     このようにまだいくつかのドキュメントは日本語訳されていないものもありますが、日本語独自の情報として、次のURLで開発と運用に関するものが用意されています。

    ・WebObjectsによる開発と運用についての技術情報
    http://www.apple.com/jp/webobjects/techinfo/index.html

    WebObjectsに付属のリソースとサンプルコード

     WebObjectsをインストールした場合も、英語版だけではありますが今回紹介したドキュメント一式がインストールされます。ただし、ドキュメントは追加や改訂がおこなわれる場合がありますので、最新版についてはWeb上のドキュメントを確認するようにしてください。
     また、サンプルコードもWebObjectsに付属のものや、Webからダウンロードできるものがあります。

    ・WebObjects付属のドキュメント
    /Developer/Documentation/WebObjects
    ・WebObjects付属のサンプル
    /Developer/Examples/JavaWebObjects
    ・サンプルコード
    http://www.apple.com/jp/webobjects/samples.html

    メーリングリスト

     今回紹介したドキュメントおよびサンプルだけでもかなりの量になりますが、ディスカッションの場としてAppleとOmni社がメーリングリストを提供しています。どちらも英語のメーリングリストになり、Appleが提供しているものは、開発、運用、アナウンスと3つに別れています。アナウンスはリリースなどに関してAppleからの発表に使われているものです。もっとも最近はアナウンスがあまりありませんが(T_T)

    ・Apple
    http://lists.apple.com/mailman/listinfo/webobjects-dev
    http://lists.apple.com/mailman/listinfo/webobjects-deploy
    http://lists.apple.com/mailman/listinfo/webobjects-announce
    ・Omni
    http://www.omnigroup.com/developer/mailinglists/

    書籍

     またまた英語での情報になりますが、入門用の書籍を1冊ご紹介しておきます。Mac OS X 10.2.2 + Project Builderをもとに執筆された書籍ですが、操作手順がスクリーンショット付きで丁寧に解説されており、内容も基本的な部分から運用までまんべんなくカバーされています。

    「WebObjects 5 for Mac OS X(Visual Quickpro Guide)」
    http://www.peachpit.com/title/032111549X
    http://www.amazon.co.jp/exec/obidos/ASIN/032111549X

     さて、英語での情報に少々かたよってしまいましたが、WebObjetsに関する情報をまとめてみました。もちろんWeb上ではこの他にも様々な情報にアクセスすることができますので、Googleを有効利用するなどして開発に役立ててください。

    ニュース・解説

    今週の解説担当:木下 誠

    MOSADeNの読者の方、初めまして。HAPPY Macintosh Developing TIME! の木下といいます。今回から、新居さんの後を受けて、ニュース・解説を担当させていただくことになりました。CocoaとJava関連を中心に、Mac OS Xの開発関連のニュースをピックアップしていこうと思います。よろしくお願いします。

    ———————————————————————-
    .Mac SDKが公開
    ———————————————————————-

    Appleが、ADCで.Mac SDK 1.1を公開、およびドキュメント『Using the .Mac SDK』を公開していました。.Mac SDKは、2004年のWWDCで紹介されたフレームワークで、iDiskへのアクセス、.Macアカウントの管理などが行えます。必要となるシステムは、Mac OS X 10.2.6以降です。

    .Mac SDKでは、Cocoa APIから使えるDotMacKit.frameworkを提供しています。このフレームワークを使うことで、自分のアプリケーションから、iAppと同じようにiDiskへのアクセスが行えます。また、SDKにはiDiskのブラウズや、iDiskへのバックアップを行うサンプルが含まれます。

    Using the .Mac SDK
    http://developer.apple.com/internet/dotmackit.html

    ———————————————————————-
    テクニカルQA: Core AudioとXcode
    ———————————————————————-

    AppleのTechnical Q&Aで、『QA1386: Core Audio & Xcode – Ensuring the latest Core Audio Headers are installed』が公開されていました。Xcode 1.5をインストールすると、Core Audioのヘッダが書き換えられてしまう問題を説明しています。

    これは、QuickTime 6.5.2をインストールすると、Core Audioのヘッダとコンポーネントがアップデートされるために起こるようです。この場合、Xcodeのインストール時にMac OS X SDKのインストールをスキップすることが推奨されています。

    QA1386: Core Audio & Xcode – Ensuring the latest Core Audio Headers are installed
    http://developer.apple.com/qa/qa2004/qa1386.html

    ———————————————————————-
    Dashboard開発サイトがオープン
    ———————————————————————-

    Dashboardの開発情報を取り扱うWebサイト、DashboardDeveloperがオープンしていました。このサイトには、Dashboardのニュースを取り扱うほか、作成したWidgetを登録するギャラリーや、開発情報を議論するフォーラムがあります。Tigerはまだベータリリースもされていませんが、すでにWidgetの登録が行われているようです。

    Tigerの目玉機能の1つとなるDashboardですが、完全に新しい環境なので、開発のノウハウはこれから作っていくことになると思います。こちらのフォーラムでは早速議論が行われているようなので、のぞいてみると面白いと思います。

    Dashboard Developer
    http://www.dashboarddev.com/

    ———————————————————————-
    Xcodeを組み込み開発で利用
    ———————————————————————-

    MacDevCenter.comで、Xcodeを組み込み開発に利用する記事、『Embedded Development with Xcode』が公開されていました。これは、XcodeのGUIを使って、リッチな環境で組み込み開発を行う方法を解説したものです。

    記事では、ATMEL AVRチップを例題にして、Xcodeで組み込み開発環境を構築する手順を説明しています。Xcodeで、AVRチップ用のコンパイラ、アセンブラ、リンカといったツールを扱えるように設定するのがメインとなります。

    Embedded Development with Xcode
    http://www.macdevcenter.com/pub/a/mac/2005/01/21/embedded.html?CMP=ILC-macrss&ATT=Embedded+Development+with+Xcode

    執筆者プロフィール:木下誠
    HAPPY Macintosh Developing TIME!という、Mac開発系サイトを運営しています。Cocoaを中心に、Mac OS Xの開発の話題を取り扱っています。また、去年よりWeb Kitを使ってブラウザを作る、シイラプロジェクトを開始しています。最近はMac OS Xらしく、直感的で爽快なGUIを目指して、新たな動きを起こしています。
    http://homepage.mac.com/mkino2/

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

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