MOSA Multi-OS Software Artists

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

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

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

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

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

    2004-02-24

    目次

    • MOSA Developer News 100号記念プレゼント当選者発表
    • Cocoaでいこう! Macらしく  第39回  Yoshiki(DreamField)
    • 小池邦人の「Carbon API 徒然草」
    • 「Behind the WebObjects」  第14回  田畑 英和
    • ニュース・解説
    • MOSAからのお知らせ

      ★★ MOSA会員限定100号記念プレゼント抽選結果発表! ★★

     この度はWWDC 2003 Sessions DVD-ROMセットプレゼントへ沢山のご応募、誠に有り難うございました!
     2月19日に矢野会長立ち会いの元行われました厳正なる抽選の結果、DVD-ROMセットは横浜市の★★様・和光市の★★様のお二人に、そして以下の20名様がAppleCollection製品及びAppleTシャツに当選されました! ご本人には別途事務局より、当選のお知らせメールを差し上げます。

    ★★★ web掲載ではお名前は割愛します ★★★

    今後ともモサ伝をご支援の程、よろしくお願い致します。

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

     良くあるMacのアプリのパターンとして、補助的なウィンドウが開き、その中には現在アクティブになっているウィンドウに関する情報が表示されるというものがあります。今までは一つのドキュメントに対して一つのウィンドウを開くだけという構造になっていましたから、ウィンドウ間の連携は必要ありませんでした。ですが、この様なアプリはそうはいきません。今回から数回にかけて、この様なアプリの実装方法の一例を説明したいと思います。

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

     Cocoaの開発環境は、この順番に作らないと駄目、ということはあまりありません。そこで今回は一つの試みとして、思いつくままに実装していってみようと思います。
     まずは、どんな物を作るのか考えてみましょう。開いている画像の情報を表示する補助的なウィンドウを考えます。名前をInfoPanelとします。InfoPanelは、Editメニューの中のGet Infoを選ぶと開きます。InfoPanelはTinyViewに一つだけで、そこに表示されるのはアクティブなウィンドウの画像の情報であるとします。そして、アクティブなウィンドウを切り替えるたびに、InfoPanelの内容もそれに応じて変化します。良くあるパターンですね。それでは、順番に実装して行きましょう。

     補助的なウィンドウを表示するのですから、まずはこれを作ってしまいましょう。補助的なウィンドウはNSPanelを使うこととし、これをどのnibファイルに入れるのか考えます。画像の情報を表示するのですから、MyDocument.nibに入れれば、とても楽が出来るはずです。何故なら、File’s Ownerが画像を管理しているMyDocumentクラスのインスタンスですし、画像を表示しているウィンドウも含んでいますから、Interface Builderで直接コネクトして情報を得られるはずだからです。でも残念ながらこれは出来ません。何故なら、InfoPanelはアプリケーションに一つでないといけないのに、MyDocument.nibは画像を開くたびにロードされてしまうからです。
     それではMainMenu.nibはどうでしょうか。MainMenu.nibは最初に一度しかロードされませんから、これに入れることは可能です。でも、Cocoaのアプリでは、通常これは行いません。何故なら、MainMenu.nibに物を入れれば入れるほど起動が遅くなりますし、InfoPanelを使わない人にとっては、必要も無いのに余計なメモリを食ってしまうからです。通常、この様なオブジェクトは別のnibファイルに入れておき、必要になった時に初めてロードするようにします。

     では、InfoPanel用のnibファイルを作りましょう。最初にXcode(もしくはProject Builder)で、TinyViewのプロジェクトを開いておいて下さい。これは、Interface Builderで新規に作るnibファイルを、後で簡単にプロジェクトに加えられるようにするためです。
     次に、Interface Builderを起動してください。Starting Pointというパネルが開きますので、Emptyを選んでNewボタンを押します(fig.01)。すると、File’s OwnerとFirst Responderしか無いnibファイルウィンドウが開きます(fig.02)。パネルを作りましょう。パレットウィンドウからパネルを選んで、適当な所にドラッグ&ドロップして下さい(fig.03)。
     するとパネルのデザインウィンドウが開き、同時にnibファイルウィンドウにもパネルが現われます(fig04)。このままパネルの中身をデザインすることもできますが、それは後回しにして、まずは保存してしまいましょう。FileメニューからSaveを選んで下さい。ファイル名を入れるパネルが現れますので、InfoPanelという名前にします(fig.05)。
     Saveボタンを押すと、TinyViewプロジェクトに加えるかどうか聞いてきますので、TinyViewにチェックが入っているのを確認して、Addボタンを押してください(fig.06)。するとnibファイルがXcodeのプロジェクトに加えられます。おそらくResourcesの中に入っていませんので、ドラッグして入れて下さい(fig.07)。

    [fig.01]新規nibファイルの雛形を選ぶ
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/39/images/fig01.gif

    [fig.02]Emptyなnibファイルウィンドウが現れる
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/39/images/fig02.jpg

    [fig.03]パレットウィンドウからパネルを取り出し配置する
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/39/images/fig03.gif

    [fig.04]パネルが生成される
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/39/images/fig04.jpg

    [fig.05]ファイル名をInfoPanelにしてnewボタンを押す
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/39/images/fig05.jpg

    [fig.06]TinyViewにチェックが入っていることを確認してAddボタンを押す
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/39/images/fig06.jpg

    [fig.07]XcodeにInfoPanel.nibが組み込まれる
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/39/images/fig07.gif

     これでパネルのnibファイルは出来ました。続きは次回です。

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

    アプリ起動…我思う故に我あり

    Carbonアプリケーションでは、起動時に実行しなければいけない「約束事」が随分と減りました。ToolBoxでおなじみの(もう、そんなの知らない人も多いかもしれませんが…)Macintoshの各マネージャの初期化を実行する必要はありません。よって、InitGraf()、InitFonts()、InitWindows()、InitMenus()、InitDialogs()といった初期化のためのAPIは使用不可となりました。再度、今回のサンプルアプリケーションのmain()ルーチンを見てみることにします。

    int main( int argc, char* argv[] )
    {
        long    ver;
    
        if( ! Gestalt( gestaltSystemVersion,&ver ) )
        {
            if( ver >= 0x1020L )
                startApplication();
            else
                doErrAlert( 1 );
        }
        return( 0 );
    }
    


    まず最初に開発者が考慮すべきことは、現在のシステム環境で本アプリケーションが使用可能かどうかを判断することです。アプリケーションの実行を左右する環境要因には、システム環境とアプリケーション固有の環境(リソース、プラグインモジュール、環境設定ファイルな)の2種類があります。自分で用意しているリソースやモジュールが不足している場合には、新規に作成したりインターネット経由で自動ダウンロードさせるなど、いくつかの解決方法が考えられます。しかし、システム環境が原因(OSのバージョンが古いなど)の場合には、アプリケーション側では手の打ちようがありませんので、エラーメッセージなどを表示し、そのまま終了することになります。

    今回のmain()ルーチンでは、Gestalt() APIを利用して現在のMac OS Xのバージョンを調べ、それが10.2以上であれば起動可能と判断しstartApplication()へと処理を継続します。そうでない場合は、エラー表示ルーチンdoErrAlert()により「このアプリケーションはMac OS X 10.2以上でしか起動できません。」というエラーダイアログを表示しアプリケーションを終了させます。この環境チェック用API、何故かGestalt()と非常に「意味深」の名称がついていますが(笑)、これによりMacintoshシステムのあらゆる環境要因を調べることが可能です。

    Gestalt()の最初の引数には、調べたい対象を指示するためのパラメータ(定数)を代入します。すると、次の引数にバージョン番号などの固有情報が返されます。こうしたパラメータはすべてGestalt.hに記載されています。もし判断しなければいけない環境要因があれば、それがちゃんとGestalt.hに定義されているかどうかを調べます。例えば、システムにQuickTimeがインストールされているかどうかは、以下のように調べることができます。Mac OS XはQuickTimeのインストールが必須ですので、存在しているかどうかを調べる必要はありませんが、バージョンにより機能の違いがありますので、処理を切り替えるためにバージョン番号を調べるケースは多々あります。

        if( ! Gestalt( gestaltQuickTime,&qt ) )
        {
            ver=qt>>16;
            if( ver < 0x600 )
            {
                doErrAlert( 1 );
                ExitToShell();
            }
        }
    


    次の例では、MacintoshのCPUがAltivec(Velocity Engine)ユニットを搭載しているかどうかを調べています。現状だと、PowerPC G4とG5系のCPUを搭載したMacintoshが起動対象となります。ちなみに、ExitToShell()はアプリケーションを終了させるAPIです。

        if( ! Gestalt( gestaltPowerPCProcessorFeatures,&att ) )
        {
            chk=att&( 1<
    

    搭載CPUの種類をより詳しく調べることも可能です。その場合には、G3やG4といった大ざっぱな識別ではなく、7450、7447、750FX、970など、CPUの型番を得ることができます。ちなみに、Gestalt.hには以下のような定義もなされていたりしますが、はてさて、これは何を意味するのでしょうか(笑)。

    num {
      gestaltCPU486                 = 'i486',
      gestaltCPUPentium             = 'i586',
      gestaltCPUPentiumPro          = 'i5pr',
      gestaltCPUPentiumII           = 'i5ii',
      gestaltCPUX86                 = 'ixxx'
    };
    
    enum {
      gestaltX86VectorUnit          = 'x86v',
      gestaltX86VectorUnitNone      = 0,
      gestaltX86VectorUnitSSE2      = 4,
      gestaltX86VectorUnitSSE       = 3,
      gestaltX86VectorUnitMMX       = 2
    };
    


    しかし、状況によっては、環境の違いをGestalt()だけでは判断できない場合もあります。例えば、同じOSバージョンであってもFramework APIのバグフィックスの程度に差がある場合もあります。加えて、Gestalt()のパラメータの追加が間に合わない状況も考えられるでしょう。そうした場合には、各システムモジュールのバージョンを別途調べるなど、少々やっかいな処理が必要となります。以下が、Apple社が提示しているHIToolbox Frameworkの細かなバージョンの違いを調べるサンプルコードです。

    CFBundleRef            bundle;
    CFStringRefversion    Str = NULL;
    UInt32                 version = 0;
    
    bundle=CFBundleGetBundleWithIdentifier( CFSTR("com.apple.HIToolbox") );
    
    if( bundle != NULL )
        versionStr = CFBundleGetValueForInfoDictionaryKey( bundle,
                                           CFSTR("CFBundleShortVersionString") );
    if( versionStr != NULL && CFGetTypeID( versionStr ) == CFStringGetTypeID() )
    {
        int     major = 0, minor = 0, bugfix = 0;
        char    sz[20];
    
        CFStringGetCString( versionStr, sz, sizeof( sz ), kCFStringEncodingUTF8 );
        sscanf( sz, "%d.%d.%d", &major, &minor, &bugfix );
        version = ( major << 8 ) + ( minor << 4 ) + bugfix;
    }
    
    if( version >= 0x100 )  // これは例で現状バージョンとは関係ありません。
        // おおっ、ちゃんとバグが取れたHIToolboxだぜ!
    else
        // 残念、まだバグが取れていないHIToolboxだ(涙)

    Framework APIのバグが取れるのは嬉しいのですが、そうしたことがあまりにも頻繁に行われると、その判別と処理の切り分けだけで大仕事になります。よって、せっかく新機能のAPIのバグが取れたのに、旧バージョンを考慮するとそれが使えず、相変わらず古いAPIでの処理を継続しなければいけないといった悲しい現実に遭遇したりします。やはりバグは最初から存在しないのが一番ですね(笑)。次回は、startApplication()ルーチンへと解説を進めたいと思います。

    つづく

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

     ここしばらくD2Wの解説が続いてきましたが、今回は話題を変えて以前少し紹介した日本語エンコーディングの扱いについて詳しく解説したいと思います。

     WebObjectsを用いたシステムでは通常、Webブラウザ、データベース、アプリケーション本体のそれぞれでどのようなエンコーディングを用いているかを考慮し、相互にデータをやり取りするときのエンコーディング変換処理を必要に応じておこなっていかなければなりません。
     まずアプリケーション本体からみていきましょう。WebObjectsではVer5.0以降からはJavaのみがサポートされていますので、プログラムはJavaで開発します。Javaですので文字列の表現はUnicodeが標準で用いられます。次にデータベースですが、サポートされるエンコーディング形式はデータベースによって異なります。最近では主要なデータベースであればUnicodeをサポートしており、それに加えEUCやSJISがサポートされていたりします。
     ここでアプリケーション本体とデータベース間でのエンコーディング変換が必要になってくるのですが、WebObjects5.0以降ではリレーショナルデータベースとの接続は標準でJDBCに統一されています。そしてアプリケーション本体とデータベースとの間でのエンコーディング変換処理はJDBC側で処理がおこなわれることになっていますので、アプリケーション側ではデータベース側のエンコーディングを意識する必要がなく自動的に適切な処理がおこなわれます。
    ※もちろんJDBC内で適切な処理がおこなわれている場合ですが。

     最後にブラウザ側ですが、例えばブラウザ側ではSJISでデータを扱うとなると以下のようなエンコーディング変換が必要になってきます。

        アプリケーション(Unicode) <-> ブラウザ(SJIS)

     具体的にどのような処理が必要かといいますと、まずブラウザから送信されるSJISのリクエストデータをアプリケーションが受け取ったときにUnicodeに変換する必要があります。またアプリケーションで生成したレスポンスデータをブラウザに送信するさいにSJISに変換する必要があります。このようなエンコーディング変換処理が必要になってきますが、この変換処理は明示的にコーディングして対応しなければなりません。

    ではまずアプリケーションとブラウザ間のエンコーディング変換処理を説明する前に、WebObjectsにおけるリクエストの処理について説明しておきましょう。
     ハイパーリンクからのリクエストの場合はただ特定のURLを呼び出すだけですが、HTML Formが用いられた場合はブラウザからFormデータがリクエストデータとして送信されます。
     ブラウザから送信されたFormデータはあらかじめWebObjects Builderで設定しておいたバインドにしたがって適切な変数へとセットされます。ですので通常はリクエストデータのハンドリングを直接意識する必要はないのですが、それはWebObjectsのフレームワークが自動的に処理をおこなっていてくれるからです。このFormデータのハンドリングですが実際には次のメソッドで実行されています。

         public void takeValuesFromRequest(WORequest aRequest,
                                           WOContext aContext)

     このメソッドはWOApplication, WOSession, WOComponentの3つのクラスで実装されており、それぞれのインスタンスごとに実行され、引数のaRequestにはFormデータが含まれています。よってこのメソッドをオーバーライドすることにより、Formデータにアクセスできるようになります。
     以下のようにこのメソッドをオーバーライドすることでブラウザから送信されてきたFormデータを任意のエンコーディング(この場合はSJIS)からUnicodeへと変換することができます。Application.javaにこのメソッドをコーディングすることにより、すべてのFormデータの送信時に変換処理がおこなわれます。

         public void takeValuesFromRequest(WORequest aRequest,
                                           WOContext aContext){
             aRequest.setDefaultFormValueEncoding("SJIS");
    
             super.takeValuesFromRequest(aRequest, aContext);
         }

     これでブラウザ -> アプリケーションの変換は対応できました。後はアプリケーション -> ブラウザの対応になりますが、リクエストの生成処理は次のメソッドで実行され、このメソッドもWOApplication, WOSession, WOComponentの3つのクラスで実装されています。

         public void appendToResponse(WOResponse aResponse,
                                      WOContext aContext)
    


     引数aResponseがレスポンスデータなので、次のようにこのメソッドをオーバライドすることでレスポンスデータを任意のエンコーディング(この場合はSJIS)に変換することができます。また仕様上HTTPのヘッダーでContent-Typeによりエンコーディング名を指定する必要があるため、ここではWOResponseのsetHeader()メソッドを用いてContent-Typeの設定もおこなっています。これでブラウザに送信したレスポンスデータのエンコーディング名を知らせることができます。

         public void appendToResponse(WOResponse aResponse,
                                      WOContext aContext){
             aResponse.setContentEncoding("SJIS");
    
             super.appendToResponse(aResponse, aContext);
    
             aResponse.setHeader("text/html; charset=Shift_JIS",
                                 "Content-Type");
         }
    


     上記の方法ではリクエストとレスポンスでそれぞれエンコーディング名の指定をおこないましたが、WOMessageクラス(WOResponseとWORequestのスーパークラス)のstaticメソッドを以下のように用いればリクエストとレスポンスのエンコーディング名を一括して指定することもできます。

         WOMessage.setDefaultEncoding("SJIS");

     このようなコーディングをおこなえばアプリケーション本体とブラウザ間のエンコーディング変換にも対応することができます。ただしこれだけでは対応しきれない場合もありますので、それは次回に解説したいと思います。
     なおWebObjectsのAPIで用いるエンコーディング名ですが、Javaで使用することのできるエンコーディング名をそのまま用いることができます。Javaのエンコーディング処理についてはJDKのバージョンによって異なる場合がありますので、詳しくはJavaでの日本語処理に関する文献などを参照していただければと思います。

    ニュース・解説

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

    ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    ┃アップル、開発者向けのセミナーを日本で開催
    ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    アップルコンピュータは、「アップル デベロッパ ブリーフィング & QuickTime モバイル コンテンツ セミナー」として、開発者やQuickTimeコンテンツ制作者向けのセミナーを開催する。WWDCの日本版とまでは行かないとしても、Macの開発関連情報を国内で得る数少ない機会となる。
    2004年3月11日(木)の13:00〜19:30に、東京国際フォーラムを使って行われ、参加費は無料だ。G5に最適化するためのラボやXcodeでの開発に移行するラボも開催されるので、開発中の案件を持ち込んでチェックあるいはアドバイスをもらうことも可能としている。開発ビジネスやテクノロジーのアップデート、コンテンツ関連のセッションなどが用意されている。

    アップル デベロッパ ブリーフィング & QuickTime モバイル コンテンツ セミナー
    http://www.apple.co.jp/hotnews/2004/0311devbrief.html

    ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    ┃WWDC 2004の募集を開始
    ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    今年のWWDC(WorldWide Developers Conference)の募集が開始された。かねてよりのアナウンス通り、2004年6月28日から7月2日まで、サンフランシスコのモスコーニセンターで開催される。詳細なセッションについてはまだ公開されていないが、Application Technologies、Development Tools、Enterprise IT、Graphics and Media、Hardware Technologies、OS Foundations、QuickTime Digital Mediaといったカテゴリーで数多くのセッションが1週間にわたって開催される予定だ。なお、日本からのツアーについては現在はまだアナウンスはない。

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

    ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    ┃ファイルメーカーProの初級から実践までのセミナー
    ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    コンピュータワークスは、2004年の4月上旬に大阪でファイルメーカーProのセミナーを開催する。講師は鬼頭英嗣氏で、「エントリー編」は4月1〜2日、「リレーション編」は4月7日、「スクリプト編」は4月8〜9日に開催される。場所は大阪のEPSONスクエア御堂筋で、受講料はエントリー編とスクリプト編は41,000円、リレーション編は21,000円となっている。いずれのセミナーでも、ノートパソコンなどを持ち込んでの受講ができる。
    また、2004年3月19日には、同じく大阪のEPSONスクエア御堂筋で、「ファイルメーカーPro実例・実践セミナー」を開催する。具体的な事例に則したデータベース構築を行うことで、実践的な技術を身につけようというものである。受講料は20,000円(過去に同社のセミナーを受講した人は17,000円)である。

    コンピュータワークス
    http://www.computerworks.co.jp/

    ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    ┃NSViewからOpenGLのテクスチャを生成
    ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    NSViewの表示結果をOpenGLのテクスチャとして利用する方法を解説した文書が公開された。ビットマップ化してテクスチャとして利用する方法であるが、サンプルプログラムが掲載されているので、それを手がかりにすることもできるだろう。

    Technical Q&A: Creating an OpenGL texture from an NSView
    http://developer.apple.com/qa/qa2001/qa1325.html

    ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    ┃システムサウンドなどのサウンド関連文書が公開
    ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    警告音やユーザインタフェースでの効果音を出したいような場合に利用するAPIが紹介された文書が公開された。また、「サウンド」のシステム環境設定での警告音出力先とシステムサウンドの出力先の利用方法も解説されている。Mac OS X 10.3から利用できる機能も紹介されており、システムでのサウンド機能を改めてチェックしておく必要があるだろう。
    また、Audio Unitのイベントについての文書も掲載されている。Core Audioを使ったプログラミングにおいて必要となる知識である。

    Technical Note: The System Sound APIs for Mac OS X 10.2, 10.3 and later
    http://developer.apple.com/technotes/tn2002/tn2102.html
    Technical Note: Handling Audio Unit Events
    http://developer.apple.com/technotes/tn2002/tn2104.html

    ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    ┃Rendezvousに関する文書が公開
    ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    Technical Q&AにRendezvousに関する文書がいくつか公開されている。サービスタイプ名といった仕様の部分や、あるいは機能の利用の仕方などがまとめられている。ソフト開発者はもちろん、ネットワーク機能を知りたい人も要チェックだろう。

    QA1310 - Clearing the Rendezvous service cache
    http://developer.apple.com/qa/qa2001/qa1310.html
    QA1312 - Rendezvous service types used in Mac OS X
    http://developer.apple.com/qa/qa2001/qa1312.html
    QA1339 - The state of mDNSResponde
    http://developer.apple.com/qa/qa2001/qa1339.html
    QA1333 - Duplicate Rendezvous services while browsing
    http://developer.apple.com/qa/qa2001/qa1333.html
    QA1331 - Use empty string for Rendezvous domains
    http://developer.apple.com/qa/qa2001/qa1331.html

    ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    ┃Swingのルック&フィールを変更する方法
    ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    Mac OS Xで稼働させるSwingアプリケーションは、ルック&フィールにAquaを使うようになっている。その変更方法をまとめた文書が公開された。他のルック&フィールをデフォルトにしたい場合、コマンドラインからはシステムプロパティで指定する。アプリケーションではInfo.plistに設定を加える。また、Javaの設定そのものの変更方法も公開されており、稼働するすべてのSwingのルック&フィールを設定する方法も解説されている。

    QA1059: Setting the look-and-feel for Swing applications
    http://developer.apple.com/qa/qa2001/qa1059.html

    ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    ┃Mac OS X Server 10.3でのスパム対策を解説
    ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    デベロッパ向けのドキュメントで、Mac OS X Server 10.3で、メールのスパム除去を行う方法が紹介されている。Mac OS X Serverでメールサーバを運用する場合、通常はPostfixをMTAとして利用する。さらに、オープンソースで開発されているスパム除去ツールのSpamAssassinを使い、procmailの処理をメールの受け取りにかませることで、送られてきたメールのスパム判断を組み込むことができる。コマンド等での処理が必要だが、手順を細かく説明しているので、スパム対策を施したい管理者にとっては有益な情報になるだろう。

    Fighting Spam on Mac OS X Server
    http://developer.apple.com/server/fighting_spam.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=モサ伝]第101号

    2004-02-18

    目次

    • 藤本裕之のプログラミング夜話 #39
    • 高橋真人の「プログラミング指南」 第38回
    • ニュース・解説
    • MOSAからのお知らせ

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

     ついさっき,かなり以前にヒトに譲ってしまったルータのマニュアルをシュレッダにかけていた(オレは客先から来たコンフィデンシャルの書類とかも裏紙として使うので処分する時には全部シュレッダにかけることにしている。
    Fellows製パーソナル・シュレッダーFS5というのを使用)。
     ルータのメイカーのサイトからPDFをダウンロードして印刷したそれ,気がつけばなんとも懐かしい文書の裏に印刷されているではないか。1990年に港区のラフォーレ飯倉で開催された第2回『アップル・デベロッパー・カンファレンス’90日本」で配布されたレジュメである。「MacApp」とか「アップルの新技術・TrueType」てな文字が次々とコマギレにされて消えて行く。そうかそうか,そういう時代もあったなぁ,と。

     そんなかに,色違いの紙に印刷されたレジュメがあってデカい字で「ローカライズというビジネスチャンス」と書いてあるのを見つけた。そーなのだ,この頃デベロッパーでデカい顔をしていたのは(つうこたぁないっすな,でかい会社だったのは,であります)みんな,米国で発売され好評を博したソフトを日本語にローカライズして売ってる会社ばっかりであり,日本国内でオリジナルのソフトを開発・販売してたのはほんまに数えるほどだったのである。
     あー,だんだん思い出して来たぞ。このカンファレンス,技術的な話はクソの役にも立たない内容だったうえ(英文資料の翻訳が抱腹モノだったのを覚えてる),あげくの果てに当時MacPowerの編集者だったトジマさんの司会でそのテのローカライザーの巨頭数社の社長だか専務だかとにかく偉いヒトばっかりの座談会まで聞かされたのだ。
     出席したのは……別にさしさわりはなかろうが念のため匿名にすると「北海道でハードウエアを作っていた○社」,「PageMakerのローカライズをしていた△社」,「大阪で漢字変換モジュールを作りローカライズもやってた◆社」「福岡にあったあそこ,というだけで誰でも思い出せるだろう■社」の4社で,もうここまで書けばお気づきと思うが,一社たりともMac業界に残ってない(笑)。いや,どこにも残ってないところの方が多いくらいなんである。そうでしょ?
     トジマさんがどういう司会をしたか忘れたが,この座談会を企画したアップルの意図といえば,先の「ローカライズというビジネスチャンス」のレジュメでも分かるように,アメリカで売れているソフトをわずかな(っていうと語弊があるだろうけどさ)手間でローカライズして日本で売るのは美味しい商売でっせ,今日はそういう戦略で成功してらっしゃる皆さんをお招きしましたんでみんなでお話を拝聴しましょう,そして皆さんも続いてください,というようなもんだったんだろう。

     当時数少ない日本オリジナルのMacソフトを作ってたオレ自身は,そういうアップルのモノイイにちとカチンと来たような記憶がある。デベロッパーカンファレンスといいながら,来ているヒトも今のMOSAの会合を思えばやたら営業バタケ,マーケティングバタケのヒトが多かったようにも思うし,おお,そう言えばまだ当時は「ソ連」という国があって,あの飯倉の坂を降りたところに大使館があり,右翼の街宣車がふんじゃらかんじゃら喚いていたなぁ。あ,それは関係ないか。
     オレは別にアリとキリギリスの話をしようとかウサギとカメの話をしようというんぢゃない。賭けてもいいが,あのときステージでふんぞり返っていたヒトらは今でもオレよりきっといい暮らしをしているだろうし,そもそもオレだってアリよかキリギリスの暮らしの方が,カメの地道よりもウサギの飛躍の方が好きだ。そうぢゃなくて。
     「ローカライズしてお金儲けましょ」と言ってたころのこの催しはラフォーレ飯倉で2日間,昼飯にサンドウィッチとブリック・パックの牛乳がでただけで参加費がデベロッパー30,000円,一般40,000円というものだった。もちろんマシンの値段も当時とは違うし比べる方が間違っているんだけど,昨年のモサの湘南イベントなんか思い出しても,この14年でアップルもずいぶん変わり,オレたちみたいな零細デベロッパを大切にしてくれるようになったなぁ,と。そうそう,新聞などによればハラダさんはこの年にアップルに入ったのね,長いことご苦労さまでした。
    (2004_02_09)

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

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

     こんにちは、高橋真人です。早速、続きに入りましょう。
     コードは、さらに以下のように続きます。

    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という今回のプログラムの核心の機能を果たすクラスが登場しました。このクラスの定義はTextContent.hにあります。以下の部分ですね。

    class TextContent
    {
    public:
         virtual             ~TextContent() {}
         virtual void        WriteTo(ofstream& outStream) = 0;
         vector<string>      content;
    };

     以前も書きましたように、このプログラムは説明を分かりやすくするために多分に作為的です。そのためオブジェクト指向のやり方としてはまずい部分をいくつか抱えていますが、それは今の段階では無視します。(なので、public:というのは気にしないでください)
     さて、このクラスはメンバ関数2つとメンバ変数1つとを持ちます。~TextContent()とWriteTo()、それからcontentがそれらに当たります。~TextContent()はいわゆるデストラクタというやつで、インスタンスが破壊されるタイミングで呼び出される関数でしたね。
     ところで、それぞれの関数の頭に付いている「virtual」という識別子は何でしょうか? それを説明するためにはメンバ関数の実装について考える必要があります。
     既に書いたようにTextContentのクラス定義はTextContent.hというヘッダファイルにあります。対応する実装ファイルであるTextContent.cppを見てみますと、ナンと中身が何もありません。ヘッダファイルをインクルードしているだけで、あとはなぁーんにも書かれていないのです。一体、メンバ関数の実装はどこにあるのでしょう?
     まずはデストラクタである~TextContent()の後ろに注目してみてください。
     {}というカラのカッコがありますよね。実はこれがこの関数(デストラクタ)の実装部分です。C++では、通常はメンバ関数の実装は実装ファイル(cppファイル)に書くことが多いですが、内容が極めて短い場合やちょっとした事情がある場合には、クラス定義の中に直接関数の実装を記述することがあるのです。(Javaのやり方と同じですね)
     そんなわけで、ほとんど存在感の感じられない {} ですが、これで立派な関数定義を表しているということになるわけです。ちなみに、今回のような書き方でなく、cppファイルの方に実装を記述する場合には、

    TextContent::~TextContent()
    {
    }
    


    のようになりますが、その場合、関数の定義部分(つまり、ヘッダファイルの方)の末尾にはセミコロンを付けないとエラーになりますので。
     さて、virtualの話でしたね。実は、C++ではクラスのメンバ関数の前にvirtualと付くと、それを「仮想関数」と呼ぶのです。仮想関数というのは「サブクラスによって再定義される可能性のある関数」のことでして、つまりメンバ関数の前にvirtualというキーワードがあると、「この関数はサブクラスによってオーバーライドされるかもよ」ってことを意味するわけです。
     この「かもよ」ってところがミソなんです。「仮想関数」なんて名前が付くから実体(つまり実装)がないのかと言えばそんなことはなく、オーバーライドされない場合には、ちゃんとデフォルトの実装(つまり、このクラスにおける定義)が働く仕組みになっています。
     ところで、WriteTo()というメンバ関数ですが、こっちの方はよくみると、末尾に「= 0」なんていう奇妙なものがくっついてます。実は、virtualに加えてこの = 0 が付くと、今度は「純粋仮想関数」という名前に変わります。
     純粋仮想関数だなんて、ずいぶん大層な名前だと思いませんか? ただでさえこむずかしい用語が並んでいるC++ですが、さすがにこの用語を見た時には、私も「何なんだ、これはっ」と、ギョッとした記憶があります(笑)。
     さて、仮想関数が「純粋」になってきますと、今度は本当に実体(つまり実装)がなくなっちゃいます。従ってサブクラスによる上書きが、今度は必須ということになってまいります。さらに、この純粋仮想関数を一つでもメンバに含んだクラスのことを「抽象クラス」と呼びまして、これは「サブクラスによって上書きされることが前提となっているクラス」ということになります。
     言い換えれば、このクラスは実体化ができないということでして、今回の例で言えば、TextContentクラスからはインスタンスを作ることができないのです。

    TextContent  aInstance;    // エラー
    TextContent  *aInstancePtr = new TextContent;    // エラー

    と、いずれの場合もエラーになってコンパイルはできません。
     ちなみにC++によるポリモーフィズムは、親クラスに対する関数呼び出しがサブクラスによって上書きされるという形で動作しますが、このvirtualというキーワードを付け忘れると、この仕組みが働かなくなるので注意しましょう。
     さて、C++の難解ワードの森を彷徨っているうちに、今回も終わりになってしまいました。うーん。冒頭に掲げたコードも、最初の1行めだけしか説明できませんでしたね(笑)。では、また次回。

    ニュース・解説

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

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

    【開発環境】

    皆さん、ADCでSeedingされている物を仕事で利用しているマシンにインストールする時は注意しましょう(当たり前ですよね)。完成版のような振りをしていたので(笑)あまり深く考えずにナニの最新環境をインストールして動作確認をしてみました。すると、ナニの方は問題ないのですが、なんと、Metrowerks CodeWarriorのCarbonプロジェクトがMakeできなくなることが判明いたしました! 色々と調べてみると、テンプレートの時点でLibraryとしてリンクされているcrt1.oで何らかのトラブルが発生しているようです。これをMacOS X Support/Libraries/Startup/mwcrt1.oに差し替えたところ無事Makeできるようになりました。う〜ん、ナニはメイン環境じゃないので油断していたのがいけなかったようです(反省)。

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

    前回から2月14日の期間中、Apple社のDeveloperサイトには数多くのドキュメントが登録されました。すべて、Developer ConnectionのDocumentation Revision Listのサイトからアクセスすることが可能です。Java 1.4.2の発表に伴い、それに関連するドキュメントがいくつも登録されています。どうも、Cocoa関連のドキュメントにPDF版が少ないというのは伝統のようですね。

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

    「Java 1.4.2 Release Notes」 (PDFあり)
    「PowerPC Numerics」 (PDFあり)
    「Working With Bluetooth Devices」 (PDFあり)
    「Event-Driven XML Parsing」
    「Apple Event Manager Reference」 (PDFあり)
    「Printing」
    「Foundation Reference for Java」 (PDFあり)
    「Foundation Reference for Objective-C」 (PDFあり)
    「Application Kit Reference for Java」 (PDFあり)
    「Application Kit Reference for Objective-C」 (PDFあり)
    「Foundation Framework」
    「Runtime Configuration」
    「Launch Services Concepts and Tasks」 (PDFあり)
    「Launch Services Reference」 (PDFあり)
    「Java 1.4.2 API Reference: Apple Extension」
    「Java 1.4.2 API Reference: J2SE」
    「Java 1.4 Info.plist Java Dictionary Keys」 (PDFあり)
    「Java 1.4 System Properties」 (PDFあり)
    「Java 1.4 Virtual Machine Option」 (PDFあり)

    また、デベロッパ向けの読み物として以下の2つの内容が追加登録されています。

    「OpenGL Tools for Serious Graphics」(読み物)

    http://developer.apple.com/opengl/opengl_serious.html

    「Fighting Spam on Mac OS X Server」(読み物)

    http://developer.apple.com/server/fighting_spam.html

    前回から2月14日の期間中、新規テクニカルノートは4つ登録されました。
    「Mac OS X 10.3 Navigation Services Changes」では、Mac OS X 10.3になりNavigation Servicesへ新規に実装された機能とその変更点が取り上げられています。重要な点は、Navigation Services Dialogに表示されている各アイテム(メニューとかボタン)は、すでにダイアログアイテムではないということです。ダイアログを前提にして何らかのカスタマイズを行っているソフトは、Mac OS X 10.3以降では正しく動かなくなります。ただし、今までのアプリケーションとの互換性を維持するために、Navigation Services Dialogのカスタムエリア(ユーザがコントロールを追加できる領域)は、今まで通りダイアログとして機能しており、Dialog Manager APIを利用することが可能です。
    「The System Sound APIs for Mac OS X 10.2, 10.3 and later」では、SysBeep()の代わりとなるAPIが紹介されています。いよいよSysBeep()に渡す謎の引数ともお別れのようです…(笑)。

    TN2102 「The System Sound APIs for Mac OS X 10.2, 10.3 and later」
    TN2104 「Handling Audio Unit Events」
    TN2107 「Working Around Incorrect -needsToDrawRect: Behavior in Custom View Classes」
    TN2105 「Mac OS X 10.3 Navigation Services Changes」

    テクニカルQ&Aの方は8つ登録されました。Rendezvous関連のQ&Aが複数登録さ
    れています。「QA1334」「QA1335」「QA1339」については、前号の新居さんの
    解説を参照してください。

    QA1310「Clearing the Rendezvous service cache」
    QA1059「Setting the look-and-feel for Swing applications」(日本語訳)
    QA1312「Rendezvous service types used in Mac OS X」
    QA1331「Use empty string for Rendezvous domains」
    QA1333「Duplicate Rendezvous services while browsing」
    QA1339「The state of mDNSResponder」
    QA1335「Use NSSound instead of NSMovie for audio only playback on Mac OS X 10.3 and greater」
    QA1334「OpenGL Driver Monitor Decoder Ring」

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

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

    前回から2月14日の期間中、Apple社のSample Codeサイトには3つのサンプルソースコードが登録されました。「ThreadsExportMovie」はCocoaアプリケーショです。このサンプルでは、QuickTime 6.4から導入されたスレッドセーフのAPI(今回はQuickTime Movie Export Component)の仕組みを試すことができます。ただし、QuickTime 6.4 がインストールされていたとしても、このアプリケーションはMac OS X 10.2(Jaguar)環境では動作しませんので注意してください。

    「ThreadsExportMovie」(QuickTime関連)
    「Video Hardware Info」(Graphics 3D関連)
    「NSOpenGL Fullscreen」(Cocoa&OpenGL関連)

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

    【デベロップメント SDK】

    前回から2月14日の期間中、Apple社のDeveloperサイトに登録されたデベロップメントSDKは「Bluetooth SDK 1.3.3」と「Bluetooth SDK 1.4.1」です。1.3.3の方がMac OS X 10.2(Jaguar)用で、1.4.1の方がMac OS X 10.3(Panther)用となっています。

    「Bluetooth SDK 1.3.3」
    「Bluetooth SDK 1.4.1」

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

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

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

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

    2004-02-10

    目次

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

    MOSA Developer News 100号記念プレゼントを実施!

    お陰さまでMOSA Developer News(モサ伝)は、今号で100号を配信する事ができました。
    これまでのご愛読のお礼として、MOSA会員の皆様へ100号記念プレゼントを実施いたします。

    【MOSA会員限定100号記念プレゼント!】
    ・WWDC 2003 Sessions DVD-ROMセット(アップルコンピュータ(株)ご提供)
     2003年のWWDCの全セッションを収録したDVDのセットをMOSA会員限定で2名様にプレゼント致します。

    ★★★応募は締め切りました★★★

    ・その他のプレゼント
    以下のAppleCollection製品及びAppleTシャツをMOSA会員20名様へプレゼント致します。
    このプレゼントは応募形式を取らず、MOSA会員を対象に事務局で抽選を行い、102号で当選者を発表致します。発表をどうぞお楽しみに!
    Apple Panther Tシャツ      6名様
    Coffee Cup & Saucer       2名様
    Lexon CD Holder         2名様
    Disk Case(Blue)         2名様
    Apple Yo-yo           1名様
    Eraser pack           1名様
    See-Thru Pen           6名様
    (Red/Green/Orangeいずれかの色)

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

     ついにモサ伝も第100号。今日は最後に、Macらしさについて、自分なりの考えも述べようと思います。

    座標の原点を左上にしよう

     今まで作ってきたTinyViewですが、ウィンドウを操作してみて不自然に感じたことは無いでしょうか。TinyViewを起動して適当な画像を開き、ウィンドウを縮めたり拡げたりしてみて下さい。中の絵がそのたびに上下しますね。つまり、左下が原点になっています(fig.01)。通常のMacのアプリではどうでしょうか。普通は左上が原点になっているはずです。こちらの方が動きとしてずっと自然です。何故なら、ウィンドウのサイズを変更するには、右下にあるresizeコントロールを操作します。この時、左上が原点になっていれば、見える範囲を調節するように感じるからです(fig.02)。もちろん、表示されている内容によっては、動作が違う方が良い場合もあるでしょうが、TinyViewの場合は左上原点の方がより自然でしょう。

    [fig.01]resizeコントロールを操作すると、中身の絵は左下が固定の動きをする
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/38/images/fig01.jpg

    [fig.02]左上が原点なら、resizeコントロールの操作は表示範囲の変更に見える
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/38/images/fig02.jpg

     この様に左上を原点としたい時、一番簡単な方法は、Viewを上下反転させてしまう方法です。NSViewのリファレンスを見て下さい。isFlippedというメソッドがあるはずです。これをオーバライドしてYESを返すようにすると、座標が上下反転します。では、実装してみましょう。MyImageView.mに、次のメソッドを追加して下さい。

    - (BOOL)isFlipped{
        return YES;
    }

     ビルドして実行してみましょう。適当な画像を開くと、あれ?何も表示されなくなってしまいました(fig.03)。resizeコントロールを操作すると、スクロールバーは左上原点の動きをしますから、これはうまくいっているようです(fig.04)。でも、画像が表示されないのでは意味がありません。何故表示されないのでしょう。これは、composite系のメソッドが、isFlippedの影響を受けないことに原因があります。つまり、原点が左上に行ってしまいましたから、そこを原点としてその上に描いてしまっているのです(fig.05)。ちなみに、composite系以外の、isFlippedの影響を受けるメソッドでしたら、左上を原点とした上下反転した画像が表示されます(fig.06)。

    [fig.03]画像が表示されなくなってしまった
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/38/images/fig03.jpg

    [fig.04]resizeコントロールを操作すると、中身は左下固定になっているのが
    分かる
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/38/images/fig04.jpg

    [fig.05]ウィンドウの外に描画してしまっている
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/38/images/fig05.jpg

    [fig.06]composite系以外は、isFlippedの影響を受ける
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/38/images/fig06.jpg

    では、これを解決するために、composite系で描画する原点を、描画範囲の左下に移しましょう。次の様にdrawRectメソッドを修正して下さい。

    - (void)drawRect:(NSRect)rect {
        [ image compositeToPoint:NSMakePoint( NSMinX(rect), NSMinY(rect) + NSHeight(rect)) 
    fromRect:rect operation:NSCompositeSourceOver];
    }
    

     y座標に高さを足しています。左上が原点ですから、これで左下の座標になります。NSMakePoint()は座標を作る関数です(Xcodeを使っている方は、コマンドキー+ダブルクリックで実装されている場所に飛び、何をやっているのかを確かめてみて下さい)。さて、ビルドして実行してみましょう。今度は、きちんと表示されました(fig.07)。resizeコントロールを操作してみましょう。あれ?ウィンドウ内の画像の動きが左下原点の様に見えます。でも、スクロールバーを見ると、表示しているのは左上のはずです(fig.08)。スクロールバーを使って、下にスクロールしてみましょう。何だか滅茶苦茶になってしまいました(fig.09)。

    [fig.07]ウィンドウの中に表示されるようになった
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/38/images/fig07.jpg

    [fig.08]スクロールバーの位置と描画内容が合っていない
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/38/images/fig08.jpg

    [fig.09]縦スクロールで画像が崩れてしまった
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/38/images/fig09.jpg

    これはisFlippedをYESとしたために、今回はMyImageViewとimageの座標が等しく無いからです。具体的には上下逆転しています。そこで、これを補正するためのコードを追加します。drawRectを次の様に修正して下さい。

    - (void)drawRect:(NSRect)rect {
        NSRect theFrame, theSrcRect;
    
        theSrcRect = rect;
        theFrame = [ self frame];
        theSrcRect.origin.y = NSHeight(theFrame) - NSHeight(rect) - NSMinY(rect);
        [ image compositeToPoint:NSMakePoint( NSMinX(rect), NSMinY(rect) + NSHeight(rect))
     fromRect:theSrcRect operation:NSCompositeSourceOver];
    }
    


     ビルドして実行してみて下さい。今度は正常に動作したはずです。なお、座標が上下逆転しているのにfig.06の様に描画が上下逆転しないのは、先程も言ったように、composite系は描画に関してはisFlippedの影響を受けないからです。余談ですが、drawRectを次の様に実装すれば、isFlippedがYESでもNOでも動作するようになります。この方がより汎用的であると言えるでしょう。

    - (void)drawRect:(NSRect)rect {
        NSRect theFrame, theSrcRect;
    
        theSrcRect = rect;
        if( [ self isFlipped]){
            theFrame = [ self frame];
            theSrcRect.origin.y = NSHeight(theFrame) - NSHeight(rect) - NSMinY(rect);
            [ image compositeToPoint:NSMakePoint( NSMinX(rect), NSMinY(rect) + 
    NSHeight(rect)) fromRect:theSrcRect operation:NSCompositeSourceOver];
        }else{
            [ image compositeToPoint:rect.origin fromRect:theSrcRect operation:
    NSCompositeSourceOver];
        }
    }

     さて、今日まで随分とウィンドウの動作に手を入れてきました。この様に見栄えにこだわることが、それほど必要なことなのでしょうか。今まで実装して来たことを思い出してみて下さい。見栄えとは言っても、別段何かを飾り立てるようなことはしていません。求めて来たのは、ただひたすら、人間にとってより自然な動作になるように。これだけです。動作が自然になれば、ユーザはその部分に関して気を使う必要がなくなります。つまり、自分のやりたいことのみに集中することが出来るのです。Macのアプリが使いやすいのは、こういった地道な努力の積み重ねの結果だと、私は考えています。余計な所を飾らない、そしてこういった所で手を抜かない。これこそが、Macらしいアプリだと思います。
     なお、この様な努力の積み重ねの結果、動作がより自然になればなるほど、ユーザから見ると、何もやっていないように見えてしまいます。何だか報われないですね(^^;)。でも、それでもMacのプログラマは、使いやすい物を目指すのです。

    (全てのサンプル画像は、ゆきみだいふくさんのご好意により、使用させていただいています。)

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

    アプリケーションの入り口に立つ

    CarbonアプリケーションをC言語で開発する場合、その入り口のルーチン(関数)はmain()となります。この点については、他の環境でのアプリケーション開発と変わりありません。ちなみにC言語のプログラミング入門書を見ると、必ず最初に以下のようなサンプルコードが紹介されています。これはどうも、カーニハン&リッチー(伝説的C言語入門書)からの伝統のようです(笑)。

    main()
    {
        printf( "hello, world n" );
    }

    このソースをコンパイル&リンクして完成したアプリケーションは、標準出力へ”hello, world”と出力し、その後改行を1回実行します。ひと昔前のパソコンであれば(つまりMS-DOSがインストールされておりモニタにカーソルが点滅しているパソコン)このアプリケーションを実行することで、現状のカーソル位置に”hello, world”と表示できます。

    昔は、こうした簡単な入門サンプルを見た人から「Macintoshで簡単に文字を表示したいだけなんですが、どうしたら良いでしょうか?」という質問をよく受けました。確かに、以前であれば(ある意味では今もなんですが)、ウィンドウをオープンし、そこに”hello, world”と表示するだけのために、ToolBox APIを含めて数多くの複雑な概念を勉強する必要がありました。まあ、それでも文字を表示するだけならそれほど困難ではないのですが、次のステップとして、文字入力、画像表示、ユーザインターフェースに伴うウィンドウやイベントのハンドリングと進んでいくと…「Macアプリの開発はハードルが高い」と言われた「所以」にぶつかることになります。このため、初期ユーザの中には、アプリケーションの入り口の段階で立ち往生したまま、Macintoshでのプログラミングを挫折した人も多かったようです。

    しかし、皆さんもう心配いりません!MacintoshはMac OS Xの導入で大きく進化しました!アプリケーションフォルダからConsoleを起動して上記のCarbonアプリケーション(なのです)を起動してみてください、ちゃんとConsoleウィンドウに”hello, world”と表示されるではありませんか!Macも簡単になったものです(笑)。さて、冗談はさておき、Macintosh開発環境(XcodeやCodeWarrior)でも、標準出力用Consoleウィンドウを自動にオープンする仕組みがあり、別環境用アプリケーションの開発にも対応しています。また現状では、単純な処理であれば、Carbonなどの深い知識がなくても「Macintoshライク」なアプリケーションを簡単に開発できる環境がいくつも存在しています。

    実は、カーニハン&リッチーからの伝統はXcodeでもしっかり守られているのです。XcodeにおいてUNIXのコマンドラインから実行するアプリケーションを開発する場合、新規プロジェクトテンプレートとして「Standard Tool」(リストの一番下)を選択します。保存されたプロジェクトで唯一のソースファイルには、以下のようにサンプルコードが記述されています。

    int main (int argc, const char * argv[]) {
        printf("Hello, World! n");
        return 0;
    }
    


    先んじて紹介したソースコードとそっくりですが、main()に2つの引数が追加されていることが分かります。最初のargcには、実行されたUNIXコマンドのパラメータ数に1を足した値が代入されています。次のargvはポインタの配列で、コマンド名とパラメータ名の文字列が代入されています。例えば、あるファイルを別名称で複製するcopy(ふたつのパラメータを受け取る)と言うUNIXライクなコマンドを作成したとします。ターミナルから…

    copy gozira.jpg gamera.jpg

    と打ち込むと、argcには3が、argv[0]には”copy”が、argv[1]には”gozira.jpg”が、argv[2]には”gamera.jpg”が代入されてきます。これらを受け取ることで、アプリケーションは実際のファイルコピー処理を実現できるわけです。これは、ユーザからの「意志」をアプリケーション側に伝える仕組みです。太古から実装されているユーザインターフェースの一種とも言えるでしょう。この仕組みは単純なのですが、アプリケーションにとっては重要な意味を持っているわけです。これとまったく同じ仕組みではありませんが、Carbonアプリケーションにも、「ユーザの意志」をアプリケーション側に伝える仕組みは用意されています。それについては、後々詳しくお話しすることになりますので、今回のmain()の引数の話しをぜひ記憶しておいてください。

    さて、先ほどのテンプレートソースを参考にすると(笑)、今回の「サンプルアプリケーションの入り口」であるmain()ルーチンは、以下のように記述されます。Macintoshでは使いもしないargcとargvが律儀に記載されていますので、main( int argc, char* argv[] )の部分は、main(void)と省略してもかまいません。

    int main( int argc, char* argv[] )
    {
        long    ver;
    
        if( ! Gestalt( gestaltSystemVersion,&ver ) )
        {
            if( ver >= 0x1020L )
                startApplication();
            else
                doErrAlert( 1 );
        }
        return( 0 );
    }
    


    これから紹介していくソースコードにおいて、名称の先頭が大文字のルーチンはCarbon Frameworkを含めたシステムが提供するAPIで、小文字の方は自作ルーチンとなります。次回は、このソースコードの内容(そんな大げさな内容ではないですが…)と意味についてお話したいと思います。

    つづく

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

     前回D2Wのアシスタント機能について紹介したときに”task”の説明をおこないましたが、今回はこの”task”について詳しくみていきたいと思います。D2Wが標準で生成する画面は、基本的にはEntityとtaskの組み合わせによって決められます。つまり、あるテーブルに対してどのような処理(task)を実行するかによって画面が生成されることになります。
     実際には各taskごとのテンプレートがD2Wのフレームワーク内に用意されており、このテンプレートはEntityに依存せず汎用的に使用できるようになっています。よって、どのようなデータベース(モデル)を用いた場合でもEntityとtaskに応じて画面を動的に生成することが可能になっています。

     それでは具体的にどのようなtaskがあらかじめ定義されているかをみていきましょう。D2Wのフレームワークでは各taskに対応する形でにはInterfaceが定義されていますのでそのInterface名も紹介しておきます。

    ・QueryAll(QueryAllPageInterface)
     標準ではログイン後に最初に表示される画面で使用されるtaskです。任意のEntityを任意のAttributeで検索することができます。ただし”Hidden Entity”に対して検索をおこなうことはできません。QueryAllでは任意のEntityに対して単一のAttributeでしか検索ができませんが、複数のAttirbuteで詳しく検索をおこないたい場合は”Query”を使用します。

    ・Query(QueryPageInterface)
     任意のEntityのすべてのAttributeでの検索をおこないます。QueryAllではリレーション先のデータは検索対象には含まれていませんが、Queryではリレーション先のデータで検索をおこなうこともできます。検索時に複数の条件を指定した場合にはAND検索がおこなわれます。

    ・List(ListPageInterface)
     任意のEntity内のデータを一覧表示し、QuerryAllあるいはQueryで検索した結果の表示で用いられています。データの一覧を任意のAttirbuteでソートすることもできます。

    ・Inspect(InspectPageInterface)
     任意のEntityの任意のデータ(1レコード)の詳細を表示します。Listではリレーション先のデータまでは表示されませんが、Inspectではリレーション先のデータも表示されます。このタスクではデータの表示をおこなうだけで、データの変更をおこなうには次の”Edit”を使用します。

    ・Edit(EditpageInterface)
     データの変更や新規登録をおこないます。リレーションの編集をおこなうには”EditRelationship”や”Select”などを使用します。

    ・EditRelationship(EditRelationshipPageInterfece)
     Select(SelectPageInterface)
     リレーションの編集をおこないます。リレーションの編集は対1と対多の両方に対応しています。実際にリレーションを設定する手順ですが、既存のデータをリレーション先として設定する場合はまず”Query”を用いて検索をおこない、検索結果一覧の中からリレーション先を選択します。このとき検索結果の一覧表示には”Select”が使用されます。既存のデータにリレーション先が存在しない場合は、”Edit”を用いてデータを新規に作成してからリレーションを設定することもできます。またEditRelationshipでは既存のリレーションを解除することもできます。

    ・Confirm(ConfirmPageInterface)
     処理の実行を確認し、Entityには依存しません。Yes/Noの2択により処理を実際に実行するかキャンセルするかを選択し、データを削除するときの確認に用いられています。

    ・Error(ErrorPageInterface)
     こちらもEntityには依存せず、エラーメッセージの表示をおこないます。例えばモデル上で設定したDelete Ruleに違反するようなデータの削除操作をおこなったときに用いられます。

     以上があらかじめ定義されているtaskの概要ですが、今回紹介した機能はあくまでも標準の状態での機能です。ルールを記述していくことによって例えばListのページにリレーション先のデータを追加するなど、標準の機能に様々な変更を加えていくことができますし、独自のテンプレートを使用することもできます。

     以上のようなtaskごとにテンプレートが用意されているわけですが、以前紹介したように標準で3種類のLookが用意されています。そのため1つのtaskに対してLookごとに3種類のテンプレートがフレームワーク内に実装されています。例えば”List”の場合は以下の3つのテンプレートが存在します。

    BASListPage, WOLListPage, NEUListPage

     これらは異なるコンポーネントとして存在するわけですが、機能的には同一であるため、それぞれ共通のD2WListPage(ListPageInterfaceを実装している)を継承する形で実装がおこなわれています。

     さて、これまでしばらくD2Wの話ばかりしてきましたので、D2Wの解説はひとまず終わりにして、次回は話題を変えてみたいと思います。

    ニュース・解説

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

    ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    ┃Java 1.4.2がリリース、日本語の処理に問題含み
    ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    Mac OS XのJavaがVer.1.4.2にアップデートされ、1.4.2_03のリリースが使えるようになった。ソフトウエアアップデート等でアップデートできるが、Ver.1.4.1は削除されてリプレースとなる。アップデート後のシステムは、1.3.1、1.4.2等が利用できる状態にアップデートされる。
    1.4.2ではLiveConnectに対応した。LiveConnectは当初はNetscapeで開発された機能で、HTML内に記述するJavaScriptからアプレットがオブジェクトとして作業できたり、逆にアプレット側のJavaプログラムがそれを含むHTMLページ側に記述したJavaScriptの関数などを呼び出すことができる。

    さらに、Swingのファイル選択ダイアログボックスであるJFileChooserが改良され、より通常のダイアログボックスに近い形式になった。カラーコレクションについては、1.4.1ではKodakCMMのインプリメンテーションであったが、1.4.2ではシステムプロパティで設定することでColorSyncを利用することができる。AWTの改良、そしてプロキシ設定等も改良されている。

    一方、Windows版などでも問題になっていた、JISコード文字列のJava 1.4.2での問題はそのままMac版にも持ち込まれた。ISO-2022-JPのエンコードで余分なエスケープシーケンスがあるものをStringクラスの文字列としてインスタンス化すると、内部で無限ループに陥る。BizTechやまぐまぐといったメールマガジンで実際にそうしたエンコードがなされおり、よく使われているPerlのライブラリ等でそうしたデータ構築をするためと思われるが、不要なエスケープシーケンスが混じったメールは日常的に流通している。なお、この点については、Windows版が登場したときにバグレポートされており、Sun Microsystems側は認知している問題で、この問題が顕在化してすでに半年以上は経過している。次回のリリースで直るものとなっているようで、1.4.2_04ないしは1.5では直るものと認識されているようだ。このバグにより、たとえばJavaMailを使っている場合にある種のメールを受信すると、そこでプロセスの処理が止ってしまい、CPUの利用率が極端に高くなるという状況に陥る。

    なお、WebObjects 5.2.2については、Java 1.4.2での動作は十分に検証されていない。基本的にはJava 1.4.1での利用が保証されたバージョンとなっている。明確な問題は発生していないようであるが、WebObjectsの運用等では意識しておく必要はあるかもしれない。

    Java 1.4.2 Now Available
    http://developer.apple.com/java/index.html

    Java 1.4.2 Release Notes
    http://developer.apple.com/documentation/ReleaseNotes/Java/Java142RN/index.html

    Java 1.4.2 API Reference: Apple Extensions
    http://developer.apple.com/documentation/Java/Reference/1.4.2/appledoc/api/index.html

    Java 1.4.2 API Reference: J2SE
    http://java.sun.com/j2se/1.4.2/docs/api/index.html

    ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    ┃Cocoaで利用するXMLパーサクラスについての解説文書
    ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    Mac OS X 10.3以降で利用できるXMLパーサについての解説文書が公開された。イベントドリブン方式のXMLパーサである。XMLをもとに、特定のタグやあるいは文字列を見つけることによってデリゲートで定義されたメソッドを呼び出す方式で、XMLの内容を解析できるようになっている。なお、このクラスはObjective-Cでのみ定義されているが、JavaについてはSAXなどを利用することを想定していると思われる。

    Event-Driven XML Parsing
    http://developer.apple.com/documentation/Cocoa/Conceptual/XMLParsing/index.html

    ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    ┃CocoaのNSViewでの効率的な描画機能についての注意
    ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    Technical Notesに、Mac OS X 10.3からCocoaに搭載された描画高速化機能についての注意点が掲載された。NSViewにgetRectsBeingDrawn:count:とneedsToDrawRect:のメソッドが追加され、再描画が必要な領域なのかを判断できるようになった。しかしながら、文字があるような場合などで正しく判断しないことがあり、その回避方法を解説している。

    Working Around Incorrect -needsToDrawRect: Behavior in Custom View Classes
    http://developer.apple.com/technotes/tn2002/tn2107.html

    ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    ┃サウンドはNSSoundでならす
    ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    Cocoaでサウンドをならすときには、NSMovieよりもNSSoundを使う方がより良い結果を得られることがTechnical Q&Aで紹介されている。NSSoundはCore Audioの機能を使ってさまざまなフォーマットが利用できるようになっており、安定してサウンドの再生ができる。

    Use NSSound instead of NSMovie for audio only playback on Mac OS X 10.3 and
    greater
    http://developer.apple.com/qa/qa2001/qa1335.html

    ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    ┃Launch Servicesの解説とリファレンスが公開
    ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    Launch Servicesのドキュメントが公開された。解説文書とリファレンスが公開されている。Mac OS Xで搭載されているLaunch Servicesは初期の頃から存在するが、ドキュメントがないためにヘッダを参照してプログラムをした人も多いだろう。別のアプリケーションを起動したり、文書を開くという仕組みをプログラムするときに必要になる。ほかに、アプリケーションの情報や、文書がどのアプリケーションで起動されるかなどの情報を取得したり、最近使った項目の処理などの機能もある。起動する場合もさまざまなオプションがあり、URLを開く対象に指定することもできる。

    Launch Services Concepts and Tasks
    http://developer.apple.com/documentation/Carbon/Conceptual/LaunchServicesConcepts/index.html

    Launch Services Reference
    http://developer.apple.com/documentation/Carbon/Reference/LaunchServicesReference/index.html

    ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    ┃JBossが1.0.1にアップデート
    ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    Mac OS X Server 10.3に含まれるアプリケーションサーバのJBossがVer.1.0.1にアップデートしている。JBossそのもののバージョンは3.2.2RC2、Tomcatは4.1.24となっているが、基本的には、Java 1.4.2への対応となっている。なお、Java 1.4.2へアップグレードした後にJBossが起動できない場合の対処も文書が公開されている。

    JBoss Update for Mac OS X に関する情報とソフトウェアのダウンロード
    http://docs.info.apple.com/jarticle.html?artnum=120310

    Java 1.4.2: Java 1.4.2 Update インストール後 JBoss と Tomcat が開始しない
    http://docs.info.apple.com/jarticle.html?artnum=107814

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

    2004-02-03

    目次

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

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

     今回は、再びTinyViewの描画に手を入れます。

    無駄な描画をしないようにしよう

     実を言えば、現在のTinyViewは、場合によっては必要無い所まで描画してしまっています。第29回で行った実装を、もう一度見直してみましょう。
    MyImageView.mの中の、drawRect:を見て下さい。

    - (void)drawRect:(NSRect)rect {
        [ image compositeToPoint:NSZeroPoint operation:NSCompositeSourceOver];
    }

     composite系で画像全体を描画しています。ウィンドウ内に画像全体が表示されている場合はこれで良いのですが、画像がウィンドウからはみ出していて、スクロールにより一部を見れる場合はどうでしょう。この場合は、はみ出している部分は描画する必要が無いことになります。しかも、スクロールさせた時には元々表示されていた部分はそのまま使われますので、新しく現れた部分だけ描画すれば良いのです(fig.01)。

    [fig.01]一部だけ描画すれば良い例
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/37/images/fig01.jpg

    それなのに常に全て描画するのは無駄だと言えます。では、どの部分を描画すれば良いのでしょうか。実は、drawRect:が呼び出された時に渡って来るrectが、描画を必要とする範囲を示しています。
     rectは、今までも出て来ていましたが、矩形を表す構造体です。どの様に宣言されているのか見てみましょう。Xcodeで、NSRectと書いてある所にマウスカーソルを持って行き、コマンドキーを押しながらダブルクリックしてみて下さい(fig.02)。

    [fig.02]NSRectの所で、コマンドキー+ダブルクリック
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/37/images/fig02.gif

    すると宣言されている所にジャンプしたはずです(ジャンプしなかった時は、ビルドしてからもう一度やってみて下さい。)。NSRectは次の様に宣言されています。

    typedef struct _NSRect {
        NSPoint origin;
        NSSize size;
    } NSRect;

    originは原点。sizeは縦横のサイズです。NSPointとNSSizeの宣言はすぐ上にあります。

    typedef struct _NSPoint {
        float x;
        float y;
    } NSPoint;
    
    typedef struct _NSSize {
        float width;         /* should never be negative */
        float height;        /* should never be negative */
    } NSSize;
    


     この矩形がどの部分を表しているかと言いますと、MyImageViewの座標です。例えば、fig03の様にMyImageViewの一部がウィンドウに表示されていて、その中の赤枠の部分だけ描画が必要な場合、その部分を表すrectが渡って来ます。fig03の例で言えば、originに(628,306)、sizeに(140,457)の値が入ったrectです。

    [fig.03]rectで渡って来る値
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/37/images/fig03.jpg

    ここで気をつけて欲しいのは、この座標は画像の座標では無いということです。あくまでMyImageViewの座標ですから、この部分に画像(image)のどの部分を描画すれば良いのかということになります。ですから、正しくはfig04の様になりますね。つまり、imageの赤枠の部分をMyImageViewの赤枠の部分に描画することにより、ウィンドウの赤枠の部分に表示されるわけです。

    [fig.04]imageとMyImageViewの関係
    http://www.remus.dti.ne.jp/~yoshiki/cocoa/ed1/37/images/fig04.jpg

    これを見て気付いたと思いますが、今回はたまたまMyImageViewとimageの座標は等しいです。ですから、同じ値を使って良いことになります。それでは、必要な部分だけを描画するように修正してみましょう。

    - (void)drawRect:(NSRect)rect {
        [ image compositeToPoint:rect.origin fromRect:rect operation:NSCompositeSourceOver];
    }
    


     描画しなければならないのは、MyImageViewの中のrectで示された矩形の部分です。今回はimageの座標もMyImageViewと値が同じですから、imageの中のrectで示された部分を、そこに描画すれば良いことになります。そこで、描画先の座標をrect.origin、描画元の矩形をrectにしています。これで必要な部分だけを描画するようになりました。実際にビルドして実行してみて下さい。
     こういった座標に関することは、言葉で書くとややこしくなりますが、具体的に図で見れば単純なことだと分かります。プログラムを組んでいて混乱したら、図に書いてみると良いでしょう。
     ところで、TinyViewを使っていて、動作が奇妙に感じることはありませんか。何か動作が通常のMacのアプリとは違うような。画像を開いてウィンドウを縮めてみて下さい。中身の画像が左下固定になっているのが分かると思います。この動作は人間から見て不自然ですね。通常のMacのアプリだったら、左上が固定のはずです。と言うわけで、Macらしいアプリにするために、次回はここに手を入れて行きます。

    (全てのサンプル画像は、ゆきみだいふくさんのご好意により、使用させていただいています。)

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

     唐突だが読者の皆さんは郵便局の「転居先転送サービス」というものをご存知であろうか。郵便局に行くとこのサービス専用のハガキというのがあって,これに転居元の住所と転居先の住所,それに転居日を記入して最寄りのポストに投函すれば,そこに書いた転居の日から1年間,旧住所宛に届いた郵便物を(銀行などから来る「転送不要」と朱書きされているヤツは別)新住所に転送してもらえる,というものだ。
     数年前突如逆上してマンションを購入,次にこのサービスを利用するのはローン返済不能になって夜逃げするときくらいであろう私が言うのもナンだがこれは実に便利な制度であって,その効用たるやこれをもう一度利用するために不肖フジモトココロの奥深くでナニゴトも経験だから一回くらいは夜逃げも悪くないかなと想像したりするくらいのモノなんである(もちろん嘘です)。
     だいたい皆さんもこの原稿をメールで読んでいるくらいだから,日常的な交際・連絡などにアナログ郵便(……と呼ぶべきなのかな,「郵政省メール」と言う呼び方はもう正確ぢゃないらしいからな)を使うということは少ないと思う。私など,年賀状を除けばプライベートな郵便物,すなわち宛名や中身に少しでも手書きの文字が存在する郵便物を受け取ること自体稀である。いや,オレも今年は自分の年賀状に手書きの文字を入れられませんでした,すいません。

     とにかく,その唯一の例外と言ってよかろう(賀状に先立つ「喪中のはがき」などもこの範疇に入れていいと思う)年賀状のヤリトリは当たり前だけど年に一回である。つまりですね,「年賀状による年一回の住所通知」と「転居先転送サービスの期間が1年間」というのは,当初そういう考慮のもとに実施されたわけではないかもしれぬが相互に補完し合って「知人の間の相互連絡ネットワーク」を維持している見事なシステムなんである。
     具体的にみようか。ここに,MOSAの理事にも似た名前のヒトがいるけど全く架空の存在であるところのコイケさんというヒトがいて,昨年の6月に引っ越しをしたとする。忙しいので転居通知メールなど出せない。そこでフト,これまたこの原稿を書いているフジモトには全く関係のない架空の存在である友人フジモトが飲み会でほざいていた言を思い出し,「転居先転送サービス」の申し込みだけを行った。
     かくして今年の正月,彼のところには旧住所宛に出された年賀状が配達される。また,今年自分で出した年賀状には当然ながら新しい住所を書いてあるので,来年以降もモノゴトが円滑に進むであろうと期待できる。静かな正月,コタツでミカンなど剥きながらコイケさんはああ便利な世の中だなあと思うのである。

     まぁもちろん,コイケさんがまたしても似ている名前の理事はいるけれども金輪際無関係の架空の存在であるタナカ君とのつきあいはこれきりにしようと今年は年賀状を出さなかったり,逆にこれまた(以下略)のタカハシさんが昨年くれた年賀状の住所が変わっているのに気づかずにいて2年続けて旧住所宛に年賀状を出したりすれば,このシステムによる相互連絡は破綻するわけだが,それはまぁマニュアルに沿ってない使い方というか人為による破綻なのでしかたがない。
     そうした人為的なものは別としてこの「連絡維持システム」が崩壊する可能性というのはあるだろうかと考えたとき,ワタシはこのシステムの巧緻にほとんど絶句するくらい感動したのである。
     ……すなわち,通知サービスを申し込み,転居日から1年以内であるにも関わらず転送が行われないというという事態は,「転居したその日にその日を転居日として申し込みはがきを投函し,その申し込みはがきが集配されて局に着き処理される以前に旧住所宛の郵便物が配達に回った場合」に出来すると考えられる。
     ところが,「年に一回の住所通知」である年賀状が配達される1月1日は,おそらくは「1年中で一番引っ越しの少ない日」であるのである。ああ,すべからくシステムというのはこのように構築されるべきである。そう思いませんか?
     ところで,私がなんでこんなことに思いを巡らせたかと言えば,今年出した年賀状が実に5枚も宛先不明で戻って来たからである。MOSA関係者は一人もいないので,「これを読んでいたら連絡をくれ」と書いても虚しいが,キサマらは「転送サービス」くらい使いやがれよな,と虚空に悪態をつかせていただいてまた次回。おそまつ。
    (2004_01_27)

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

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

     こんにちは、高橋真人です。早速、続きに入りましょう。
     続いてのコードは、以下のようになっています。

    ifstream ifs(targetFile.c_str());
    if (not ifs) {
        abort();
    }

     ifstreamというのは、ファイルからデータを読み出すためのクラスです。input file streamの略だと考えると分かりやすいでしょう。streamというのは日本語にすると「小川」とか「流れ」といった意味になりますが、ファイルのI/O(入出力)においてはデータを読み書きするために使われる仕組みです。
     ANSI Cのライブラリの例ですとfread()やfwrite()などの関数が、ある程度の分量のデータをまとめてドサッと読み書きするに対して、fgetc()やfputc()などは、小さな単位のデータを片っ端から順々に流していく形で読み書きしていきますが、これがストリーム方式です。printf()などの関数もこの分類に入れていいのでしょう。
     MacのToolboxにはストリーム方式はなく、ブロック単位での読み書きのみでしたが、PowerPlantなどのフレームワークが独自にストリーム方式を提供していたりしました。(LFileStreamなど)
     Mac OS Xの場合、Carbonには未だストリームはないようですが、Cocoaの方には辛うじてPantherから用意されたようです。(NSStreamなど)
     まあ、ファイルの読み書き程度であればストリームを使えないからといって特段不便なこともないでしょうが、ネットワークを経由してのデータの送受信ということになるとストリームを使えた方が便利になるケースも多いように思います。
     さて、CはUNIX環境から生まれた言語ですから、データのやりとりの対象を基本的にファイルとして扱います。よって、FILE構造体へのポインタとして標準の入出力(stdout、strin)も使えます。Cの拡張によって作られたC++の場合、ストリームはクラスとして実現されています。
     皆さんおなじみのHello worldですが、Cにおいては、

    printf("Hello world! n");

    と書きますが、C++の場合は、

    cout << "Hello world n";

    となります。C++ではちょっと事情があって、ストリームへのデータ書き出しのためにビットシフト演算子である << を多重定義して使っています。すなわち、output streamと任意の型とでこの演算子を挟んで記述すると、データの書き出しが行われるというわけです。何でこんな奇妙なこ演算子の使い方をするのかを知りたい方は、「プログラミング言語C++第3版」
    http://www.ascii.co.jp/books/detail/4-7561/4-7561-1895-X.html 
    あたりを読んでみてください。
     ちなみにCのprintf()の場合、書き出すデータの型によって、正しく%dや%sなどの変換指定子を対応させてやらないととんでもないエラーになったりしますが、C++のこの方法では演算子のオーバーロードの仕組みがちゃんと対象の型を認識してよきにはからってくれますから、この手の気づかいは必要ありません。例を上げれば、こんな感じです。

    int n = 10;
    char *str = "Hello world";
    char c = 'a';
    cout << str << n << c;

    書き出す順番に、どんどん << を使ってつなげていけばいいのです。
     さて、ifstreamは、コンストラクタに文字列を与えると、それをファイルのパスと解釈してファイルをオープンしてくれます(stringは、c_str()というメンバ関数を使うと、内部に保持している文字列をC文字列として返します)。従って、ここではカレントのユーザーのデスクトップにある"text.txt" という名のファイルが開かれることになります。
     ファイルのオープンと言えば、当然次は「ちゃんと開けたかどうかの確認」に入るわけですが、いきなり不思議な表現が出てきます。
     まず、notというのはC++において別名定義された ! 記号であり、意味は全く同じです。ただ、ソースの中でとかく埋もれて見えにくくなりがちな ! よりも認識率が高いので私は常用しています。このnotで、ifsを打ち消しているわけですが、ifsを単独で記述すると、「ストリームがオープンに成功していて、書き込む準備ができているときに真を返す」ということになっていますから、通して考えれば、ファイルのオープンに失敗した場合に、if文の中身が実行されることになるわけです。
     まあ、Cにおける

    FILE *fp = fopen(filename, "r");
    if (!fp) {

    という表現と極めて近い書き方だと思ってくだされば十分です。
     そして、ファイルのオープンが失敗した場合にabort()、すなわちプログラムを強制終了、という手順になります。

    ニュース・解説

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

    Carbon ドキュメント & サンプル & SDK ナビゲーション(2003/01/30)

    【開発環境】

    Metrowerks CodeWarrior v9.1をMac OS X 10.3の環境で利用すると、AltiVec関連のFrameworkが正しくリンク出来ないというバグ(だと思う)が存在することは以前に紹介しました。それを改善したv9.2の登場を心待ちにしているのですが、なかなか登場しません。加えてInterface Builderにも、古いNibファイルをオープンすると、Tabコントロール内に配置したオブジェクトが少しずつ下方へ移動してしまうバグがあります。残念ながら、こちらの修正バージョンも現れません。おかげで私の知り合いは、わざわざMac OS X 10.2環境をインストールしてNibファイルの作成とプログラミング開発を続けています。

    そう言えば、Xcode v1.1にチャレンジしたのだが、諸々の問題のためProject Builderへ帰っていった人もいましたね(笑)。開発環境を含め、仕事に直接利用しているアプリケーションに致命的なバグがあるのは非常に困ります。楽器演奏を仕事にしている人のバイオリンのネックが折れているようなものでして、「仕事にならない!」というのが本音でしょう(でも、何とかしているのが現実ですが...)まあ、バイオリンならば、修理に出したり買い換えたりといくつかの対策がありますが、こちらに限ってはメーカ側の修正をひたすら待つしかないというのが...実に寂しい2004年の冬なのです(涙)。

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

    前回から1月30日の期間中、Apple社のDeveloperサイトにはドキュメントがひとつも登録されませんでした。ただし、デベロッパ向けの読み物として2つの内容が追加登録されています。最初の方は、CHUD(Computer Hardware Understanding Development)に含まれる「Shark」というパフォーマンス・ツール(プロファイラ)についての記事です。興味のある方は印刷して保存されておくと良いでしょう。こうしたデベロッパ向け記事についても日本語訳が欲しいところです。

    「Optimizing with Shark: Big Payoff, Small Effort」

    http://developer.apple.com/tools/shark_optimize.html

    「Mac OS X Makes It Easy to Add Competitive Application Features」

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

    1月30日までに新規テクニカルノートはひとつも登録されませんでしたが、テクニカルQ&Aの方は5つ登録されました。いくつかのQ&Aには日本語訳もありますが、内容は古いままです。英語バージョンの方のみが再登録となりますので注意してください。

    QA1332 「Shearing a Coordinate Space with NSAffineTransform」
    QA1149 「DV Codec settings and performance」(日本語)
    QA1328 「Server Processes and the Dock」
    QA1087 「Issues with boot time KEXT loading」(日本語)
    QA1330 「Music Player Sequence Destinations」

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

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

    前回から1月30日の期間中、Apple社のSample Codeサイトには4つのサンプルソースコードが登録されました。「AddNibToNav」サンプルは、Navigationサービス・ダイアログのカスタムエリアに、Nibファイルから読み込んだユーザインターフェースを追加する仕組みを紹介しています。今までは、リソースファイルからDITLリソースを読み込んで実現していた機能です。

    「Verification」(DiscRecording関連)
    「ElectricImageComponent」(QuickTime関連)
    「AudioBurn」(DiscRecording関連)
    「AddNibToNav」(HIToolbox関連)

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

    【デベロップメント SDK】

    前回から1月30日の期間中、Apple社のDeveloperサイトに登録されたデベロップメントSDKは「Kernel Debug Kit」の最新版だけです。また、ToolsサイトにCHUDの最新版 v3.0.4が登録されています。

    「Kernel Debug Kit 10.3.2」

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

    「Computer Hardware Understanding Development Tools 3.0.4」

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

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

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