MOSA Multi-OS Software Artists

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

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

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

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

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

    2004-03-30

    目次

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

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

     今回でこの連載も丸一年になります。一年間のご愛読、ありがとうございました。実は、丁度一年で連載終了・・・のつもりだったのですが、きりの良い所まで行きませんでした(^^;)。最低限説明しないといけないことも残っていますし、今しばらく続きます。

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

     さて、今回はパネルの方に手を入れます。第42回でパネル上にNSFormクラスのインスタンスを加えましたが、プログラムからこれにアクセスできないと、これに情報を表示できません。そこでこのアドレスを格納するインスタンス変数を実装し、nibファイルで接続しておくことにします。InfoPanel.nibでは、File’s OwnerはInfoPanelControllerクラスでした。そこで、InfoPanelController.hを開いて、次の様にインスタンス変数を加えてください。

    @interface InfoPanelController : NSWindowController {
        IBOutlet NSForm *infoForm;
    }

     ところで、今までは、こういう時は次の様に書いていました。

    IBOutlet id infoForm;

     idは任意のオブジェクト型へのポインタです。このように書けば、infoFormはどんなオブジェクトを指しても良いことになります。その代わり、当然、ビルド時に型のチェックは行われません。一方、今回の様な書き方をすると、infoFormはNSFormクラスのオブジェクトしか指せなくなりますが、ビルド時に型のチェックを行ってくれます。一長一短がありますので、状況や好みに応じて使い分けてください。今回はどちらでも良かったのですが、あえて、今までと違う書き方をしてみました。
     それでは、変更したInfoPanelController.hを保存しましょう。そして、InfoPanel.nibに反映させてください。やり方は何度も書きましたので、簡単に書きます。nibファイルウィンドウでFile’s Ownerを選び、Classesタブを選んでクラスの一覧に切り替え、InfoPanelControllerクラスが選ばれている状態でClassesメニューを選び、そこからRead InfoPanelController.hを選びます。
     これでInfoPanel.nibはFile’s OwnerがinfoFormを持つことを知りましたので、これをパネル上のNSFormクラスのインスタンスに接続しましょう(この辺りの方法は第9回でやっています)。Instancesタブを選んでインスタンスの一覧に戻してください。そして、controlキーを押したままFile’s Ownerをマウスで選択し、そのままドラッグしてパネルのデザインウィンドウ上のNSFormまで持っていって離してください(fig.01)。今回はそんなことは無いと思いますが、もしデザインウィンドウで選択しにくいような時には、インスタンスの一覧をOutlineモードに切り替えて、その中で接続先を指定することもできます(fig.02)。InfoパネルがConnectionsに切り替わりますので、OutletsのinfoFormを選んでConnectボタンを押してください(fig.03)。実を言えば、ヘッダーファイルで型をidにせずに、今回のようにきちんとクラスまで書くと、この時にも型のチェックをしてくれます。これで接続ができましたので、保存してください。

    [fig.01] contorlキーを押したまま、File’s OwnerからNSFormまでドラッグ
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/44/images/fig01.jpg

    [fig.02] Outlineモードで接続先を指定することもできる
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/44/images/fig02.gif

    [fig.03] infoFormを選んで、Connectボタンを押す
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/44/images/fig03.gif

     これでNSFormクラスのインスタンスにアクセスできるようになりましたので、これに情報を表示するメソッドを実装しましょう。
    InfoPanelController.mに次のメソッドを加えてください。

    - (void)updateImageInfo{
        ImageInfo *imageInfo;
        NSSize imageSize;
    
        imageInfo = [ ImageInfo sharedImageInfo];
        imageSize = [ imageInfo imageSize];
        [ [ infoForm cellAtIndex:0] setFloatValue:imageSize.width];
        [ [ infoForm cellAtIndex:1] setFloatValue:imageSize.height];
    }
    


     このメソッドの中で使っているImageInfoクラスをInfoPanelController.mは知りませんので、#import “InfoPanelController.h”の次に、次の一行を加えてください。

    #import "ImageInfo.h"

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

    imageInfo = [ ImageInfo sharedImageInfo];

     みんなで共通で使うImageInfoクラスのインスタンスのアドレスを教えてもらっています。ImageInfoクラスは前回実装しましたから、覚えていますよね。

    imageSize = [ imageInfo imageSize];

     imageInfoにimageSizeメッセージを投げて、イメージのサイズを教えてもらいます。この値を表示すれば良いわけです。

    [ infoForm cellAtIndex:0]

     infoFormにcellAtIndex:メッセージを投げて、0番目のフィールドを教えてもらっています。返って来るのはNSFormCellクラスのインスタンスです。
    CodeWarriorでPowerPlantを使っていた方は、どのフィールドであるかを指定するのに、indexではなくてTagを使いたいと思うかもしれないですね。それもできます。その場合は、indexOfCellWithTag:で、まずTagに対するindexを教えてもらい、それを指定します。Tagはもちろん、InterfaceBuilderで設定できます。

    [ [ infoForm cellAtIndex:0] setFloatValue:imageSize.width];

     0番目のNSFormCellクラスのインスタンスに対して、横幅の値をセットしています。

    [ [ infoForm cellAtIndex:1] setFloatValue:imageSize.height];

     やってることは一つ前といっしょですね。1番目のフィールドに縦幅をセットしています。
     これでこのメソッドを実行すれば、パネルにイメージの横幅と縦幅を表示することができるようになりました。この続きは次回です。

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

     先日(つか前回のこいつの原稿を書いていたまさにその時の出来事だったんだが)71になるウチの母親が自転車に乗っていて高校生の自転車と衝突、右上腕骨を骨折してただいま要介護の状態なんである。
     いや別に身内の不幸を書いて同情を集めたいわけではなくて(お見舞いの品などは拒みませんが)、つまりそれ以来、ワタシは炊事洗濯掃除など所謂「火事」……ぢゃない「家事」というものを一通りこなしつつ仕事をしているわけなんである。
     もともと母親と同居を始める前10年ほど一人暮らしをしていたし、こう見えてなかなかのキチントさん(笑)なので別段苦でもないんだが、それは措き、こうなってつくづく思ったのは家事というのは「段取り」であるということである。

     例えば本日の朝の行動、6:30に準備開始、主菜のシャケの切り身を冷凍庫から取り出して解凍プレートの上に置き、カーテンを開け母親をベッドから出して座椅子を準備(こいつが昼間のままの位置にあるとベッドに寝たとき背が邪魔でTVが見えないのだ)し、これまた冷凍のハッシュドポテトをオーブントースターに入れて(油が出るのでクッキング・シートを天板の上に敷く)15分にセット。今日は燃えるゴミの日なので生ゴミを含めて一袋にまとめ階下のゴミ置き場に持って行く。ポストから朝刊を取って戻り、解凍できたシャケをロースターに入れて弱火に。昨夜の残りの野菜スープも火にかけ、頂き物のニシンのコブ巻きを2切れ、切り分ける。スープが沸騰したら冷蔵庫から残りご飯を出して電子レンジであたため、食器棚から皿、茶碗、小鉢など出して食材を盛りつける。箸が使えない母親のためにシャケの身を食べやすくほぐし、スプーンとフォークとともに出す。食い終わったら食器を軽くすすいで食器洗い機(これには実に助かってる)に入れ、スイッチ・オン。母親にクスリを飲ませる。野菜スープが終わったので、NHK BS 7:30からの「てるてる家族」を観ながらタマネギとキャベツ、セロリとピーマンを切り、缶詰のトマトとブイヨンと共に圧力鍋へ。強火にして錘の回転を待ちつつ新聞を読む。錘が回転を始めたら弱火にして10分、また新聞。キッチン・タイマーが鳴ったら火を止めて10分蒸らす。朝刊を読み終わり、圧力を抜いてスープを普通の大鍋に移して圧力鍋を洗う。スープのために出たタマネギの皮などの生ゴミを新聞紙に包んで生ゴミ入れに入れ(こうしておくと悪臭が少ない)、コーヒー豆を挽いてコーヒーメイカーのスイッチを入れてベランダの鉢植えに水をやる。そうこうするうちに食器洗い機が止まるので皿や茶碗を棚に戻し、落ちたコーヒーを魔法瓶に移し、サーバーなどは昼の食器と一緒に洗うべく食器洗い機に入れて仕事場に入るとほぼ9時、仕事開始である。

    思い出しながら書いてみるとなかなかスゴいことをやっているようだが、実はそれほどたいしたことではない。シャケを解凍しているウチにゴミを出しに行き朝刊を取ってくるのも野菜スープを作りながら新聞を読むのもコーヒーメーカーがポコポコ言ってる時に鉢植えに水をやるのもごく普通のことである。そうでしょ?
     ところがプログラムを書く段になると、稀にどうしてもこれが出来ないヒトがいるんだよね。昔風の、スタートとエンドがあるフローチャートで書けるようなプログラムってのはつまり、「シャケの解凍」が終わるまで「ゴミ出しと朝刊取り」に行けず、鍋を火にかければずっと火の前でたたずんでいることになる。
     もちろん前後関係が重要な段取りもある。タマネギやキャベツを切る前に圧力鍋を火にかけたら危ないし、コーヒーメーカーのスイッチを入れてから豆を挽く馬鹿はいない。問題はそういう後先に意味や依存関係がある動きと相互に独立した動きとの見極めなんだよね。その見極めも含めての段取り能力こそプログラマの腕だ、と。
     最近話題の「片付けられないヒト」ってのはこういう段取り能力が圧倒的に劣っているんだろう。オレの過去の経験に照らしても、出来るプログラマに部屋が片付けられないヤツは……あれ? なんでゾロゾロといるんだろう(笑)。
    (2004_03_26)

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

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

     こんにちは、高橋真人です。早速続きを始めます。
     ようやく今回のプログラムのキモの部分になるわけですが、コードとしては極めて単純で以下のようになっています。

    tc->WriteTo(ofs);

     tcはTextContentクラスのインスタンスを指すポインタで、ofsは書き出し用のストリームでしたね。
     表面上は単純に見えても内部にそれなりの仕組みが潜んでいる場合が多いのがオブジェクト指向のコードです。もちろんこのコードも単純な関数の呼び出しではありません。
     以前に説明しましたようにWriteTo関数は純粋仮想関数となっています。ですから実装ファイル(TextContent.cpp)中には実装コードは存在しません。そしてその代わりにサブクラスで必ず関数の実装が必要となるわけでしたね。クラス定義ファイルであるTextContent.hにおいてvirtualという修飾語が付けられていることが仮想関数を意味していたのを思い出しましょう。このvirtualがあることで、関数の呼び出しはポインタが指しているインスタンスのメンバ関数の呼び出しにすり替えられるということでした。
     今回の例でtcが指しているのはDosTextクラスのインスタンスですから、実際に呼び出されているのはDosText::WriteTo()です。(「::」という記号はスコープ解決演算子と呼ばれる演算子ですが、ここではこの関数がDosTextクラスに所属していることを表していると理解しておいてください)
     ところで、「インスタンスがDosTextクラスのものなのだから、そのクラスの実装が呼ばれて当たり前ではないか」と疑問を持たれる方もおいでかもしれません。
     そう思われるのも無理はありません。ですが「ポインタが指しているインスタンスのクラスは実行時にならないと分からない」ということがここでの重要なポイントです。今回のコードでは最初からインスタンスのクラスがDosTextだということが分かり切っているためにその辺がよく見えませんが、次回の連載でプログラムに少し手を加えて、生成するインスタンスが実行時に切り替わるように改造してみることにします。
     では、DosTextクラスにおけるWriteToの定義を見てみましょう。

    void DosText::WriteTo(ofstream& outStream)
    {
         for (size_t i = 0; i < content.size(); ++i) {
              outStream << content[i].c_str() << DOS;
         }
    }
    


     関数の中身は単純なforループ文です。ループしながらvectorの要素を一つずつ巡回しています。(このように配列の要素を順に巡っていく処理をする場合、最近ではイテレータという仕組みがよく使われます。今どきのプログラミングではポビュラーな仕組みなので、これについてもいずれ説明します)
     ストリームに書き出しているのは、content[i]が保持している文字列、そして改行コードになります。
     前回の説明で抜け落ちていたのですが、getline(ifs, buffer);という関数呼び出しでは、改行コードはbufferの中に格納されません。ですので、ファイルから読み込む段階で切り落とされていた改行文字を、しかるべき改行コードに変換したということになります。
     こんなところで、長きにわたった今回のサンプルプログラムの説明を終わります。(漏れている部分もあるかもしれませんが)
     結局のところ、WriteTo()での改行コードをDOS、つまりCR+LFにするというだけのためにわざわざポリモーフィズムを使ったというのが今回のプログラムです。この程度の理由でわざわざポリモーフィズムを使うことは普通はあり得ないでしょう。ポリモーフィズムの仕組みが見えやすいように、実行内容を極めて単純にすることこそがプログラムの目的ですので、その辺の不自然さに関しては目をつぶってください(笑)。
     全体的に中身の薄い単純なプログラムではあったわけですが、それでもC++という言語の特有の表現がいくつもあって、理解しづらいものだったかもしれません(これでもかなりシンプルな書き方をしてあるんですが)。
     プログラム全体を通して見てみると、main.cppの冒頭で定義しているdefine文、現在はDOSとなっていますが、これをMACまたはUNIXと書き換えることでtc->WriteTo()によって呼び出される関数が切り替わるという相関関係をご理解いただけば今回の不自然なサンプルプログラムの目的は達したということになります。

    ニュース・解説

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

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

    【開発環境】

    Apple社のDeveloperサイト内に「Reference Library」サイトが新設されました。ここからApple社が発表した最新のドキュメント、リリースノート、テクニカルノート、サンプルコード、Q&Aを一括で参照することができます。ページの右上にポップアップメニューがありますので、それを選択して各カテゴリーへダイレクトに移動します。Developerサイトの構成については、Mac OS Xへの切り替え以来、紆余曲折、色々と変遷があったのですが、ようやく分かりやすい体系にまとまったもようです。WWDCにおいて、サイト担当者が参加者にアンケートを取りプロトタイプを見せて意見を聞いていたのを思い出します(意見を述べるとTシャツがもらえた)。これでもう少し日本語訳ドキュメントが増えれば嬉しいのですが...(笑)。

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

    Apple社から「Xgrid Technology Preview 2」が発表されました。前回のPreview 1にはまともなドキュメントが付属していませんでしたが、今回は「Xgrid Guide」という30ページ程度のPDFドキュメントが付いています。アップロードされたばかりなので、前回のバージョンと比較してどのような点が変更、強化されているのかはまだ未確認です。ドキュメントをざっと見た感じでは、まだまだ情報不足のような気がしますが、正式版の登場が待ち遠しいテクノロジーであることは間違いありません。

    http://www.apple.com/acg/xgrid/

    また、Apple社から「Spoken Interface」というUniversal Accessに関連した新テクノロジーが発表されています。以下のサイトに幾つかの図版と共に技術についての詳しい内容が解説されていますので、興味があるかたは参照してください。音声認識にしろ、音声による操作のナビゲートにしろ、とにかく日本語対応でなければ我々にとっては宝の持ち腐れです。その点についてApple社は、もう少しよ〜く考えて欲しいと思います。

    http://www.apple.com/accessibility/spokeninterface/

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

    前回から3月26日の期間中、Apple社のDeveloperサイトにはドキュメントが多数登録されました。やっとこさ販売が開始されたXserve G5の仕様ドキュメントも含まれています。また、Quartz 2Dについてのカテゴリー別リファレンスが大量に登録されましたので、ここではそれらをすべてまとめて参照できるサイトを記載しておきます。

    「Xserve G5 Developer Note」(PDFあり)

    http://developer.apple.com/documentation/Hardware/Developer_Notes/Servers/XserveG5/index.html

    「New Getting Started Documents」

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

    「Introduction to Adding Behavior to a Cocoa Program」

    http://developer.apple.com/documentation/Cocoa/Conceptual/AddingBehaviorToCocoa/index.html

    「Cocoa Text & Fonts」

    http://developer.apple.com/documentation/Cocoa/TextFonts-date.html

    「Data Browser Reference」(PDFあり)

    http://developer.apple.com/documentation/Carbon/Reference/databrow_reference/index.html

    「Displaying Data in a Data Browser」(PDFあり)

    http://developer.apple.com/documentation/Carbon/Conceptual/display_databrowser/index.html

    「Apple Human Interface Guidelines」(PDFあり)

    http://developer.apple.com/documentation/UserExperience/Conceptual/OSXHIGuidelines/index.html

    「Mac OS X Man Pages」(PDFあり)

    http://developer.apple.com/documentation/Darwin/Reference/ManPages/index.html

    「Menu Manager Reference」(PDFあり)

    http://developer.apple.com/documentation/Carbon/Reference/Menu_Manager/index.html

    「Quartz 2D Reference」(PDFあり)

    http://developer.apple.com/documentation/GraphicsImaging/Reference/CGAPI-date.html

    また、デベロッパ向けの読み物として以下の内容が登録されています。先ほど紹介したReference Libraryサイトの使い方についての解説です。

    「Making the Most of the ADC Reference Library」(読み物)

    http://developer.apple.com/referencelibrary/usingreflib.html

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

    QA1343 「Audio Unit Resizing」
    QA1198 「Rendezvous enforces the service type format in Panther」
    QA1344 「DDR SDRAM ICs for PowerBooks and iBooks that use Memory bus slewing」

    http://developer.apple.com/qa/indexes/whatsnew0.html

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

    前回から3月26日の期間中、Apple社のSample Codeサイトにはサンプルソースコードがひとつも登録されませんでした。う〜ん、ついにサンプル打ち止めか?
    http://developer.apple.com/samplecode/

    【デベロップメント SDK】

    前回から3月26日の期間中、Apple社のSDKサイトには「CoreAudio SDK v1.3.1」がひとつだけ登録されました。また10.3.3の登場に伴ない、ダーウィンの最新ソース7.3も登録されています。

    「CoreAudio SDK v1.3.1」

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

    「Darwin 7.3 Source Code」

    http://www.opensource.apple.com/darwinsource/

    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=モサ伝]第106号

    2004-03-23

    目次

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

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

     前回、NSFormをパネルの上に置いた時、項目が2つ以外の時はどうしたら良いのだろう?と、疑問を感じた方はいませんでしたでしょうか。今回は必要無いのですが、項目数の変更方法を書いておきます。まず、NSFormを選択します。すると、周りに8つの点が現れますから、この内の下の真ん中の点を、オプションキーを押しながらマウスで縦方向にドラッグします。これで、項目数を増減できます(fig.01)。なお、オプションキーを押さないと、フィールドの高さの変更になってしまいますので、ご注意ください。

    [fig.01] オプションキーを押しながらドラッグする
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/43/images/fig01.jpg

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

     TinyViewのInfo Panelには、メインウィンドウに表示されているイメージの横幅と縦幅を表示することにしました。そのためには、その値をもらって来なければなりません。今回は、その方法を考えます。
     必要なのはメインウィンドウのイメージのサイズだけですから、常に一組です。そこで、これを格納するクラスを作り、一つだけインスタンス化して共有し、あるドキュメントがメインウィンドウになったら、そこにイメージのサイズを書き込んでもらう、ということにします。こうすれば、そこの値は常にメインウィンドウのイメージのサイズになるはずです。では、そのクラスを作りましょう。名前はImageInfoにします。TinyViewのプロジェクトに、ImageInfo.mとImageInfo.hを加えてください。ファイルの生成方法は、今まで何度もやってきましたので、もう説明いたしません。今までの記事を参考にしてやってみてください。
     ImageInfo.hの実装は、次の様にしてください。

    #import <Cocoa/Cocoa.h>
    
    @interface ImageInfo : NSObject
    {
        NSSize imageSize;
    }
    + (id)sharedImageInfo;
    - (void)setImageSize:(NSSize)newSize;
    - (NSSize)imageSize;
    @end

     ImageInfo.mの実装は次の様にしてください。

    #import "ImageInfo.h"
    
    static id sharedImageInfo = nil;
    
    @implementation ImageInfo
    
    + (id)sharedImageInfo{
        if( !sharedImageInfo){
            sharedImageInfo = [ [ ImageInfo alloc] init];
        }
        return sharedImageInfo;
    }
    
    - (void)setImageSize:(NSSize)newSize{
        imageSize = newSize;
    }
    
    - (NSSize)imageSize{
        return imageSize;
    }
    
    @end
    


     実装はいたって簡単です。このクラスは、イメージのサイズを格納するインスタンス変数、imageSizeを持っています。ここに値をセットするメソッドがsetImageSize:、取り出すメソッドがimageSizeです。では、sharedImageInfoは何をやっているのでしょうか。
     sharedImageInfoは頭に+が付いていることから分かるように、クラスメソッドです。つまり、インスタンス化しなくてもそのまま使えます。実装を見て行きましょう。まず、static変数であるsharedImageInfoの値を調べ、それがnilだったら、ImageInfoクラスのインスタンスを生成し、初期化してstatic変数sharedImageInfoに格納しています。そしてその値を返しています。どこかで見たような構造ですね。これはAppController.mの中に実装したshowInfoPanel:と同じ手法です。インスタンスが生成されていない時は生成してそのポインタを返し、既に生成されていたらそのポインタを返す。常に同じ一つのインスタンスだけを使う仕組みです。ImageInfoクラスを使う人は、常にsharedImageInfoでインスタンスのポインタを教えてもらって使うことにします。こうすれば、自動的に一つのインスタンスだけを皆が使うようになります。
     ところで、static変数とは、C言語の仕様です。第19回で、Objective-CはC言語と混在できると書いたことを覚えていますでしょうか。実はObjective-Cは、一度C言語に展開されてからコンパイルリンクされるので、C言語と混在できるどころか、C言語の手法をそのまま使えるのです。
     それではMyDocument.mに、ImageInfoクラスのインスタンスに対してイメージの横幅と縦幅を格納する処理を加えましょう。次のメソッドを追加してください。

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

     windowDidBecomeMain:は、NSWindowクラスのDelegate Methodです。従って、リファレンスの説明はNSWindowクラスの方にあります。これを見ると、メインウィンドウになった時に呼び出されることが分かります。つまり、上記実装ではメインウィンドウになった時に、imageからsizeを取得し、その値をImageInfoクラスのインスタンスにセットしています。これが呼び出されるためには、MyDocumentがウィンドウのdelegateになっている必要がありますが、Cocoa Document-based Applicationでプロジェクトを生成した時には、これは最初から接続されています。一度InterfaceBuilderで確かめてみてください。
     では、これを実際にパネルに表示するのは次回です。

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

    メインオブジェクトを確保-その1

    今回からは、startApplication()内に記述されている各種初期化ルーチンの処理内容を見ていくことにします。最初にstartApplication()を再度掲載しておきます。

    void startApplication(void)
    {
        if( ! setupObject( MAX_OBJ ) )  // 使用する汎用オブジェクトを確保する
        {
            setupDrag();                // ドラッグ&ドロップ用ルーチン登録
            setupMenu();                // アプリケーションメニューの構築
            setupAppleEvent();          // アプリ起動とドキュメントオープン対応
            setupEventLoopTimer();      // イベントタイマールーチンの登録
            setupApplicationEvent();    // アプリケーション用イベントハンドラ登録
            RunApplicationEventLoop();  // メインイベントループの開始
        }
        else
            doErrAlert( 2 );      // オブジェクトが確保できない場合のエラー
    }


    初期化での最初の仕事は、アプリケーションで利用するメインオブジェクト(Object構造体)を指定個数だけ確保することです。
    この作業はsetupObject()で行われます。メイン構造体である「Object」は、MOSA.hにおいて以下のように定義されています。ここで確保されたObject構造体は、カタログウィンドウのDataBrowser Control(一覧表)へ画像ファイルがひとつ登録されるごとにひとつだけ消費されて行きます。

    typedef struct
    {
        Ptr               o_prev;    // リンクされた前方のObject構造体へのポインタ
        Ptr               o_next;    // リンクされた後方のObject構造体へのポインタ
        WindowRef         o_wref;    // オーナ(所有者)ウィンドウのWindowRef
        OSType            o_type;    // 登録された画像ファイルのタイプ
        FSSpec            o_fsc;     // 登録された画像ファイルのFSSpec(保存場所)
    
    } Object,*ObjectPtr,**ObjectHandle;
    


    構造体メンバーの詳細については機会ごとに解説するとして、とりあえず構造体を確保する処理を見てみましょう。MOSA.hにおいて「MAX_OBJ」は10000と定義されていますので、今回は10000個のObject構造体を確保します。Object構造体ひとつのサイズが88byteですので、トータルで約860Kbyteのメモリ領域を消費することになります。まあ、現状マシンのメモリ搭載量から考えれば微々たる容量でしょう(笑)。確保したメモリ領域の先頭アドレスと最終アドレスは、後々の処理のために外部変数のs_baseとs_bmaxに保存しておきます。
    setupObject()での処理は以下の通りです。

    ObjectPtr    s_base;    // 確保されたメモリ領域の先頭アドレス
    ObjectPtr    s_bmax;    // 確保されたメモリ領域の最終アドレス
    
    short setupObject( unsigned long max )
    {
        long    len;
        Ptr     pp;
    
        len=max*sizeof( Object );   // 確保すべきメモリブロックの総容量
        if( pp=NewPtrClear( len ) ) // メモリを確保してゼロで初期化
        {
            s_base=(ObjectPtr)pp;   // 先頭アドレスを保存
            s_bmax=s_base+max;      // 最終アドレスを保存
            return( 0 );
        }
        return( 1 );
    }
    


    私はToolBoxに慣れてしまっているので、メモリ領域を確保するためには、NewPtr()、NewPtrClear()、NewHandle()、NewHandleClear()などのAPIを使用しますが…

        if( pp=NewPtrClear( len  ) )

    の箇所を、

        if( pp=calloc( max,sizeof( Object ) ) )

    と記述しても、Mac OS Xでは内部的にまったく同じ処理が実行されていると思われます。処理における差異はないので、記述の違いは単純に好みや習慣の違いだけです。最近は、Apple社が提供しているサンプルソースコードでもNewPtr()の代わりにmalloc()が使われているのをよく見かけます(笑)。ちなみに、Mac OS 9の時代には、アプリケーションの途中でNewPtr()でメモリを確保すると、その領域のために(たった1byteでも)フラグメンテーション(メモリ領域の断片化)が発生し、その後に大容量メモリ領域を確保できなくなり痛い目に遭うことがよくありました。当時のMacintoshは搭載メモリ容量も少なかったので、メモリ領域の確保には神経質にならざるをえませんでした。

    こうしたフラグメンテーションの問題を避けるために、ToolBoxの各種オブジェクト(メニューやコントロール)を保持している構造体は、Handle(ハンドル)経由で確保されていました。Handleはメモリ領域の先頭アドレスを示すポインタです。Handle経由で確保されたメモリ領域は動的に移動させることが可能なので、こちらを利用しているかぎりはメモリ領域のフラグメンテーションを避けることができました。ところが、唯一の例外、そして問題児(笑)だったのが、ウィンドウをオープンする時に確保されるGrafPortやWindowRecordといった構造体でした。これらはNewPtr()で確保され、その先頭アドレスであるWindowPtr経由でアクセスする仕組みとなっていました。

    つまり、処理中タイミングの悪い箇所でウィンドウを作成すると、フラグメンテーションが発生しデータが読み込めなくなるバグの原因になったのです。そのため、アプリケーション起動時に先んじて必要最大個数のWindowRecordを確保しておき、ウィンドウ作成時にはそれを利用するような技も使っていました(今回と同様)。Mac OS Xからウィンドウやメモリのハンドリングの仕組みも変わり、そうした心配はほとんどありません。しかし「メモリ領域の確保と解放」の意識が希薄になっている今日この頃のプログラミング世界では、こうした仕組みが存在した「意義」を知っておくことも悪くはないでしょう。

    そんなわけで、次回はメモリに関係する問題点を継続して考えてみます。また、オブジェクト用のメモリ領域を自分自身で確保するのではなく、Frameworkの汎用APIをうまく用いる手法などについてもお話したいと思います。

    つづく

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

     今回はDirect Actionについて解説します。WebObjectsではセッション管理を自動的におこなってくれて便利ですが、かならずしも全てのWebアプリケーションでセッション管理が必要となるわけではありません。
     ショッピングサイトを構築するする場合などではユーザごとにショッピングカートの機能が必要になってきますが、セッション管理の仕組みを利用すればこのような機能は簡単に実現できます。ですが、ユーザごとの処理が不要なアプリケーションの場合はリクエストに応じてわざわざセッションを生成する必要はなく、必要のないものを生成してもリソースの無駄遣いになるだけです。
     そこでWebObjectsではセッションを使用しない処理もサポートしており、これがDirect Actionと呼ばれる機能です。もともとHTTPはセッションレスなプロトコルであるため、その上でセッションを管理するには工夫が必要になってくるわけですが、WebObjectsではデフォルトで自動的にセッション管理をおこなうため、セッションレスな処理をおこなうには逆に少し手間かもしれません。といっても基本的な決まりを覚えてしまえばさほど難しいことはなく、ゴリゴリとCGIプログラミングをやったことのある方ならこちらのほうが分かりやすいかもしれません。

     ではDirect Actionの使い方を具体的にみていきましょう。WOのコンポーネントでハイパーリンクやフォームを作成した場合、そのリクエストを処理するアクションメソッド(WebObjects BuilderのInspector上でactionアトリビュートにバインドするメソッド)をWOComponetのサブクラスに実装します。Direct Actionの場合も同様にリクエストを処理するメソッドを実装するのですが、実装するのはWODirectActionクラスのサブクラスになります。WebObjectsのプロジェクトを作成すると自動的にWODirectActionのサブクラスDirectActionが生成されますので、最初はこれを使えばよいでしょう。Direct Actionで呼び出すメソッドには命名規則があり、メソッド名はxxxActionのように”Action”を最後に付ける必要があります。例えば次のようなメソッドになります。
     ここで戻り値の型として指定しているWOActionResultsはWOComponentおよびWOResponseがimplementsしているinterfaceです。

         public WOActionResults testAction() {
             return pageWithName("Main");
         }
    


     次にこのメソッドのバインドのやり方ですが、actionアトリビュートは使用せずactionClassとdirectActionNameを用いて以下のように設定します。つまりこれでどのクラスのどのメソッドを呼び出すかを指定しているわけです。ここでdirectActionNameにはメソッド名から”Action”を外したものを指定しますので注意してください。WebObjects BuilderのInspectorは自動的に利用可能な適切な名前をバインド先の候補として表示してくれます。

         actionClass = "DirectAction";
         directActionName = "test";

     Direct Actionはハイパーリンクからもフォームからも呼び出すことができますが、フォームの場合はWOSubmitButtonではなくWOFromに対してバインドをおこなってください。このようにして用意したDirect Actionのメソッドは以下のような固定のURLで呼び出すことができます。

    http://<host>/cgi-bin/WebObjects/App.woa/wa/test

     バインド方法から説明しましたので、ちょっと分かりにくいかもしれませんがDirect Actionを呼び出すURLは固定です。ですのでスタティックなHTMLから呼び出すといった使い方もできますし、もちろんWebObjectsのアプリケーション内からWOHyperlinkやWOFormのようなDynamic Elementを用いて呼び出すこともできます。またURLが固定になるということはWebブラウザ上でブックマークすることもできます。
     testAction()を呼び出したURLにはメソッド名(からActionを外したもの)しか含まれていませんが、この場合はDirectActionクラスのメソッドが呼び出されます。独自に追加したクラス(WODirectActionのサブクラス)上のメソッドを呼び出す場合のURLは以下のようになり、URLにクラス名とメソッド名が両方含まれます。

    ■DirectAction用のクラス

    public class Test extends WODirectAction {
    
         public Test(WORequest aRequest) {
             super(aRequest);
         }
    
         public WOActionResults sampleAction() {
             return pageWithName("Main");
         }
    
    }

    ■TestクラスのsampleAction()を呼び出すURL
    …/cgi-bin/WebObjects/App.woa/wa/Test/sample

     またURLでメソッド名を省略した場合にはdefaultAction()が呼び出されます。URLが”…/cgi-bin/WebObjects/App.woa/wa”だけですとDirectActionクラスのdefaultAction()が、”…/cgi-bin/WebObjects/App.woa/wa/Test”だとTestクラスのdefaultAction()が呼び出されます。
     以上がDirectActionの呼び出し方に関する基本的なルールですが、WOのアプリケーション内からDirectActionを呼び出した場合以下のようなURLが自動的に生成され、セッションIDがパラメータとしてわたされます。

    …/App.woa/wa/test?wosid=TOfbDOyVpgAtTYKP7PX0Ww

     このパラメータにより、セッションで管理されたページからDirectActionを呼び出したときでも、DirectAction内で引き続きセッションにアクセスすることができます。このようにWOではDirectActionとセッションを込み合わせた処理をおこなうこともできます。
     では次回はDirectAction内でのパラメータのハンドリング方法について解説します。

    ニュース・解説

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

    ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    ┃Mac OS X/Server 10.3.3に対応するWebObjects 5.2.3がリリース
    ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    Mac OS X 10.3.3、そしてMac OS X Server 10.3.3へのアップデートが公開されたが、併せてWebObjects 5.2.3へのアップデートも行われた。ただし、「Applications Server Update for Mac OS X Server 10.3」として、JBoss、Tomcatのアップデートと一緒にWebObjects 5.2.3が公開されている。
    WebObjects 5.2.3は、Mac OS X/Server 10.3.3、Java2 1.4.2といったシステム環境での開発や稼働をサポートするバージョンである。他にバグフィクスなどが行われているが、動作環境を最新のものに対応するのがアップデートの大きな目的である。(なお、執筆時点では、Applications Server Update for Mac OS X Server 10.3についての文書が削除されていて参照はできなかった。)

    WebObjects: 5.2.3 Updateについて
    http://til.info.apple.co.jp/cgi-bin/artnum?id=107873
    http://docs.info.apple.com/jarticle.html?artnum=107873

    About the Applications Server Update for Mac OS X Server 10.3
    http://www.info.apple.com/kbnum/n107869

    ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    ┃Java 1.4.2 Update 1をデベロッパ向けに公開
    ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    Mac OS XのJava2 1.4.2について「Update 1」が近々公開されそうだ。ADCのサイトに、Update 1をADC会員向けに公開したことが公表された。2004年3月にはWindowsなど向けにJava2 1.4.2_04がリリースされており、JISコードの文字列の問題が解消されている。Update 1は順序的にはWindows版として公開されたものと同じものと考えられるため、早期にバグは修正される可能性もある。

    Java for Mac OS X
    http://developer.apple.com/java/index.html

    ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    ┃Cocoaのテキスト処理に関するドキュメントが公開
    ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    Cocoaのテキスト関連の解説ドキュメントがまとめて公開されている。新しい内容というわけではないが、現状のテキスト処理関連機能がまとまっているので、より学習しやすくなったとも言えるだろう。以下のテーマの文書が公開されているが、Strings、Text Editingなどのテキスト編集コンポーネント、ファイル入出力に関するText Input and Outputあたりは基礎的な内容がまとまっているので、必読の文書だろう。また、スタイル付きテキストの扱い方や、複雑なレイアウトをするための仕組みなどについても解説されている。

    ●公開された文書名
    Text Attributes、Rulers and Paragraph Styles、Text Editing、Text Layout、Text System Storage Layer、Font Handling、Text Input and Output、Text System Architecture、Characters and Glyphs、Font Panel、Spell Checking、Text Attachments、Text Fields、Text Input Management、Text Views、Strings、Text System User Interface Layer、Attributed Strings

    Cocoa Text & Fonts Documentation
    http://developer.apple.com/documentation/Cocoa/TextFonts-date.html

    ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    ┃Quartz 2Dのリファレンスが公開
    ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    Mac OS Xのグラフィックス機能であるQuartz 2D(Core Graphics)のリファレンスが公開された。関数や構造体、タイプ名などのリファレンスが、以下のテーマごとに文書化されて公開されている。いずれも、HTMLとPDFで公開されている。

    ●公開された文書名
    CGAffineTransform Reference、CGBitmapContext Reference、CGColor Reference、CGColorSpace Reference、CGContext Reference、CGDataConsumer Reference、CGDataProvider Reference、CGFont Reference、CGFunction Reference、CGGeometry Reference、CGGLContext Reference、CGImage Reference、CGPath Reference、CGPattern Reference、CGPDFArray Reference、CGPDFContext Reference、CGPDFDictionary Reference、CGPDFDocument Reference、CGPDFObject Reference、CGPDFPage Reference、CGPDFStream Reference、CGPDFString Reference、CGPSConverter Reference、CGShading Reference

    Quartz 2D Reference
    http://developer.apple.com/documentation/GraphicsImaging/Reference/CGAPI-date.html

    ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    ┃デバッグまで可能なPerlのプログラミング環境
    ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    Script DebuggerなどのAppleScript関連ツールを開発しているLate Night Softwareが、Mac OS Xで利用できるPerlの開発環境「Affrus 1.0」をリリースした。価格はダウンロード版が$99、CD-ROM版が$109となっている。キーワードをカラーで区別できるエディタでプログラミング作業ができるが、BBEditなどの外部エディタもサポートしている。そして、Perlのプログラムのデバッグができることが最大の特徴になるだろう。ステップ動作やブレークポイント、変数の値の参照などが可能である。Perlは5.6ないしは5.8対応となっている。コマンドライン機能も統合されており、標準入力や環境変数を割り当てての実行などができる。デモ版も用意されている。

    Affrus 1.0
    http://www.latenightsw.com/affrus/index.html

    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=モサ伝]第105号

    2004-03-16

    目次

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

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

     すいません。前回の説明に抜けがありました。AppController.hとAppController.mは、InfoPanelControllerクラスのことを知らないので、コンパイルするとエラーが一杯出たと思います。AppController.hの#import の次に、次の一行を加えて下さい。

    @class InfoPanelController;

     これでエラーは出なくなったはずですが、まだワーニングが出ます。AppController.mの#import “AppController.h”の次に、次の一行を加えて下さい。

    #import "InfoPanelController.h"

     これでワーニングも出なくなったはずです。

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

     前回の最後に、AppController.hをMainMenu.nibに各自で反映させてくださいと書きましたが、これはうまくできましたでしょうか。もう何度もやっていることですが、ざっくり手順を書いておきます。TinyViewのプロジェクトをXcode(またはProject Builder)で開いてください。MainMenu.nibをダブルクリックして、Interface Builderで開きます。nibファイルウィンドウでAppControllerを選んでから、Classesタブを選択してクラスの表示に変えます(fig.01)。Classesメニューから、Read AppController.hを選びます(fig.02)。これでヘッダが読込まれ、AppControllerクラスが更新されました。

    [fig.01] AppControllerを選んでから、Classesタブを選ぶ
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/42/images/fig01.jpg

    [fig.02] Read AppController.hを選ぶ
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/42/images/fig02.gif

     さて、これでAppControllerがshowInfoPanel:メソッドを実装していることを、nibファイルは知ることができました。さっそくメニューから「Show Info」を選んだら、これを呼び出すようにしましょう。controlキーを押したままEditメニューの「Show Info」をマウスで選択し、そのままドラッグしてAppControllerまで持っていって離してください(fig.03)。すると、InfoパネルがConnectionsに切り替わり、Target/Actionの一覧表示に切り替わりますので、showInfoPanel:を選んで、Connectボタンを押してください(fig.04)。
     これで、「Show Info」メニューを選ぶと、showInfoPanel:メソッドが呼び出されるようになりました。ついでにショートカットも指定しておきましょう。
     InfoパネルをAttributesに切り替えて、Key Equivalentに「i」を入れて下さい(fig.05)。これでコマンドキー+iでもパネルが開くようになったはずです。MainMenu.nibを保存してからXcodeに戻り、ビルドして実行させてみてください。TinyViewが起動したら、Editメニューから「Show Info」を選んでみましょう(fig.06)。空のパネルが開いたはずです(fig.07)。画像を開いてから、コマンドキー+iを押してみる等、色々と試してみてください。期待通りの動きをするはずです。

    [fig.03] メニューからAppControllerまでドラッグ
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/42/images/fig03.jpg

    [fig.04] showInfoPanel:を選んでConnectボタンを押す
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/42/images/fig04.gif

    [fig.05] コマンドキー+iを指定する
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/42/images/fig05.gif

    [fig.06] Show Infoメニューを選ぶ
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/42/images/fig06.gif

    [fig.07] パネルが開く
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/42/images/fig07.gif

     さて、画像の情報を表示するパネルですから、のっぺらのままにしておくわけにはいきませんね。ここに、画像の幅と高さを表示することにします。まずはパネルに表示する場所を作りましょう。
     InfoPanel.nibを開いてください。パネルの大きさを適当に調節し、パレットウィンドウからNSFormをドラッグ&ドロップしてください(fig.08)。これで2項目表示できるようになりましたので、それぞれのタイトルをwidthとheightに変更しましょう。フィールドをダブルクリックして選択してください(fig.09)。さらにタイトルをダブルクリックして、文字を変更できるようにします(fig.10)。タイトルをwidthとheightにしましょう(fig.11)。ついでにパネルのタイトルも変更しておきましょうか。パネルを選んでから、ToolsメニューのShow Infoを選び、Infoパネルを開いてください。Window TitleをInfo Panelに変更しましょう(fig.12)。
     さて、これで良いでしょうか。動作確認してみましょう。確認の方法は遥かな昔、第3回でやっていますが覚えていますでしょうか。FileメニューからTest Interfaceを選んでください。するとパネルが動作し、各項目が編集可能であることが分かります(fig.13)。表示するだけの項目なのに、これはまずいですね。
     Interface BuilderメニューのQuit Interface Builderを選んで、テストを終了させたら、NSFormを選んで、Infoパネルを開いてください(どちらもInfo Panelですね。分かりにくくて、すいません)。Editableにチェックが入っているので、これを外してください(fig.14)。もう一度テストしてみましょう。今度は編集できなくなっているはずです(fig.15)。これでデザインはOK、続きは次回です。

    [fig.08] NSFormをパネルにドラッグ&ドロップ
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/42/images/fig08.jpg

    [fig.09] フィールドをダブルクリックして選択する
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/42/images/fig09.gif

    [fig.10] タイトルをダブルクリックして文字を変更できるようにする
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/42/images/fig10.gif

    [fig.11] タイトルをwidthとheightにする
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/42/images/fig11.gif

    [fig.12] Window TitleをInfo Panelにする
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/42/images/fig12.gif

    [fig.13] 各項目に入力できてしまう
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/42/images/fig13.jpg

    [fig.14] NSFormのEditableのチェックを外す
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/42/images/fig14.gif

    [fig.15] 今度は各項目に入力できない
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/42/images/fig15.jpg

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

     前回アップルが主宰しているメーリングリストのことを書いたら早速数名日本人のヒトが参加してくれたようで嬉しい。今回はそっからのネタ。CocoaやObjective-C以前の、Cの常識を忘れちゃいけないというお話。

    くだんのメーリングリストに寄せられる疑問質問の類いをみていると目につくのが、初心者にありがちなのは「Objective-C」がCやC++と全く別の毛色の違う言語であるかのように考えちゃってるトコなんだよね。これは実際にあったQ&Aなんだけど、

    「Cのソースから呼ばれるCallBack関数をCocoaで書きたい、どうしたらいい?」

    ってのがあって、つまり言わんとしているトコロはクラシックのころにあったProcPtrみたいなのを使いたいってことなんだけど、訊いてる方はCからオブジェクトにアクセスするってところで壁にぶちあたってるし、答えてる方は「腰までCocoaまみれ」なので、「CallBackを呼ぶ側にターゲット(オブジェクト)とセレクタ(アクション)を渡すには……」なんてことを言い出すわけ。

     ちとソースに書いてみると、

    void useCallBackFunc(int (*callBack)()) {
    //中身は想像してください
    }
    


     というCallBackを使うCの関数があって、ここで例えば以下のクラスのメ
    ソッド「wantToBeCalled」を使いたいというハメになった。

    @interface   MyClass : NSObject {
    //インスタンス変数も想像してください
    }
    - (int) wantToBeCalled ;
    
    @end

     こういう場合どうしたらいいのか、とCocoaのメーリングリストに質問してきたわけね。なんかCocoaの(あるいはObjective-Cの特殊な仕様でこのwantToBeCalledの正しいアドレスをuseCallBackFunc()に渡す方法があるんぢゃないかと、質問者は思ったわけだ。さぁみなさんもちと考えてみて。

     答えは実に簡単である。C++でも同じことができるけど、上のMyClassのインプリメンテ−ションの前に次のような静的変数を定義し、MyClassの初期化の時にこの変数に「self」を入れておく。

    static id myClassInstance = nil;

     続いてこんな関数を宣言する(ヘッダーにextern宣言をするのを忘れない)。

    int callMethodOfMyClass() {
      if(myClassInstance != nil) {
         return [myClassInstance wantToBeCalled];
      }
      return -1; // error...
    }
    


     このMyClassというクラスのインスタンスがいくつも作られるような場合にはもう一段別の工夫がいるってことだけ注意して欲しいけど、強調したいのはこのちょっとしたテクニック、Objective-CでもC++でもない、Cの範疇の知識があれば思いつくはずだってこと。新しい言語や環境を前にすると、なんだかなんもかんも新しく憶えなくちゃならないような気がするもんだけど、実は違うんだよね。
    (2004_03_11)

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

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

     こんにちは、高橋真人です。さっそく続きを始めましょう。
     前回までで、読み込んだファイルの内容を保持するインスタンスが用意されるところまでを説明しました。続いての処理はファイルからのデータの読み込みになります。

    string buffer;
    while (getline(ifs, buffer)) {
         tc->content.push_back(buffer);
    }
    


     まず、ファイルの内容を1行ずつ読み込むためのバッファを用意しています。これはstringクラスの変数です。ANSI Cのライブラリでこのような処理をする場合、大方、以下のような形になります。

    char buffer[4069];
    while (fgets(buffer, sizeof(buffer), fp) != NULL) {
         /* 読み込んだ行データの処理 */
    }
    


     この場合、バッファとして用意するのはC文字列ですから、当然長さに制限があります。そのため、通常は「ほぼ1行が充分に納まる大きさ」のバッファを用意するわけですが、ごくたまに4095バイトをオーバーする行があったりすると、1行を2回(ないしはそれ以上)に分けて読み込むことになるため、余計な手間がかかることになります。
     ですが、C++においては上記のようなgetline()という関数とstringを組み合わせて使うことでそのような手間をかける必要がなくなります。まあ細かくは説明しませんが、要はこの場合、必要に応じてbufferが自動拡張してくれるというわけです。
     このようにしてストリーム経由でファイルから取得した行データは、tcが保持するvectorの「新しい要素として」追加されます。STLのvectorにおいて、push_back()という関数は、要素をコピーして格納するので、contentの中には次々とstringが追加されていくのだと理解してください。
     Cでこのような処理をする場合、行の長さに応じたメモリーの確保をして、それを配列に追加する、というような手順が必要で、さらにこの配列が用済みの段階で、確保しておいたメモリーを解放してやるという処理もやらねばなりません。対してstringクラスを使うと領域の解放も含めてクラスが面倒を見てくれるために手間はグッと少なくなります。
     ただ一つだけお断りしておきますが、getline()によって拡張されたstringの保持しているメモリ領域は必ずしも内容物の量にピッタリ合っているとは限りません。なので、もっとメモリーを適切に確保してやる必要がある場合にはもう少し手間をかけてやる必要があります。
     さて、いよいよ書き出しです。読み込みのときにifstreamというクラスを使ったように、書き出しの時にはofstreamというクラスを使用します。ANSI Cのfopen()関数にファイル名を書き出しモードで与える場合と同じく、ここでも新規に書き出し用のファイルが作成されて開かれます。
     ifstreamの時に説明したのと同様、ofstreamのコンストラクタがファイル作成に失敗するなり、ストリームのオープンに失敗するなりした場合、ofsの評価はゼロとなりますので、その場合にはabort()でプログラムを終了させます。
     こうして書き出し用のストリームの準備ができたら、あとはTextContentのWriteTo()関数にこのofsを渡してやることで書き出し処理に入ります。この部分こそが今回のサンプルプログラムでいちばん重要な部分となりますので、次回はその説明をいたしましょう。

    ニュース・解説

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

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

    【開発環境】

    WWDC2004における「学生奨学金制度」を紹介したサイトが登場しました。しかし、申し込み期限が2004年3月12日となっており(やたら早いぞ)受付はもう終了したようです。この学生奨学金制度に通れば、WWDC 2004への参加費用(US $1,595)が無料となります。ただし日本から参加する場合には旅費の負担が大きいので、そちらの方も何とかしないとWWDCへ参加する学生は増えないでしょう。旅費の何割かをサポートするような制度を準備できないでしょうか?>アップル社

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

    Metrowerks社のダウンロードサイトに「CodeWarrior Development Studio for Mac OS, v9.2 Update」(英語版)が登録されました。さっそくアップデートを実行し、いくつかの自作プロジェクトを再Makeしてみましたが、これといった問題には遭遇しませんでした。v9.1とMac OS X 10.3の環境で遭遇したAltiVec関連のFramework(vecLib)が正しくリンクされないと言う不都合は解消されていました。しかし、プロジェクトテンプレートを作成する時にリンクされているcrt1.oが正しく機能しない現象はそのままで、MacOS X Support/Libraries/Startup/mwcrt1.oの方に差し替えないとダメでした。ただし、こちらはCodeWarrior側の問題ではない可能性がありますので、何とも言えないところです。

    「CodeWarrior Development Studio for Mac OS, v9.2 Update」(英語版)

    http://www.metrowerks.com/MW/download/updates.asp?date_op=on+or+after&year=95&month=01&day=1&did=find&vers=CWMACOS9&submit=Select+%3E%3E

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

    前回から3月12日の期間中、Apple社のDeveloperサイトにはドキュメントがひとつも登録されませんでした。ただし、デベロッパ向けの読み物として以下の内容が登録されています。「Web Kit」を利用することで、アプリケーションのオンライン登録を実装しようという試みを紹介しています。そのためのCocoaプロジェクトの構築方法や、内部的に利用する CGI scriptのサンプルなども記述されています。

    「Using the Web Kit for Application Registration」(読み物)

    http://developer.apple.com/internet/webservices/webkitreg.html

    前回から3月12日の期間中、新規テクニカルノートは2つ登録されました。
    「HFS Plus Volume Format」は再録なのですが、Mac OS XでHFS Plus用に新たに追加された機能、ヘッダ、構造体などについての情報が盛り沢山です。TN2106の方については、先週の新居さんの解説をご参照ください。

    TN1150 「HFS Plus Volume Format」(日本語訳あり)
    TN2106 「Scripting Interface Guidelines」

    http://developer.apple.com/technotes/indexes/whatsnew0.html

    テクニカルQ&Aの方は2つ登録されました。「Developer Tools JBoss and Tomcat Do Not Start After Installing Java 1.4.2 Update」 は、題名のとおりの内容です(笑)。Apple社のJavaチームは不都合解消に向けて動いているようですね。

    QA1228「The Rendezvous Name is not the Rendezvous name」(日本語訳有り)
    QA1025「Developer Tools JBoss and Tomcat Do Not Start After Installing Java 1.4.2 Update」

    http://developer.apple.com/qa/indexes/whatsnew0.html

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

    前回から3月12日の期間中、Apple社のSample Codeサイトにはサンプルソースコードがひとつも登録されませんでした。4週連続登録ゼロ!どうしたサンプルソースコード?

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

    【デベロップメント SDK】

    前回から3月12日の期間中、Apple社のDeveloperサイトに登録されたデベロップメントSDKはありませんでしたが、ToolsサイトにCHUDの最新版 v3.5.0が登録されました。また、C、C++、Objective-CのヘッダファイルからHTMLドキュメントを自動生成するツール「HeaderDoc」が発表されています。

    「Computer Hardware Understanding Development Tools Ver.3.5.0」

    http://developer.apple.com/tools/performance/

    「HeaderDoc」

    http://developer.apple.com/darwin/projects/headerdoc/

    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=モサ伝]第104号

    2004-03-09

    目次

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

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

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

     前回まででパネルの準備はできました。ただし、何も表示されない空のパネルではありますが。次はこれを表示させるメニューを実装します。いつものように、Xcode(もしくはProjectBuilder)で、TinyViewのプロジェクトを開いてください。そして、MainMenu.nibをダブルクリックして、Interface Builderで開いて下さい。メニューバーが表示されますので、Editメニューをクリックして開いてください(fig.01)。この一番下にパネルを表示させるShow Infoというメニューを追加します(第39回で、Get Infoとすると書きましたが、Show Infoに変更します)。まずは、見やすくなるように区切りを入れましょう。パレットウィンドウからSeparatorをドラッグ&ドロップしてください(fig.02)。これで区切りが出来ましたので、その下にMenu Itemをドラッグ&ドロップします(fig.03)。Menu Itemが追加されたら、名前をダブルクリックして編集できるようにし、Show Infoに変更します(fig.04)。これで、メニューはできました。

    [fig.01] Editメニューを開く
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/41/images/fig01.gif

    [fig.02] Separatorをドラッグ&ドロップ
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/41/images/fig02.gif

    [fig.03] Menu Itemをドラッグ&ドロップ
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/41/images/fig03.gif

    [fig.04] Menu Itemの名前をShow Infoに変える
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/41/images/fig04.gif

     さて、このメニューでパネルを表示させるわけですが、これを行う処理がまだありません。これを実装しましょう。Cocoaでは、メニューを選択したり、ボタンをクリックした時に呼び出されるメソッドを、InterfaceBuilderで接続することにより、指定することができます。つまり、パネルを開くメソッドさえ実装してしまえば、それを呼び出したり、呼び出すように指定したりするコードを書く必要は無いということです。とても楽ちんですね。では、そのメソッドを実装してしまいましょう。場所は、同じMainmenu.nibに含まれている、AppControllerの中にします(fig.05)。

    [fig.05] メソッドを追加するAppController
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/41/images/fig05.jpg

     Xcodeに戻って、AppController.hを開いてください。そして、次の様にコードを書き加えてください。

    @interface AppController : NSObject
    {
    }
    - (IBAction)showInfoPanel:(id)sender;
    @end
    


     Interface BuilderでActionとして接続するメソッドは、上記の様に形が決められています。IBActionは、Interface Bulderがヘッダーを解析する時に使用するものです。Xcodeでコマンドキーを押しながらIBActionをダブルクリックしてみてください。コンパイル時にはdefineでvoidに置き換えられていることが分かります。型がvoidですから、このメソッドに返り値はありません。引数のsenderには、通常はこのメッセージを発行したオブジェクト自身のアドレスが入っています。こうすれば、必要に応じてメッセージの発行元に情報を問い合わせることができますので、引数で情報を渡す必要がありません。メソッドの形が決められていても困らないのは、この仕組みのおかげです。
     さらに、インスタンス変数infoPanelControllerを追加して、下記の様にしてください。

    @interface AppController : NSObject
    {
        InfoPanelController *infoPanelController;
    }
    - (IBAction)showInfoPanel:(id)sender;
    @end

     このインスタンス変数に関しては、メソッドの中身を実装する時に説明します。では、続けてAppController.mを開いてください。そして、次のコードを追加してください。

    - (IBAction)showInfoPanel:(id)sender {
        if( !infoPanelController){
            infoPanelController = [ [ InfoPanelController alloc] init];
        }
        [ infoPanelController showWindow:self];
    }

     infoPanelControllerがnilの時に限り、InfoPanelControllerクラスのインスタンスを生成し、そのアドレスをinfoPanelControllerに格納しています。こうしますと、infoPanelControllerがnilなのは最初の一度だけですから、一度インスタンスが生成されると、次からは生成を行わず、常に同じインスタンスを使うようにります。情報パネルはアプリに一つだけですから、この様な手法を取っています。そして、infoPanelControllerにshowWindow:というメッセージを送り、パネルを表示させています。
     さらに、次のメソッドを実装してください。

    - (void)dealloc {
        [ infoPanelController release];
        [ super dealloc];
    }

     deallocは今まで何度も出て来ましたが、ここではAppControllerが解放される時に、infoPanelControllerを解放するようにしています。
     それでは、一度ビルドしてエラーが無いことを確かめましょう。確かめたら、再びInterface Builderに戻ってください。AppController.hを変更したので、これをMainMenu.nibに反映させる必要があります。方法は第9回でやっていますので、各自でやってみてください。続きは次回です。

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

    ストレスなき初期化を望む!

    現状のシステム環境でアプリケーションが起動できることを確認したら、続いて本来の目的を達成するための準備作業に取りかかります。つまり「初期化」と呼ばれている作業に移るわけです。どんな対象物に対してどのような初期化が必要なのかは、アプリケーションの目的によって随分と異なります。起動時にアバウトダイアログをオープンし、そこにどんな初期化を実行しているのかを表示するアプリケーションがあります。Mac OS 9起動時のアイコンパレードのような感じですね。「そんなの表示している暇があったらさっさと起動してくれ!」と思うのは筆者だけでしょうか(笑)。

    例えば、筆者が使っているPhotoshop Elements 2.0の場合には、起動時に、プラグイン、カラーパレットやプロファイル、ブラシやペンのパターンデータ、フォント、ヘルプドキュメント、環境設定などの読み込みと初期化を行っていることが分かります。Elementsには、初期化過程で最新の環境に不足しているリソースを見つけると、自動でAdobeサイトに接続して必要なリソースをダウンロードする機能まで実装されています。結局、初期化の時間が長いということは、そのアプリケーションの機能が複雑で肥大化しているという証拠のひとつなのですが、まあ、単純なアプリケーションでも初期化のやり方が下手だと、やはりユーザは待たされてストレスがたまる原因となります。

    では、サンプルアプリケーションでこの初期化を実行しているstartApplication()ルーチンを見てみましょう。

    void startApplication(void)
    {
        if( ! setupObject( MAX_OBJ ) )  // 使用する汎用オブジェクトを確保する
        {
            setupDrag();                // ドラッグ&ドロップ用ルーチン登録
            setupMenu();                // アプリケーションメニューの構築
            setupAppleEvent();          // アプリ起動とドキュメントオープン対応
            setupEventLoopTimer();      // イベントタイマールーチンの登録
            setupApplicationEvent();    // アプリケーション用イベントハンドラ登録
            RunApplicationEventLoop();  // メインイベントループの開始
        }
        else
            doErrAlert( 2 );            // オブジェクトが確保できない場合のエラー
    }
    


    何らかの問題が発生し初期化に失敗した場合には、システム環境不的確の時と同様に「XXXのためにアプリケーションが起動できません!」等のエラーメッセージを表示して起動を中止するのが普通です。startApplication()では、アプリケーションで使う汎用オブジェクトが指定個数(MAX_OBJ=10000)確保できない場合に限り、エラーを表示して起動を中止します。Mac OS 9の時代では、メモリ管理をしっかりしないと後々大きな問題が起こる可能性がありましたが、Mac OS Xでは、よほど大きなメモリ領域を確保しようとしなければ、メモリ不足に対して神経質になる必要はありません。また、小さなメモリ領域の確保であれば、それは確実に成功すると判断し処理を先に進めても大丈夫でしょう(落ちないようにしておけば)。詳細なエラーシステム構築に労力をつぎ込む人もいますが、そうした手間は報われないのが現実です。「過ぎたるは猶及ばざるが如し」はプログラミングの世界でも生きています。

    メニューの構築や、先んじて準備しておくべきウィンドウ(例えば機能パレット用フローティングウィンドウなど)の作成については、アプリケーションを外側から眺めただけでも、初期化でどんなことをしているのかはおおよそ見当がつきます。しかし、利用する機能によっては、それに依存する「暗黙の約束事」が存在しており、そうした種類の初期化については、FrameworkやAPIの使い方をきちんと勉強していないと、にっちもさっちも行かない状態に陥ります。

    例えば、QuickTimeにはv1.0のころからEnterMovies()とExitMovies()という2つのAPIが存在します。アプリケーション起動時(もしくは機能の必要時)に、EnterMovies()を実行しておかないと、Movieコントローラで映像(Movieファイル)を再生するような処理は動きません(QuickTimeがインストールされていてもです)。EnterMovies()は、Movie再生に関連する機能を使うことをQuickTimeに知らせます。そうすると、QuickTimeがそれらの機能のための「初期化」を実行するわけです。逆に、ExitMovies()を呼べば、その機能のために確保されていた作業用メモリやリソースなどが解放されます。

    メモリ使用量にシビアであったMac OS 9のころなら理解できますが、QuickTime 6.5とMac OS Xの時代になってもまだこのAPIが生き残っているのはちょっと驚きです(笑)。以下は、筆者が作成したMovie再生用アプリケーションの初期化部分です。律儀に処理を抜ける時にExitMovies()を呼んでいますが、アプリケーション終了時にはすべての使用メモリは解放されるので、実際には呼んでも呼ばなくても同じ結果となります。

    void main(void)
    {
        WindowRef    wptr1;
    
        EnterMovies();                  // Movie関連の機能を使えるようにする
        SetMenuBar( GetNewMBar( 128 ) );
        setUpAppCarbonEvent();
        RunApplicationEventLoop();      // メインイベントループ開始
        if( wptr1=FrontWindow() )       // 終了時にすべてのウィンドウを閉じる
        {
            while( wptr1 )
            {
                DisposeWindow( wptr1 );
                wptr1=GetNextWindow( wptr1 );
            }
        }
        ExitMovies();                  // Movie関連の機能の使用を停止する
        ExitToShell();
    }
    


    このサンプルは「MoviePlay_4.0_QT6.sit」というデータ名で以下のサイトに登録されています。main()からEnterMovies()を取り外して動作確認をしてみてください。

    http://www.ottimo.co.jp/library/index.html

    前回も言及しましたが、昔のMacintosh環境でアプリケーションを開発している時には、こうした「暗黙の約束事」が非常に多くて苦労させられました。
    Mac OS XとCarbon環境になり、随分とそうした制約の呪縛から解放されたのも事実です。しかし、まだ幾つものダークサイドが存在しており、システムの勉強を怠っていると引き込まれて脱出不可能になりますので、くれぐれも注意してください(笑)。次回は、startApplication()内に記述されている各種初期化ルーチンを順次見ていくことにします。

    つづく

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

     前回はWebObjectsでのエンコーディング処理について解説しましたが、今回はその続編です。前回解説した方法だけでは対応しきれない場合がありますので今回はその解説をします。

    プログラムの実行時にExceptionが発生した場合、WebObjectsはデフォルトのエラー画面を自動的に生成して、Exceptionの理由やstack traceを表示します。開発中はこれはこれで便利なのですが、独自のエラー画面を表示させることも可能です。このときエラー画面の生成は通常のリクエスト-レスポンスの処理とは違った流れで処理がおこなわれるため、エンコーディング処理をどのようにおこなうかが問題になってきます。

    まずエラー画面のカスタマイズ方法を説明しておきますと、Exceptionが発生した場合にはWOApplicationのhandleException()が呼び出されます。そこでこのメソッドを以下のサンプルのようにオーバーライドして、独自に用意したエラー画面用コンポーネント(サンプルではExceptionPage)からレスポンスを生成するようにすれば、独自のエラー画面を表示させることができます。

    ・エラー画面カスタマイズ例

         public WOResponse handleException(Exception anException,
                                           WOContext aContext) {
             WOComponent page = pageWithName("ExceptionPage", aContext);
             return page.generateResponse();
         }
    


     実際にこのExceptionが発生してエラー画面の表示がおこなわれた場合のレスポンス生成処理は、以下のように通常とは異なった流れになります。通常はApplicationとSessionのappendToResponse()が呼び出されますが、Exception発生時には呼び出されず、ApplicationのhandleException()からエラー画面コンポーネントのappendToResponse()が呼び出されます。

    ・通常の場合

         ApplicationのappendToResponse()
           -> SessionのappendToResponse()
                -> コンポーネントのappendToResponse()


    ・Exceptionが発生した場合

         ApplicationのhandleException()
           -> エラー画面コンポーネントのappendToResponse()

     よって前回紹介したようにApplicationのappendToResponse()をオーバーライドする方法では、Exception発生時にオーバーライドしたメソッドが呼び出されないので対応できないことになります。ではどうすれば対応できるかですが、お手軽な方法としては前回紹介したWOMessage.setDefaultEncoding()を利用してデフォルトのエンコーディングを指定しておくという方法があります。ただしこれではHTTPのヘッダーでContent-Typeが指定できないため、ブラウザに送信したレスポンスデータのエンコーディング名を知らせることができません。*1そこでエラー画面のコンポーネントでもappendToResponse()が呼び出されることに着目して、コンポーネント内でエンコーディング処理をおこなう方法が考えられます。つまりApplicationで実装したappendToResponse()をそのままコンポーネントにも実装するわけです。この方法ですとHTTPヘッダーへのアクセスも可能になり、Content-Typeの指定にも対応できます。

    このようにしてエラー画面でのエンコーディング処理に対応することができますが、ようするにレスポンスデータに対して適切なエンコーディング処理がおこなえればよいわけです。またException発生時以外にもWebObjectsが処理するエラー画面がありますので、エラー発生時に呼び出されるWOApplicationの主なメソッドと、それらがどのような場合によびだされるかを紹介しておきます。

    ・handlePageRestorationErrorInContext(WOContext aContext)
    WOComponentのインスタンスがリストアできなかった場合、Webブラウザのバックボタンを何度も実行したときに発生します。

    ・handleSessionRestorationErrorInContext(WOContext aContext)
    セッションインスタンスがリストアできなかった場合、セッションがタイムアウトしたときに発生します。

    さらに、Direct Actionを使用したときにもリクエスト-レスポンス処理の流れが異なってきますので対応が必要になりますが、原理的にはエラー発生時と同様にレスポンスデータに対して適切なエンコーディング処理がおこなえればよいわけです。Direct Actionについてはまだこの連載で取り上げていませんでしたので、次回詳しく解説したいと思います。

    さてここで少し話題を変えまして、Panther Serverでの運用につてフォローしておきたいと思います。WebObjects 5.2.2でPanther Serverへの対応がおこなわれ、詳細については以下のTILに記載されていますが、Panther ServerでWebObjectsの運用をおこなうのに必要な設定方法に関する情報が追加されています。

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

     まずwotaskdの起動スクリプトを編集してコメントアウトされているwotaskdの起動命令を有効にする必要があります。次にApache用のアダプターを使用する場合にはApacheの設定ファイル(/etc/httpd/httpd.conf)を編集してアダプターの設定ファイルをIncludeする必要があります。
     JaguarのころはWebObjectsの運用環境をインストールすればこれらの処理は自動的におこなわれていましたが、PantherになってOS本体にWebObjectsも含まれるようになった反面、このような設定が必要になりました。サーバ管理で簡単に設定できるようになれば便利なのですが、この設定方法を知らないと苦労すると思いますのでご注意ください。

    *1 HMTLでエンコーディング名を指定できないことはないのですが、話が長くなるのでここではこれ以上立ち入らないことにします。詳しくはHTTPやHTMLの仕様を調べてみてください。

    ニュース・解説

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

    ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    ┃FM-TechがファイルメーカーProのセミナーを開催
    ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    ジェネコムとバルーンヘルプが主催する「FM-Tech」がファイルメーカーProの講習会を開催する。初歩から実務で生かせるレベルまでを解説する「ファイルメーカーPro 基礎習得」は受講料が55,000円となっており、2日間にかけて行われる。また、より高いレベルの技術者を目指す「ファイルメーカーPro 中級」と、Webアプリケーションを作成する技術を習得する「ファイルメーカーPro Webパブリッシング1」も開催され、いずれも受講料は60,000円となっている。日程は別表の通りだが、東京や大阪だけでなく各地で開催される。場所などはFM-TechのWebサイトで確認してもらいたい。

    ◎ファイルメーカーPro 基礎習得
     名古屋:2004年3月18日-19日
     東京 :2004年3月18日-19日
     北九州:2004年4月 8日- 9日
     大阪 :2004年4月13日-14日
     札幌 :2004年5月18日-19日

    ◎ファイルメーカーPro 中級
     大阪 :2004年4月20日-21日

    ◎ファイルメーカーPro Webパブリッシング1
     東京 :2004年3月25日-26日
     大阪 :2004年4月15日-16日

    FM-Tech
    http://www.fmtech.jp/

    ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    ┃ヘッダからドキュメントを生成するツールの最新版がリリース
    ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    Appleは、C、C++、Objective-Cのヘッダファイルから、HTML形式のドキュメントを自動的に生成するツール「HeaderDoc」のVer.8のβ版をリリースした。ライセンスはAPSLとなっておりソースコードも公開されている。このツールは、AppleのWebサイトでのAPIリファレンス作成にも使われているもので、Perlで記述されたツールである。

    HeaderDoc
    http://developer.apple.com/darwin/projects/headerdoc/

    ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    ┃スクリプトのインターフェス策定ガイドライン
    ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    AppleScriptのインタフェースを設計に対するガイドラインを記載した文書が公開されている。AppleScriptではコマンドやプロパティなどを定義し、ユーザは辞書を見ながらプログラムを行う。こうしたスクリプト作成のキーワードなどを定義するのは開発者側の仕事になるが、コマンドよりもむしろオブジェクトをきちんと定義するといった方向性が与えられている。ユーザが実際に処理したものは、アプリケーション内のオブジェクトであり、オブジェクトをどのように設計し、そしてプロパティやメソッドとしてのコマンドに展開するのかといった設計がポイントになるだろう。名前の付け方のルールなども示されている。スクリプト対応アプリケーション開発者は必読の文書だ。

    TechNote 2106: Scripting Interface Guideline.
    http://developer.apple.com/technotes/tn2002/tn2106.html

    ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    ┃AWT/SwingとCocoa-Javaの混在は避けるべき
    ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    JavaネイティブのGUIレイヤであるAWTやSwingと、Cocoa-Javaが同時に使えるのかというQに対する答えが掲載されている。AWTやSwingで作られたアプリケーションからCocoa-Javaを呼び出すのはやめた方がいいとしており、Mac OS Xのネイティブな機能を呼び出すにはJNIを使うべきであるとしている。

    Technical Q&A: Mixing AWT/Swing and Cocoa Java
    http://developer.apple.com/qa/qa2001/qa1342.html

    ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    ┃Javaを知らなくても受講できるWebObjectsのセミナー
    ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    テクニカルピットは、倉橋浩一氏によるWebObjectsの講習会「JavaなしWebObjectsセミナー」を2004年4月21〜23日に開催する。受講料は40,000円。
    Javaの知識がないような開発者や利用者に向けて、WebObjectsを使ったデータベース処理を伴うWebアプリケーションを開発する方法を解説する。ファイルメーカーPro開発者やWebデザイナーなどを対象にした内容となっている。データベースの概念から、部品を組み合わせてページを作る方法などを講習する。自身の機材を持ち込んでの受講が可能であるが、機材をレンタルして利用する事もできる。

    テクニカルピット:WebObjectsのページ
    http://www.techpit.co.jp/WO/

    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=モサ伝]第103号

    2004-03-02

    目次

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

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

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

     前回はパネルのnibファイルを作りました。これを表示させて用いるには、これをロードして管理するクラスが必要となります。これを作成しましょう。Xcode(もしくはInterfaceBuilder)で、TinyViewのプロジェクトを開いて下さい。そして、「ファイル」メニューから「新規ファイル…」を選んで下さい。すると「アシスタント」パネルが開き、どんなファイルを作るのか聞いてきます。作るのはウィンドウを管理するプログラムですから、NSWindowControllerを継承したクラスにすることにしましょう。「Objective-C NSWindowController subclass」を選んで、「次へ」ボタンを押します(fig.01)。するとファイル名を指定するパネルになりますので、「InfoPanelController.m」というファイル名にして「完了」ボタンを押してください(fig.02)。これで「InfoPanelController.h」と「InfoPanelController.m」というファイルが生成され、TinyViewのプロジェクトに組み込まれたはずです(fig.03)。

    [fig.01]「Objective-C NSWindowController subclass」を選択する
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/40/images/fig01.gif

    [fig.02]「InfoPanelController.m」というファイル名にする
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/40/images/fig02.gif

    [fig.03]ファイルが生成され、プロジェクトに組み込まれる
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/40/images/fig03.gif

     それでは、コードを実装して行きます。InfoPanelController.mの中身を見て下さい。コメントを除くと、次の様になっています。

    #import "InfoPanelController.h"
    
    @implementation InfoPanelController
    
    @end

     第28回でNSViewを継承したクラスのファイルを生成した時と違って、随分とシンプルです。と、言うより空っぽですね。ここで、NSWindowControllerクラスのリファレンスを見てみましょう。Method Typesの中に、Initializing NSWindowControllersという項目があります。ここに並んでいるのは、指定イニシャライザですから、NSWindowControllerクラスをインスタンス化したら、この中のどれかを使って初期化しなければなりません。InfoPanelControllerクラスもNSWindowControllerを継承しているのでこれはいっしょですが、ロードするnibファイルがInfoPanel.nibと決まっていますので、これは決め打ちにできます。そこで、次の様に初期化を行うメソッドを実装します。

    @implementation InfoPanelController
    
    - (id)init {
        self = [ super initWithWindowNibName:@"InfoPanel"];
        return self;
    }
    
    @end

     スーパークラスにinitWithWindowNibName:メッセージを送って初期化しています。ロードするnibファイル名はInfoPanelです。
     リファレンスを読めば分かりますが、こうやって初期化すると、File’s Ownerは自分自身になりますので、これをnibファイルに反映させておきます。新しく作成したクラスをnibファイルに反映させる方法は第29回で説明していますが、ざっとおさらいしておきます。Interface BuilderでInfoPanel.nibを開いてください。開いたら、一度Xcodeに戻って、InfoPanelController.hをnibファイルウィンドウにドラッグ&ドロップしてください(fig.04)。これでInfoPanel.nibでInfoPanelControllerクラスを使えるようになりましたので、File’s Ownerをこれに切り替えます。File’s Ownerを選んでからToolsメニューのShow Infoを選び、Info Panelを表示させ、これをCustom Classの選択画面に切り替えてください(fig.05)。NSObjectが選択されているはずですので、一覧の中からInfoPanelControllerを探して、選択をこれに換えます(fig.06)。これで、File’s OwnerはInfoPanelControllerクラスになりました。

    [fig.04]InfoPanelController.hをドラッグ&ドロップ
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/40/images/fig04.gif

    [fig.05]File’s OwnerのCustom Classを表示する
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/40/images/fig05.gif

    [fig.06]Fil’s OwnerのCustom ClassをInfoPanelControllerにする
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/40/images/fig06.gif

     次にFile’s OwnerのConnectionを見てみましょう。Info PanelをConnectionに切り替えてみてください。Outletにwindowというインスタンス変数が見えます(fig.07)。これはNSWindowControllerが管理するウィンドウ指すインスタンス変数です。つまり、ここに値が入っていないと、どのウィンドウを管理すれば良いのか分からないことになります。そこで、これをPanelに接続します。controlキーを押したままFile’s Ownerをマウスで選択し、そのままドラッグしてPanelまで持っていって離して下さい(fig.08)。Info PanelでOutletのwindowを選択し、connectボタンを押してください(fig.09)。これでInfoPanelControllerはPanelを管理するようになりました。

    [fig.07]Outletにwindowというインスタンス変数がある
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/40/images/fig07.gif

    [fig.08]controlキーを押したまま、File’s OwnerからPanelまでドラッグ
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/40/images/fig08.gif

    [fig.09]connectボタンを押して接続する
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/40/images/fig09.gif

     実を言えば、このConnectionは良く忘れます。「まったく動作しない。おかしいな。」と思ったら、ソースだけでなく、正しくConnectionが張られているのかを確かめることをおすすめします。それでは、続きは次回です。

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

     ガラリと話が変わるが今回はアップルが主催しているメーリング・リストの話。これを読んでるヒトにはアップルとデベロッパー契約を結んでいるヒトも多かろうと思うが、年間500ドルのセレクト・コースについてくるDTSへの質問インシデントは年間で2件である。まずこれが多いか少ないか。
     誰でもそうだろうとは断言できないが、オレなど年に2件しか訊けないとなるとどうしても構えてしまう。貧乏性というのか、契約の更改が10月だとすると(って実際オレのデベロッパ契約の更改時期は10月なんだけどさ)、11月とか12月……いや5,6月くらいまでは「そのウチもっと重大な質問がワイて出て来るんではないか、今使ってしまうのはもったいないんぢゃないか」などと思ってしまうんだよね。
     しかもそうやって構えるせいか、オレの質問は俄然DTSのヒトビトにとっても厄介なモノになる傾向まで帯びてしまう。
     例えば昨年インシデントを使った2件の質問のウチ、1件はまだ調査中(一度だけ「まだ忘れてません。調べています」というメールが来たきりもう3ヶ月経つが……ホントに忘れてないよね?)、もう1件は回答自体は完璧だったけど「CarbonならできるんですがCocoaではできません」というオレには役立たずなものだったのだ(笑)。
     と、言ってあんまり敷居を低くしてしまうと(つか、インシデントを大判振る舞いしてしまうと)、言わずもがなみたいなレベルの低い質問にスタッフが忙殺されてしまうという懸念もある。いや、現在でも実はそのテの「質問に答えることよりもその正しい答えを相手に理解させることの方が難しい」質問ばかりが多くて、例のオレの質問を抱えたスタッフも、ココロのどこかで「ああ、フジモトのあの件について調べねば」と思いつつ、調査の時間が取れないでいるのかも知れない。

     自分が内向的なニンゲンだとは思わないが、プログラミングという仕事自体はトコトン内向きな作業である。視野を広く頭を柔軟に先入観に捕われず……と心がけていても、時としてワケの分かんない思い込みに捕われたり、知っているはずのことに思いいたらず苦吟したりする。そんなとき、他人の視点はとってもありがたい。
     そこでアップルのメーリングリストである。以下のURLにアクセスして頂ければわかるがテーマ別にかなりの数のパブリック・メーリング・リストが運営されている。

    http://www.lists.apple.com/mailman/listinfo

     現在オレが参加しているのは「cocoa-dev : Discussions regarding native Mac OS X application development using Cocoa frameworks.」と「xcode-users : Community supported Xcode help list」の2つ。この2つだけで週平均600〜700通の投稿がある。
     多過ぎる? 別に全部を読む必要はない。「何についての投稿なのか」わかるようなタイトルをつけるというマナーは割と定着しているので、興味のない話題は飛ばしてしまえる。もうすこし過去ログを簡単に検索できたらいいなとは思うが、投稿数に関していえば逆にこのくらい活発でなければ、自分の質問に答えてもらえるという期待値も下がってしまう……。
     もちろんオレとてネーティブの連中のようにスラスラと英語が読めるわけではないので、日本語で情報交換できる同じような場があればいいなと思いもするのだが、昨年末からこの2つのメーリング・リストで見かけた日本人らしい名前はオレの他に一人だけ、という現状ではアップルに「日本語のMLも作ってよ」とは言えないしなぁ。
     ……昨年のMOSA湘南イベントの時のアンケートによれば「今後使って行きたい開発環境」のトップはCocoaだったんだが、そういう情報交換って必要なくなっているのかしら? 月250円だかで参加できるニフティのWEBフォーラムで開設している「Macプログラミングの部屋」も閑古鳥が鳴いている。それとももしかして活況を呈している日本語のそういう場が既にあってオレが知らないだけなのか?
    (2004_02_24)

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

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

     こんにちは、高橋真人です。早速、続きです。
     さて、前回の冒頭に掲げたコードを再度見てみましょう。

    TextContent *tc;
    if (strcmp(RETURN_CHAR, MAC) == 0) {
         tc = new MacText;
    }
    else if (strcmp(RETURN_CHAR, UNIX) == 0) {
         tc = new UnixText;
    }
    else {
         tc = new DosText;
    }

     TextContentというクラスについて前回は説明したわけですが、肝心のインスタンスがまだ生成されていませんでしたね。インスタンスは、すぐあとに続く条件判断のコードの中で生成されています。ここではRETURN_CHARというシンボルの定義が何であるかによって、TextContentを指すポインタに、TextContentクラスそのもののインスタンスではなく、TextContentのサブクラスのインスタンスを生成してからポインタに代入する、という仕組みになっています。
     RETURN_CHARの定義は、main.cppの先頭で行われています。本来ならば、ユーザーに「改行コードは何にする?」と尋ねるとか、環境設定の設定値を読み込むなどといった形にするべきなのですが、あくまでコードを単純にするために今回のコードでは決め打ちにしてあります。
     で、とりあえず今はDOSということになっていますから、条件判断の結果DosText(というTextContentのサブクラス)のインスタンスが生成され、tc(TextContentを指すポインタ)に格納されます。
     以前にも解説したオブジェクト指向の技術の中でも重要なポリモーフィズムですが、この仕組みのキモがまさにここにあります。tcという変数が、ポインタであることに注意してください。なぜ、tcはポインタなのでしょうか。
     Javaでは、オブジェクトはすべて参照ベースで保持することになっています。Cのイメージでとらえれば、構造体をポインタで指しているようなものです。それに対してC++では、あるクラスのインスタンスを直接変数とするも可能です。
     今回の例で言えば、

    TextContent  tc;

    となります。ポインタを示すアスタリスクがないことに注意してください。
     もっとも、前回説明したように、TextContentはそもそも抽象クラスですから、このような宣言の仕方はできないのですが、まあ、メンバ関数のWriteTo()を純粋仮想関数でなくする(後述)と、このような書き方も可能となります。さらに残りの部分も修正して、以下のようなコードにしてみます。

    // main.cpp の TextContent のインスタンス、tc の宣言以降を掲載
    TextContent tc;
    if (strcmp(RETURN_CHAR, MAC) == 0) {
         MacText mt;
         tc = mt;
    }
    else if (strcmp(RETURN_CHAR, UNIX) == 0) {
         UnixText ut;
         tc = ut;
    }
    else {
         DosText dt;
         tc = dt;
    }
    
    string buffer;
    while (getline(ifs, buffer)) {
         tc.content.push_back(buffer);
    }
    
    string outputFile(homeDir + "/Desktop/test_out.txt");
    ofstream ofs(outputFile.c_str());
    if (not ofs) {
         abort();
    }
    
    tc.WriteTo(ofs);
    
    return 0;
    


     TextContent.hのWriteTo関数の部分は以下のようにします。

    virtual void        WriteTo(ofstream& outStream)
    {
         cerr << "TextContent: Don't call me! n";
    }
    


     これは、万が一この関数が呼ばれてしまったら、stderrに「呼び出すな」というメッセージを出すということです。
     実行してみると、結果は予想通り、

    TextContent: Don't call me!

    と標準エラーに出力され、出力ファイルには何も書き出されません。
     なぜ、このようになってしまうかと言えば、DosTextクラスのインスタンスのdtをtcに代入した時点で、サブクラスの派生要素が切り落とされて、インスタンスがTextContentのインスタンスになってしまったからです。
     前回と今回にわたって見てきたように、ポリモーフィズムを期待してコーディングする場合、C++では注意すべき点がいくつかありますので、C++でコーディングする予定の人は覚えておきましょう。

    ニュース・解説

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

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

    【開発環境】

    「アップルデベロッパブリーフィング &QuickTimeモバイルコンテンツセミナー」というMacintoshデベロッパ向けのアップル社の催しが、2004年3月11日(木)に東京国際フォーラムで開催されるようです。昔々のJDCを思い出しますね(笑)。MOSAとしてもこの機に何か企画を立案し実現したいところです。もし何らかの企画が実現すれば、事務局の方からメンバーの方々へ連絡が入ると思いますのでよろしくお願い致します。

    http://www.apple.co.jp/hotnews/2004/0311devbrief.html

    それから、いよいよWWDC 2004の事前参加登録が始まりました。場所はサンフランシスコ、会期は6月28日からです。それにしても、やたらに早い募集開始です。日本からのツアーもそのうち紹介されると思われます。$300の早期割引($1,595が$1,295になる)は4月30日までとなっていますので(こちらも早すぎないか?)、登録される方は機会を逃さぬよう注意してください。まだ何が起こるかわかりませんから、いくらなんでも今から事前登録するの少し勇気が必要です(笑)。加えて、ADCのセレクトメンバーの方は、WWDC 2004の参加登録とメンバーリニューアルを同時に行うと、Apple社のハードウェアを20%割引で購入できるチケットが2つ付いてきます。ひよっとすると、通常は1つのところが2つになると言う意味なのかもしれません(表記が分かりにくい...)。
    とにかく、お見逃しなく!

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

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

    前回から2月27日の期間中、Apple社のDeveloperサイトにはドキュメントがひとつも登録されませんでした。ただし、デベロッパ向けの読み物として以下の内容が登録されています。

    「Open Standards Support in Mac OS X and Xcode」(読み物)

    http://developer.apple.com/business/macmarket/brightech.html

    前回から2月27日の期間中、新規テクニカルノートはひとつ登録されました。
    前回も紹介した「Handling Audio Unit Events」の再登録です。何か内容に訂正があったと思われますので、参考にされている方は再度チェックしてください。

    TN2104 「Handling Audio Unit Events」(前回から再録)

    テクニカルQ&Aの方は5つ登録されました。「Mixing AWT/Swing and Cocoa Java」には、「AWT/Swing javaプロセスからCocoaのJavaクラスを呼ぶことは、だいたいはうまく行くが推薦はしない」と記されています。ちゃんとJNI(Java Native Interface)経由で呼びなさいと言うことだそうです。

    QA1263 「HTTPS Proxy Settings and Java Applets」(日本語訳あり)
    QA1342 「Mixing AWT/Swing and Cocoa Java」
    QA1037 「CGBitmapContextCreate Supported Color Spaces」
    QA1275 「Make sure your PPD Plugin calls ppdCloseCompiledPPDFromTicket」
    QA1325 「Creating an OpenGL texture from an NSView」

    http://developer.apple.com/qa/

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

    前回から2月27日の期間中、Apple社のSample Codeサイトにはサンプルソースコードがひとつも登録されませんでした。ちょっと寂しい状態が続いております(涙)。

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

    【デベロップメント SDK】

    前回から2月27日の期間中、Apple社のDeveloperサイトに登録されたデベロップメントSDKは「Bluetooth SDK 1.4.1」と「Bluetooth SDK 1.5」です。1.4.1の方がMac OS X 10.2(Jaguar)用で、1.5の方がMac OS X 10.3(Panther)用となっています。前回も同様なアップデートがあったのですが、あっという間にバージョンが更新されました。

    「Bluetooth SDK 1.4.1」
    「Bluetooth SDK 1.5」

    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.