MOSA Multi-OS Software Artists

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

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

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

MOSADenバックナンバー 2008年11月発行分

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

    2008-11-25

    目次

    • りんご味Ruby         第36回  藤本 尚邦
    • 藤本裕之のプログラミング夜話   #149
    • 高橋真人の「プログラミング指南」  第147回
    • mosa entranceだより       第1回   大野 亮一郎

    りんご味Ruby   第36回  藤本 尚邦

    前回に引き続き、Rubyでの構文糖衣(syntax sugar)やDSL(Domain-SpecificLanguage=ドメイン固有言語)の作り方について、今回は、アクセッサを宣言するための疑似的な構文糖衣をどのように実現するのか、そのいくつかの方法を見ていきます。

    真偽値を返すアクセッサを宣言するための(疑似)構文糖衣 attr_predicate を使えるようにする方法としては:

     ・クラス継承             – 構文糖衣を実装した親クラスを用意
     ・ミックスインモジュール — 構文糖衣を実装したモジュールを用意
     ・オープンクラス         – Moduleクラスに直接、構文糖衣を実装

    の3つの手段が考えられます。

    ■ クラス継承 — 構文糖衣を実装した親クラスを用意

    これは、attr_predicate をクラスメソッドとして実装した親クラスを定義しておき、その派生クラスの定義で attr_predicate を使えるようにする方法です。

    --------------------------------------- attr_predicatable_class.rb ---
    class AttrPredicatableClass
     def self.attr_predicate(*names) # 構文糖衣をクラスメソッドとして定義
       names.each do |name|
         define_method("#{name}?") do
           instance_variable_get("@#{name}") ? true : false
         end
       end
     end
    end
    ----
    


    親クラスを定義したライブラリを作ってしかるべき場所に置いておけば、そのライブラリをrequireでロードして、派生クラスの定義中で attr_predicate を使えるようになります:

    require 'attr_predicatable_class'
    
    class TodoItem < AttrPredicatableClass   # 派生クラスの定義
     attr_reader    :summary
     attr_predicate :done                   # 新しい構文糖衣を使用
     attr_writer    :done
    
     def initialize(summary)
       @summary = summary
     end
    end
    

    ■ ミックスインモジュール -- 構文糖衣を実装したモジュールを用意

    attr_predicate を実装したミックスインモジュールを定義しておけば、あるクラスの定義のときに、includeを使ってそのミックスインモジュールを組み込むことにより attr_predicate が使えるようになります。

    ---------------------------------- attr_predicate_attachment.rb ---
    module AttrPredicateAttachment
     def self.included(target_class)
       def target_class.attr_predicate(*names)
         names.each do |name|
           define_method("#{name}?") do
             instance_variable_get("@#{name}") ? true : false
           end
         end
       end
     end
    end
    ----
    


    クラス継承の場合と同様に、このライブラリをrequireでロードすると、クラス定義のときにモジュールを組み込んで attr_predicate を使うことができます。

    require 'attr_predicate_attachment'
    
    class TodoItem
     include AttrPredicateAttachment  # ミックインモジュールを組込み
     attr_reader    :summary
     attr_predicate :done             # 新しい構文糖衣を使用
     # 以下略
    end
    
    AttrPredicateAttachmentモジュールの定義でのポイントは
    
     def self.included(target_class)
       def target_class.attr_predicate(*names)
         ...
    


    のところで、「AttrPredicateAttachmentモジュール自体」に included というメソッドを定義していることです(このselfは「AttrPredicateAttachment モジュール自体」を指します)。

    あるクラスの定義で include によりモジュールが組み込まれたとき、その「クラス自体」を引数(つまり仮引数target_classの値)として、組み込まれたモジュールのincludedメソッドが呼び出されます。上記のTodoクラスの定義の例では:

     include AttrPredicateAttachment

    のところで、AttrPredicateAttachmentモジュールのincludedメソッドが呼び出されます。このとき「Todoクラス自体」が仮引数target_classの値となりますから、Todoクラスのクラスメソッドとして attr_predicate が定義されることになります。定義の中身はクラス継承の場合と同じですね。

    ということで、AttrPredicateAttachment を include したクラスの定義ではattr_predicate が使えるようになるわけです。

    以上の2つは、能動的にクラス継承したりモジュールを組み込まない限り使えないという点で、わりと安全で行儀のよい実現方法といえるのですが...

    ■ オープンクラス -- Moduleクラスに直接、構文糖衣を実装

    最後にオープンクラス。Rubyでは既存のクラスを実行時に直接変更することができるのですが、そのことをオープンクラスといいます。とても強力で上手に使えば有効な一方で、乱用しすぎると混乱のもとにもなるという、まさに「諸刃の剣」なのですが、Rubyの重要な特徴といえます。ということで次回に続きます。

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

     前回、映画「ファイナル・ファンタジー」を例にひいたが、あそこまで(つまりフルCGアニメーションでゲームの世界を再現するとこまで)やらないまでも、ゲームを「原作」とした映画がたくさん撮られるようになり、ある種のコンピュータゲームはその制作のしかたというか、その体制が非常に映画に似かよって来ている。

     若い人にはまたオジサンが昔話を始めたと言われそうだが、初期ののコンピュータゲームなんて、プログラマが自分で設計しシナリオを書き、シコシコとドット絵でキャラクターを描きプログラムを作りデバッグもテストもあれもこれも全部ひとりでこなして月刊アスキーにプログラム・ソースを投稿する、みたいなもんだったのだ。

     それがいまや、「インテジャーって何?」てな顔した(多分に偏見が入ってますな)ゲーム・プランナーとかいうヒトが「ローマ時代と古代中国をミックスしたみたいな文明がいちど滅びたあとの荒涼とした近未来世界でファンタスティックかつキッチュなキャラクターたちがドラゴンボールZ的にフィジカルかつエネルギッシュなバトルを繰り広げるんだよ」みたいなワケワカメのコンセプトを語ってさ、それを猟師が鉄砲で撃ってさ、煮てさ、焼いてさ……なんでとつぜん「あんたがたどこさ」になってんだかわからんが、マンガ家だったりイラストレイターだったりがキャラクターデザインをし、CG作家がそのモデルを起こし、ユーザーの操作に応えてそいつらがすべったり転んだりするコードをプログラマが書くという……プロダクション・システムというものが確立
    している。

     そうなるとなにが起きるか。1人で作ったもんであれば、その1人が食えるだけのお金を生めばまぁいいわけなんだが、100人で作ったもんは100人が食えるだけの利益を生み出す必要が産まれてくるのである。が、ゲームというものは映画以上に、コケた場合にはそれこそ徹底的にまったく全然金輪際これっぽちもお金にならないのである。

     前回書いたように映画であれば、あの「デビルマン」だってDVDを買う奴がいるのだし、もう少しほとぼりが冷めれば(我ながらなんて言い方だ)原作を読んで感動した少年が不幸にもTSUTAYAの棚であれを見つけてレンタルするかも知れない。またはこれから十数年先、かつてオレたちが産まれる前の「ゴジラ」や「ラドン」をそういう機会に観たように、あれを夏休みの午前中に「お子様映画劇場」みたいな形で放映するTV局がないとも限らない。さすればあんな映画でもそのときドキごとにいくばくかのお金を産む。

     ところがゲームはそうではあるまい。ゲーム好きの人は思い出して欲しい、ゲームに興味のないヒトは近くのゲーム好きに聞いてご覧なさい。史上、いったん「クソゲー」(それにしてもまぁとことん思いやりのない表現だよな)という烙印をおされたゲームが再評価などされたことはない。リサイクルショップでも買い取ってもらえず、なんとか不良在庫を整理しようと人気のあるゲームと抱き合わせ販売でもしようもんならあっというまに非難のまととなる。そしていつしかツワモノどもの夢の後、そのゲームがターゲットとしていたゲーム機自体が新しいものにとって代わられ忘れ去られる。もう一度書くが、それこそ徹底的にまったく全然金輪際これっぽちもお金にならないのである。

     先般(実はこれを書いてる時点では昨日なんだけど)、文化庁がやってる文化審議会著作権分科会の専門委員であったジャーナリストの津田大介氏の話を聞く機会があったんだが、興味深かったのは彼の「著作権問題を考える場合、『コンテンツに永続性がない』ってことを考えなければならない」という認識だったの。どういうことかというと、例えばかつてオレがビートルズのLPを買ったとき、オレは「音楽」を買ったのか塩化ビニルのレコードを買ったのかってことである。

     オレが買ったのが音楽だっていうのなら(JASRACが著作権料を請求するのはその立場からだ)、なんでオレはLPが聴ける環境を失ったときもういちどCDを買わなければならなかったの? つまりコンテンツの永続性がメディアによって阻害されているぢゃないかと。それでもビートルズなら必ずCDが出るからいい。かつてオレが持ってた上田正樹のソロ・デビュー盤「上田正樹」、セカンドアルバム「PUSH & PULL」、3枚目の「NO PROBLEM 」などは待てど暮らせど
    CDにならず……あ、個人的恨み言はいいか。……で、コンピュータゲームってのは、この「メディアによる永続性の阻害」ってのを宿命的に被るコンテンツなんだよな。(以下次回 2008_11_22)
                           

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

    プログラマのためのオブジェクト指向再入門(53)

    〜XcodeによるPowerPlant X入門(36)〜

     こんにちは、高橋真人です。
     前回、アタッチメントオブジェクトが消滅するタイミングで、アタッチメントによりインストールされていたイベントハンドラが取り除かれるのだが、それはそもそもどこにあるのか? という疑問を提示しました。
     その際に、「いくら探してもそのようなメンバ変数はありません」と言いましたが、これは誤りでした。確かに継承元のいずれのクラスにもそのようなメンバ変数はないのですが、そんなところを探さずとも、MyViewAttachmentクラス自体の中にちゃんとmEventHandlerというメンバ変数が用意されていたわけです。
     「うっかり見落とした」と言い訳したいところなのですが、実のところ、このメンバ変数がないと、これから行う説明が成り立ちません。そんなわけで、私のミスリードにより混乱させてしまったことをお詫びします。

     さてこれからお話しするのは、そんなアタッチメントも含めた、PowerPlantXにおけるイベントハンドラの取り扱い方についてです。アタッチメントの話を始める時にもお話ししたように、PPxではCarbonイベントのハンドリングが重要な位置を占めます。そもそもPPxが対象とするモダンなCarbonプログラムでは、Carbonイベントの取り扱いが中心となってプログラムが構成されますから、当然と言えば当然のことです。
     ただ、“生の状態”でCarbonイベントを取り扱う通常のCプログラムとは違って、PPxではオブジェクトの中にこれらの仕組みを包み込むことで、管理しやすくしています。実際、少し前に時間をかけて説明したViewのサブクラス化によるカスタマイズにおいても、Carbonイベントのハンドリングは大きな部分を占めていたわけですが、イベントハンドリングの細部がオブジェクトによ
    り包み隠されていたために、あまりこれらの部分を意識することなくカスタマイズできていたわけです。
     PPxにおけるイベントハンドリングの中核を担うのが、PPx::EventDoerというクラス(これは、PPx::ControlDrawDoerとか、PPx::SpecificEventDoerなどの大元のクラスです)です。私たちは単にこれらのサブクラスを作成し、DoXxxxx()関数を実装してInstall()関数を呼ぶだけで、あとはこれらのオブジェクトがよきにはからってくれたのです。
     そこで、それらのオブジェクトの内部動作を探ってみようというのが、これからのお話です。

     では、PPxがCarbonイベントをどのように扱っているのかを見る前に、通常のCプログラムにおけるCarbonイベントの扱い方を簡単におさらいしておきます。以下はイベントハンドラのインストールの部分です。

    EventHandlerUPP upp = NewEventHandlerUPP(EventHandlerProcName);
    EventTypeSpec typeList[] = {
       { kSomeEventClass, kSomeEventKind }
    }; 
    InstallEventHandler(target, upp, 1, typeList, NULL, NULL);
    


     まず、このコードが実行されるのに先立って、イベントハンドラの実体となるコールバック関数が定義されていることが前提となります。NewEventHandlerUPP()という関数は、このコールバック関数(以下「ハンドラの関数」と呼びます)の名前(ここでは、EventHandlerProcNameとなっています)を引数に取って、新たにUPPというものを生成して返します。
     UPPとは何でしょうか? 「UPPというのはUniversal Procedure Pointerの略で...」と説明していってもいいのですが、それに時間を割くほどの意味をここでは見いだせません。理屈として、UPPはハンドラの関数を間接的に指す“中間ポインタ”のようなものですが、現時点では“歴史的な事情で存在する”程度のものでしかなく、例えば、いまの私の手もとの環境(Mac OS X10.3
    on PowerMac G5およびMac OS X 10.5.5 on MacBook)では、NewEventHandlerUPP()に渡されるアドレスと、この関数が返すアド レスは同じ値です。理屈的に言えば、新規にメモリ領域を確保してオブジェクト を生成するはずなのですが、今のところ単に受け取ったポインタを型を変換して 返しているにすぎないわけです。

     環境が変われば違いが出るのかもしれませんが、とりあえずキャストして型を変換するだけでも結果に違いはないように思います。とは言え、AppleのドキュメントにはUPPを使うように書かれていますし、PPxもそれを踏まえて処理をしていますから、ここでは建前通りに、あたかもUPPというモノが作られていると考えてください。
     そして最後に、EventHandlerです。InstallEventHandler()というAPI関数に、ターゲット、UPP、そしてどんなイベントが発生した時にコールバックを呼び出すのか、などの情報を与えます。“どんなイベントが”という部分は、上記のコードではkSomeEventClassとkSomeEventKindという架空のEvent ClassとEvent Kindの組み合わせにしています。この辺も過去の連載で説明してあるので、分からない方は過去記事を参照してください。
     ところで、EventHandlerと呼んでいるのは便宜的なものです。常識的に考えれば、イベントハンドラは上記のハンドラの関数のことを意味するように思えますが、ここではコールバックを上記の設定で“登録した情報”が、それの意味するところとなります。

     重要なので改めて確認します。ハンドラの関数、UPP、そしてEventHadlerがここで重要な3つの要素です。あくまで呼び方は便宜的なものですから、その意味するところをしっかりと意識しておいてください。
     さて多くのプログラムでは、これらの要素がプログラムの実行中ずっと存在し続けます。C/C++では関数の定義を動的にすることはできませんから、ハンドラの関数は最初から最後までずっと存在します。あとUPPとEventHandlerは、多くの場合、プログラムの初期化の過程で生成されて、そのままプログラムが終了するまでの間、ずっと存在し続けます。
     そういう一般的なケースでは問題ありません。ところが何らかの事情で特定のハンドラが一時的にのみ必要とされることがあります。今も話題にしているアタッチメントのようなケースも一例です。この場合、前述のように一時的なものとはできないハンドラの関数を除く、UPPとEventHandlerを一時的に作り、役割が終わった時点で始末するという形になります。

     さて、通常のCプログラムにおいて、上記を実現するのはちょっとだけやっかいです。でも、実現は可能です。まずEventHandlerですが、これを始末する、つまり登録情報を抹消するのはRemoveEventHandler()というAPI関数です。この関数に渡す値は、EventHandlerRefという、EventHandlerへのポインタなのですが、この値はどこから取得できるのでしょうか?
     実は、前述のコード例でNULLになっている、InstallEventHandler()の最後の引数に対してEventHandlerRef型の変数のアドレスを渡してやると、作成されたEventHandlerのポインタが受け取れます。ですから、プログラムのどこかにこの値を保存しておいて、RemoveEventHandler()に渡してやればいいわけです。
     UPPについては、既に変数に値が取れていますから(上記のコードでは、upp)これもどこかに保存しておけば、あとでDisposeEventHandlerUPP()というAPI関数に渡して始末することができます。
     問題は、これらの値をどこに保存しておくか、です。
     Cのプログラムであれば、おそらくグローバル変数に保存しておくことになるでしょう。プログラムの構造を巧妙に作り込めば、これらのデータを無闇に晒すことなく保管しておくことも可能かもしれませんが、できることならこれらが一まとまりで管理できるとラクでいいですよね。

     このように、後始末をする際にちょっとした面倒臭さが発生するというのが、ここで問題にしたいことです。では、PPxではこの辺をどう解決しているのでしょう? それを次回は見ていきたいと思います。

    mosa entranceだより       第1回   大野 亮一郎

    MOSA会員の皆様こんにちは! mosa entranceという集まりを主催しております大野と申します。
    この度MOSA伝の場をお借りして、mosa entranceの活動をお伝えすることになりました。少しでも多くの皆様にこの企画を楽しんで戴けるような報告ができればと思っています。どうぞよろしくお願い致します。

    mosa entranceの主旨についての説明は、ぜひ初回のご案内http://www.mosa.gr.jp/?p=1973をご覧ください。簡単に申し上げますと、MOSA会員が交流する「場」を準備
    し、孤独なプログラミング(笑)を楽しくすることがひとつの目的です。特に悩めるプログラミング初学者の方に、ステップアップのお役に立てて戴きたいと考えています。

    さて、いつもの活動レポートは主催者の視点でお伝えしておりましたので、ここでは一参加者としての感想を述べさせていただこうと思います。参加してみて一番納得したのは、やはり皆さんAppleの製品をお好きなのだという当たり前のことでした。同時にMac OSだけでなくコンピュータに関する幅広い知識をお持ちの方が多いということ。私自身も仕事ではWindowsやその他のOSに触れる時間の方が長いのです。ましてやWebアプリケーションの開発に携わっていらっしゃるなら環境を選んではいられませんから、幅広い知識が前提になるわけですね。

    次にプログラミングに取り組むといっても様々な環境があるということ。開始時に簡単な自己紹介をしていますが、皆さんプログラミングとの関わり方が違います。ご自分で会社を経営し、Macを中心に開発なさっている方、企業内で開発されている方、普段はWindowsが中心で、Macは趣味的にされている方、Webアプリケーション開発をされている方、デザイン中心の方、またプログラ
    ミングはあくまで趣味としてされている方…。業界も様々で、全く異なる背景をお持ちの方がMOSAにいらっしゃることがよくわかります。mosa entranceの場で実際に皆さんとお会いすることが非常に刺激になっています。

    mosa entranceでは、もちろんプログラミング技術に関する話題が一番多く、ちょっとした余談でさえ非常に高濃度の肥やしになることが実感できます。しかし、それ以上に皆さんから直接得ることのできる、空気の様なものが大いに自分を奮い立たせてくれます。時として辛くなるのがプログラミングですが(え? 辛いことばっかり?)、そんな壁にあたっても乗り越えられるエネル
    ギーを得ています。特に私をはじめとする初学者の者にとっては、これが本当に大切なことなのではないでしょうか。

    まとまりのない文章でお恥ずかしい限りですが、これが一参加者としての私の感想です。
    MacやiPhoneでプログラミングを楽しみたいとお考えの皆様、是非一度mosa entranceにお寄りください。セミナーでお会いするMOSAの皆様とはひと味違う雰囲気を感じてみてはいかがでしょうか。お気軽に、お時間の許す範囲でお立ち寄りください。どうぞお待ち申し上げて
    おります。

    次回のmosa entrance便りは、実際にご参加戴いた方にバトンタッチしてお話し戴く予定です。
    どうぞお楽しみに!

    ★大野さんのプロフィールは上記初回のご案内にあります
    http://www.mosa.gr.jp/?p=2260

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

     

     MOSA Developer News   略称[MOSADeN=モサ伝]
            配信停止 mailto:mosaden-ml@mosa.gr.jp
     記事内容に関するご意見 mailto:mosaden-toukou@mosa.gr.jp
          記事投稿受付 http://www.mosa.gr.jp/?page_id=850
    Apple、Mac OSは米国アップル社の登録商標です。またそのほかの各製品名等
    はそれぞれ各社の商標ならびに登録商標です。
    このメールの再配信、および掲載された記事の無断転載を禁じます。
    特定非営利活動法人MOSA  http://www.mosa.gr.jp/
    Copyright (C)2007 MOSA. All rights reserved.

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

    2008-11-04

    目次

    • 「Wonderful Server Life」    第81回   田畑 英和
    • 小池邦人のCarbon視点でiPhone探求
    • ターミナルの向こうから      第36回  海上 忍 

    「Wonderful Server Life」  第81回  田畑 英和

      〜「iCalサーバ」編〜

     前回に引き続きiCalサービスについて解説します。前回はとりあえずサーバでiCalサービスを動かしてクライアントからアクセスするところまでをみてみましたが、ここでサービスの設定について確認しておきましょう。

    ◇iCalサービスの設定
     まずはサーバが標準構成の場合ですが、サービスの起動さえしてしまえば後はほとんど設定することがありません。標準構成の場合、サーバの管理には「サーバ環境設定」を使いますが、設定画面をみてみるとデータサイズの上限に関する2つの設定があるだけです。サーバとなりますと、すべてのユーザのデータを管理する必要がありますからディスクの使用量についても注意する必要がありますが、あらかじめデータサイズの上限を設定しておくことでディスクの使用量をおさえることができます。

    ・iCalサービスの設定(標準構成の場合)
    http://www.htabata.com/img/MXS105/iCal/ServerPref_01.png

     詳細構成の場合は設定項目が少し増えます。まずiCalサービスのデータを保存する場所が設定できます。

    ・iCalサービスのデータ保存場所(デフォルト)
    「/Library/CalendarServer/Documents」

     このディレクトリは「_calendar」ユーザがオーナーになっていますので、内容を直接確認するにはroot権限が必要になります。
     次にデータサイズの上限に関する設定がありますが「サーバ環境設定」の設定とは連動していませんので、標準構成から詳細構成に変換した場合はあらためて設定の内容を確認する必要があります。
     認証方式は「Kerberos」と「ダイジェスト方式」2つがあり、デフォルトでは両方の認証方式を利用する「すべての方式」になっています。このように新しいサービスでも積極的にKerberosを利用するようになってきています。
     あとはホスト名やポート番号の設定があります。また通信を暗号化するためにSSLを有効にすることもできます。SSHを有効にした場合には別途証明書の設定も必要になります。

    ・iCalサービスの設定(詳細構成の場合)
    http://www.htabata.com/img/MXS105/iCal/ServerAdmin_01.png

    ◇委任
     では次にクライアント側の設定についてみていきましょう。前回はアカウントの設定について解説しましたが、今回はユーザ間の連携について解説します。ここではtest1とtest2の2つのユーザがサーバ上に登録されているとします。「iCal」では複数のアカウントを登録することも可能ですが、クライアント上でも別々のアカウントでログインして動作を確認してみます。
     まずtest1のアカウントですが、iCalには委任という機能があり他のユーザに自分のカレンダーへのアクセスを許可することができます。test1のカレンダーへのアクセス権をtest2に与えてみましょう。
     設定方法は「環境設定」の「アカウント」から「委任」画面を表示し、右下の「編集…」ボタンをクリックしてアクセスを許可するユーザを追加します。ここではサーバ上のユーザリストは表示されませんので、手動でアクセス権を与えるユーザのユーザ名を指定します。また他のユーザに自分のカレンダーの編集も許す場合は「書き込みを許可」をチェックしておきます。

    ・自分のアカウントへのアクセス管理
    http://www.htabata.com/img/MXS105/iCal/iCal_test1_02.png

     アクセス権の追加が完了したら、アクセス権を与えられたtest2でも設定が必要です。test2用のアカウントをiCalの環境設定で登録し「委任」画面をみてみるとアクセス権があるユーザが自動的にリストアップされています。あとは「表示」をチェックするとtest2のアカウントでtest1のカレンダーにアクセスできるようになります。

    ・アクセス可能なアカウントの設定
    http://www.htabata.com/img/MXS105/iCal/iCal_test2_01.png

     iCalウインドウのサイドバーにはtest2のサーバ上のカレンダーに加えtest1のサーバ上のカレンダーも表示されるようになり、test2のアカウントでtest1のカレンダーイベントを作成できるようになります。

    ・test2のカレンダー表示
    http://www.htabata.com/img/MXS105/iCal/iCal_test2_02.png

     アクセス権の委任を行うにはクライアント上で双方のアカウントでの設定が必要になりますが、これで自分のカレンダーを他のユーザと共有したり、カレンダーの管理をまかせるといったことができるようになります。
     カレンダーはサーバ上に複数作成することができますが、委任の設定はあくまでもアカウント単位ですので、カレンダー単位で委任の設定を行うことはできません。それでは次回もiCalサービスの利用について解説します。
    次回へつづく                             

    小池邦人のCarbon視点でiPhone探求(2008/11/14)

     〜 iPhoneアプリケーションを開発しよう! 〜

    「ImageBrowserで選択した画像をどのように対称表示させるか?」を実現するために、今回からCore Graphics APIの解説に移ろうと思ったのですが、iPhone SDKのNDAも解除されたことですし、旬な時期を逃さないためにも、連載を180度(それほどでもないか…)方向転換したいと思います。ラッキーな事に、Core Graphics APIはiPhoneアプリケーションの開発(iPhone SDK)においてもそのまま利用できます。そこで、連載タイトルは「Carbon視点でiPhone探求」としてみました(笑)。

    ご存じの通り、iPhone用アプリケーションの開発にもCocoaを使います。Mac OS X環境ではCocoaネイティブの2D描画クラスなども利用可能なのですが、iPhone OS環境では、Core Graphicis(Quartz 2D)のみがネイティブの2D描画APIとなります。このままCore Graphics APIを解説していくと、話が完全にCocoaから離れますので、今まで実装してきた部分をiPhoneアプリケーションへ実装し直してから、2D画像描画へと話を進めることにします。「対称表示」機能を実装するためのソースコードは、そのままMac OS X用アプリケーションでも活用出来ますので(多分)、これにより二度手間を避けることができそうです(と思う)。

    作業の流れとしては、今までの連載で記述してきたImageBrowserを活用したソースコードを、iPhone OSのCocoa(UIKit Framework用)に書き替えることから始めます。ただし、iPhone SDKにはあの便利な「Image Kit」はありませんので、その部分については別の方法を考えなくてはいけません。また、iPhoneではファイルから画像を読み込むような環境は構築できませんので、その部分についても別アプローチが必要となります。とりあえず、今まで本連載で作成したソースコードは、雛形プロジェクトとしてMOSA Exchangeにアップロードしておきました。名称は「ShinbunShi3_08_11_14」です。今までの本連載の解説と共にご参照ください。

    Mac OS X環境のCocoaは「AppKit(Application Kit)」と「Foundation」という2つのFrameworkから構成されていました。そのうちFoundationの方は、iPhone OSでも使用できる共通仕様です(サブセットですが)。そして、もう片方のAppKitを「UIKit」に置き換えるとiPhone用Cocoaの構成となります。ちなみに、iPhone OSでは「UIKit」と「Foundation」を合わせて「Cocoa Touch」と呼ぶようです。それ以外に利用できるFrameworkとしては、Core Animation、Core Graphics、OpenGL ES(OpenGLのサブセット)、Core Audio、CFNetworkを含むCore Foundationなどがあります。残念ながらQuickTimeやCore Imageなどは利用できません。

    iPhoneでGUI(グラフィカルユーザインターフェース)を構築するにはUIKitを最大限活用します。UIKitで採用されているGUIは、ビューやコントロールを基盤にするなど、Mac OS Xのそれと多くの共通点があります。しかしメニューが存在しないなど、異なる点も多々見受けられます。また、iPhone OSにはMac OS Xではその仕組みが無い特殊なGUIも存在していることから、Mac OS XのGUIに固執する必要は無いようです。逆にUIKit独自のGUIをうまく活用してこそ、iPhoneらしいアプリケーションを開発することが可能となるでしょう。

    CocoaでMac OS X用アプリケーションを開発してきたデベロッパーであれば、AppKitFrameworkに含まれるクラスやメソッド名の先頭2文字を、NSからUIに変更することで、Mac OS X側で習得した技術スキルの多くを再利用できそうです。しかし、GUIの種類やその制御方法についてはiPhone独自の仕組みも多数あるので、今までの知識を鵜呑みにして対処すると痛い目に遭うかもしれません。謙虚に構えましょう(笑)。

    さて、iPhone用アプリケーションを実機にインストールして開発できるようになるまでの手順ですが、ざっとみて以下の様な過程となります。開発対象マシンは最新のMac OS X 10.5.xをインストールしたインテル版Macintoshとなります(PPC版では開発できませんので御注意を!)。

    (1)開発用マシン(Macintosh)を用意する
    (2)iPhoneかiPod touchを購入する(当然ですね)
    (3)Apple IDを作成する(ADCメンバーになる)
    (4)http://developer.apple.com/iphone/へアクセス
    (5)Apple IDとパスワードでログインする
    (6)iPhone SDKをダウンロードして開発用マシンへインストール
    (7)ドキュメントやサンプルもこのサイトからダウンロード可能
    (8)さらなる作業のため「Program Portal」サイトへ入る
    (9)実機インストールを可能にする各種認証用の手続きを行う

    チュートリアルビデオや技術ドキュメント、サンプルソースコードなどの開発用リソースはApple IDでログインした「iPhone Dev Center」からダウンロードすることが可能です。ここにあるドキュメントの内容はすべて英語ですが、このうちの幾つかの重要な物に関しては日本語訳されており、以下のサイトからダウンロードすることが可能です(こちらもApple IDでのログインが必要)。

    http://developer.apple.com/jp/iphone/library/japanese.html

    「Getting Started Documents」(iPhoneアプリケーション開発の概要)
    「Coding How-To’s」(コーディングに関するFAQをまとめてある)
    「iPhone OS プログラミングガイド」(iPhoneプログラミング全般)
    「iPhone ヒューマンイン ターフェイス ガイドライン」(GUIの使い方ガイドライン)
    「Objective-C 2.0 プログラミング言語」(Objective-C 2.0の解説書)
    「iPhone OS View Controller プログラミングガイド」(UIViewController使用方法)
    「iPhone OS Table View プログラミングガイド」(UITableView使用方法)
    「iPhone OS Address Book プログラミングガイド」(AddressBook使用方法)
    「iPhone Simulator プログラミングガイド」(iPhone Simulator簡易マニュアル)
    「iPhone アプリケーション チュートリアル」(iPhoneアプリ開発行程の概要)
    「iPhone OS Xcode クイックツアー」(Xcodeの簡易マニュアル)

    まず最初に読むべきドキュメントは「Getting Started Documents」です。これを読めば、iPhoneアプリケーション開発において、どのような種類の技術の習得が必要なのかを理解できます。そして、Objective-Cの未経験者は「Objective-C 2.0 プログラミング言語」を適度にカバーし、続いて「iPhone ヒューマンイン ターフェイス ガイドライン」と「iPhone OS プログラミングガイド」を読破します。最後の2つのドキュメントはiPhoneアプリケーション開発者にとっては必読書ですので、絶対に避けて通ることはできません。覚悟しましょう(笑)。

    実機を用いた(iPhoneやiPod touchへインストール)開発へ入る前には「iPhone アプリケーション チュートリアル」を読みます。開発ツールについて詳細を確認したい場合には「iPhone OS Xcode クイックツアー」と「iPhone Simulator プログラミングガイド」を調べます。アプリケーションに実装したい機能について何かしらの疑問が湧いた時には「Coding How-To’s」が大変参考になります。UIKitに属する主要クラスを解説したドキュメントとしては「iPhone OS View Controller プログラミングガイド」「iPhone OS Table View プログラミングガイド」「iPhone OS Address Book プログラミングガイド」の3つが用意されています。

    Mac OS X環境でCoocaアプリケーションを開発していた方は、「iPhone OS Xcode クイックツアー」や「Objective-C 2.0 プログラミング言語」を読む必要はないでしょう。ただし、UIKitではObjective-C 2.0のプロパティ機能を頻繁に使うので、その箇所だけは復習しておくべきかもしれません。それにしても、Interface Builderの使い方に関しての日本語ドキュメントが用意されていないのは残念ですね。どちらかと言うと、iPhoneアプリケーション開発には、XcodeよりInterface Builderに関する知識の方が重要になるからです…。ちなみに英語ドキュメントは「Interface Builder User Guide」です。

    技術ドキュメントを一通り読破したら、次にすべき事はサンプルソースコードを参照することでiPhoneアプリケーションで実現可能なことを正しく認識することだと思います。次回は「iPhone Dev Center」からダウンロードできるサンプルソースコードの内容を詳しく紹介したいと思います。

    ターミナルの向こうから      第36回  海上 忍

    〜 いま敢えて学ぶTerminalのイロハ(3) 〜

    ・困ったときの[TAB]頼み
     これからTerminalに親しもうと考えている人に、ぜひ覚えていただきたい機能が「入力補完」です。EclipseやNetBeansなどのJava系開発ツールに搭載されているあの機能……といえばピンとくるかもしれません。そう、長い関数の先頭数文字を入力すると残りの文字が自動的に入力される、あの便利な機能がTerminalでも利用できるのです。
     Terminalにおける入力補完機能は、シェルにより提供されます。Leopardでデフォルトのシェルに設定されているbashの場合、適当な文字列を入力したあと[TAB]キーを押すことにより、入力補完を実行します。困ったとき、面倒に感じたときには[TAB]を押す、まずはそのように覚えてください。

    ・なにはともあれ入力補完
     それでは、いくつか実例を紹介してみましょう。最初のお題は「カレントディレクトリ」の変更、いうなれば作業場所として使うフォルダを書類(Documents)フォルダにするというものです。まずはTerminalを起動し、プロンプト($)が表示されたところで「cd 」(「cd」の直後には半角スペース)と入力してください。

    - - - - -
    $ cd ■
    
    注:■はカーソルを意味します。
    - - - - -

     この状態で、大文字の「D」を入力し、続けて[TAB]キーを2回押してください。ホームフォルダ直下にある「D」から始まるファイルまたはフォルダが、一覧表示されるはずです。ホームフォルダ直下に「D」から始まるファイル/フォルダを作成していなければ、「Desktop」と「Documents」、「Downloads」という3つのフォルダが表示されたはずです。

    - - - - -
    $ cd D■[TAB][TAB]
    Desktop/   Documents/ Downloads/ 
    $ cd D■
    - - - - -

     次に行うのが、入力補完の精度を上げるための絞り込みです。[TAB]を押したときには、カーソルの左側に位置する文字列をもとに、カレントディレクトリ(Terminalの起動直後はホームフォルダ)内が検索されるため、「D」より「Dxx」のほうがヒットするファイル/フォルダ数は少なくなります。先ほどの例でいえば、「Do」と入力してから[TAB]を押すと、「Desktop」は除外されることになります。そして候補が1つしかない場合、[TAB]キーを1回押せば条件に一致するファイル/フォルダがカーソル位置へ挿入されます。

    - - - - -
    $ cd Do■[TAB][TAB]
    Documents/ Downloads/ 
    $ cd Doc■[TAB] → Documents■
    - - - - -
    


     もうおわかりいただけたと思いますが、この場合「Doc」に続けて[TAB]を押すだけで、「Documents/」(末尾の「/」は対象がディレクトリであることを意味します。省略可能です)と入力できるのです。カレントディレクトリ上に、先頭数文字が重複するファイル/フォルダが多ければそれだけ効率は落ちますが、長いファイル名をスペルミスなく入力できることの利点のほうが大きいと思います。
     ところで、シェルでは国際化されていない(BSDレイヤーとしての)ファイル/フォルダ名を扱うため、「書類」フォルダは「Documents」フォルダとしてしかアクセスできません。bashの入力補完機能についても、Mac OS Xで使われているGNU readline代替のライブラリ(Editline Library、libedit)は、UTF-8およびマルチバイト文字を通さない仕様のため、日本語のファイル/フォルダ名は入力補完の対象になりません。不可能ではありませんが、LeopardではASCII文字のみ可と考えて差し支えない状況です。

    ・コマンド名も入力補完
     上述の例では、ファイル/フォルダを対象にした入力補完を紹介しましたが、コマンドも対象にできます。コマンドサーチパス(コマンドが保存されるディレクトリ群の情報、デフォルトでは/binと/sbin、/usr/binと/usr/sbin、/usr/local/bin)に登録されたディレクトリに保存されていれば、コマンド名の先頭数文字プラス[TAB]キーで補完できます。これで、コマンド名の綴り
    を正確に記憶しておく必要がなくなる(先頭数文字は忘れずに)ことでしょう。

    - - - - -
    $ ba■[TAB][TAB]
    banner  basename  bash  bashbug  batch 
    - - - - -
    

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

     

     MOSA Developer News   略称[MOSADeN=モサ伝]
            配信停止 mailto:mosaden-ml@mosa.gr.jp
     記事内容に関するご意見 mailto:mosaden-toukou@mosa.gr.jp
          記事投稿受付 http://www.mosa.gr.jp/?page_id=850
    Apple、Mac OSは米国アップル社の登録商標です。またそのほかの各製品名等
    はそれぞれ各社の商標ならびに登録商標です。
    このメールの再配信、および掲載された記事の無断転載を禁じます。
    特定非営利活動法人MOSA  http://www.mosa.gr.jp/
    Copyright (C)2007 MOSA. All rights reserved.

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

    2008-11-11

    目次

    • りんご味Ruby         第35回  藤本 尚邦
    • 藤本裕之のプログラミング夜話   #148
    • 高橋真人の「プログラミング指南」  第146回

    りんご味Ruby   第35回  藤本 尚邦

    前回に引き続き、Rubyでの構文糖衣(syntax sugar)やDSL(Domain-SpecificLanguage=ドメイン固有言語)の作り方について書いていきます。

    ■ 構文糖衣=メソッド呼出

    Rubyには、クラス定義でアクセッサ宣言するために attr_reader,attr_writer, attr_accessor などの構文糖衣があります(以下はこれらを使ったクラス定義の例)。

    class TodoItem
     attr_reader   :summary
     attr_writer   :done
    
     def done?
       @done ? true : false
     end
    
     def initialize(summary)
       @summary = summary
     end
    end
    


    上のプログラムの attr_reader, attr_writer を使っているところが、「パッと見」あたかもRuby言語に最初から備わっている宣言文のよう見えるでしょうか? どう見えるかというのはまったく主観的なものなので、「いやそうは見えない」と言われてしまうとそれまでなのですが、ここはあたかも宣言文のように見えるということにしてください。これまでに強調してきたように、このattr_reader, attr_writer は、Rubyの本物の構文ではなく、メソッド呼出による疑似的な構文です。

    さて、これがメソッド呼出であるからには、メソッドを呼び出すメッセージの
    受け手(=レシーバオブジェクト) が存在するはずです。attr_readerの場合、
    レシーバは何になるのでしょうか?

    答えはselfです。これらのメソッド呼出ではレシーバが省略されているので、レシーバはselfということになります(第8回,第22回を参照のこと)。Rubyのプログラムが実行(評価)されているときには、常に、省略されたときの暗黙のレシーバであるself が存在しています。

    試しに以下のようなテストプログラム:

    class Hello
     p self, self.class          # クラス定義に実行される
     def hello
       p self, self.class        # このメソッドが呼び出されたときに実行される
     end
    end
    Hello.new.hello
    


    を実行してみましょう。ここで p というのは、デバッグなどのためにRubyに組み込まれている印字メソッドで、引数で渡された各オブジェクトの文字列表現(Object#inspectの結果)を改行文字付きで出力します(TodoItemクラスの定義にpの呼出を埋め込んで試してみるのもよいでしょう)。結果は:

    Hello
    Class
    #
    Hello
    


    となりました。この結果から:

     ・クラス定義が実行されたときのselfは、ClassクラスのインスタンスオブジェクトであるHello

     ・インスタンスメソッドhelloが実行されたときのselfは、Helloクラスのインスタンスオブジェクトである#

    ということがわかります(注: 2つめの p が実行されるのは、クラス定義時ではなくメソッド呼出時)。

    以上のことから、TodoItemのクラス定義における attr_reader メソッド呼出時のレシーバとなるオブジェクトは、「ClassクラスのインスタンスオブジェクトであるTodoItem」ということになります。Rubyでは

     Classクラスのインスタンスメソッド=クラスメソッド(のようなもの)

    なので、attr_reader もクラスメソッドのようなものということになります。

    ここで、ちょっと遠回りになりましたが、前回、構文糖衣の例として上げた、真偽値を返すアクセッサを宣言するための構文糖衣 attr_predicate の定義に戻ります。ここまでのことから、attr_predicate を TodoItem のクラスメソッドとして定義できそうだ、ということが見えてきたでしょうか。以下は、attr_predicate を TodoItem のクラスメソッドとして定義したものです。

    class TodoItem
    
     # クラスメソッドattr_predicateの定義 (このselfはClassクラスのインス
     # タンスであるTodoItem)
     def self.attr_predicate(*names)
       names.each do |name|
         define_method("#{name}?") do
           instance_variable_get("@#{name}") ? true : false
         end
       end
     end
    
     attr_reader    :summary
     attr_writer    :done
     attr_predicate :done
    
     def initialize(summary)
       @summary = summary
     end
    end
    


    このクラスを使って

    item = TodoItem.new("りんご味Rubyの原稿を書く")
    item.summary      # → "りんご味Rubyの原稿を書く"
    item.done?        # → false
                     # ...
    item.done = true  # 原稿を書いたので「完了」とする
    item.done?        # → true
    


    というようなプログラムを実行することができます。ポイントはattr_predicate 宣言によるアクセッサメソッドの done? です。

    こうして、attr_predicate という(疑似)構文糖衣を使うことが出来るようになりました。しかし、クラス定義のたびに、attr_predicate をクラスメソッドとして定義するのではあまり意味がありません。attr_predicate も、attr_reader や attr_writer と同様に、クラス定義時には暗黙で使えるようにしたいですよね。ということで次回に続きます。

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

     前回の終わりが「渡辺久美子って誰だって? それはあなた「ケロロ軍曹」を演ってる声優のひとであります。では次回はそのアイディアについて」だったので,なんかオレが今回の原稿で「渡辺久美子のアイディアについて書く」と思って妙なことを期待してるヒトがごく一部にいた(?)ようだがそれは文脈を取り違えてる。

     そーではなくて,ゲームのアイディアの話です。そもゲームのアイディアというのはそうそう路傍の石のようにそこらにごろごろと転がっているものなのか。そうぢゃないよね?

     そりゃあ,テトリスに限らず今流行りの数独だってオセロゲームだって,時代を遡れば囲碁将棋麻雀の類だってモトはと言えばニンゲンの考えたものでは,ある(いや「ヒカルの碁」によれば囲碁界には「囲碁は神の考えたゲーム」って説もあるんだけど)。

     だから,ある朝あなたが目覚めたら,今まで誰も考えたことがなく,それでいて一度やったら誰もがヤミツキ,やめられないとまらないのエビセン的面白さがあり,しかもコンピュータにインプリメントするのも簡単で,かつ作成するのにコストのかかる可愛らしいキャラクターやコワいモンスターのCGも要らず,そしてできれば他人が真似をするのはちょっと難しい……みたいなゲームが頭の中にでき上がっていたんですよあっはっは,というようなことが今後ないとは,言いきれない。

     でもそういうのはやっぱりマレだと思うでしょ? 宝くじで2億円当たってそれが原因で殺されるほどマレではないとしても,ただ宝くじで2億円当たるくらいにはマレぢゃないですか?

     ちうか,前々回にオレが「ゲームを作って一発当てる可能性」と書いた時に,あなたの頭のなかに上のようなシチュエーションが浮かんだか,というと浮かばなかったでしょ? もし違ったらごめんなさいだけど,大方のヒトの頭に浮かんだのは,前回オレが「第1群」と分類した「ありもののコンピュータ版」か,「第2群」にしてもテトリスではなく,例えば「ドラクエ」や「ファイナルファンタジー」,その他オレが知らないだけでそのスジでは有名なゲームのシリーズ……すなわち,アイディアというよりはビジュアル,アルゴリズムよりもシナリオがメインのものだったと思うのだ。

     が,ここで思い出して欲しいのは,ずっと前にここに書いた「ソフトウエアの独立性」の話である。……もう一度同じことを書くのは嫌なので,覚えていないヒトは #135〜137あたりを読み返してくだされ。……あの議論を踏まえると,あなたが思い描いたようなゲームの製作というのはなんちうか,とってもとってもとってもとってもリスキーな事業なんだよね。

     いっすか(ちょいと渡辺久美子入ってるな)? 今を去ること7年前,大ヒットゲーム・シリーズ「ファイナル・ファンタジー」の制作会社であるスクウェア(現スクウェア・エニックス)は,ハリウッドに進出,大枚1億3700万ドルをかけて全編フル3DCGのアニメ映画「ファイナル・ファンタジー」(英語では「Final Fantasy:The Spirits Within」)を作った。あれ,どのくらい
    の興行収入を上げたかというと全米で3200万ドルだそうな。なんでもギネスブックにも載ったほどの大コケで,スクウェアが計上した特別損失が130億円……これでどっかに「ファイナルファンタジーの権利を10億で買いませんか?」とか言ってりゃ今ごろ逮捕されてるかも知れんという……いや,それは別の話っすね。

     斯様にどでかい損失を出した映画「ファイナル・ファンタジー」であったが,それでもその後まったく金を産まなかったわけではない。一応4年後のクリスマスイブには地上波でも放映されいくばくかの放映権料が入ったし,DVDだって売っている。あんな映画のDVD誰が買うんだと言うなかれ。「デビルマン」のDVDだって買うヤツはいたのである。

     ここで一つ思考実験。大コケしたのが映画ではなく本家のゲームの方だったらどうだったか?
    (以下次回 2008_11_06)                     

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

    プログラマのためのオブジェクト指向再入門(52)

    〜XcodeによるPowerPlant X入門(35)〜

     こんにちは、高橋真人です。早速続けます。
     ようやくアタッチメントを外すためのViewを得るところまで説明が終わりました。残っている部分はそんなに複雑ではないので、ざっと見ていきましょう。

     前回までのお話で、Viewを検索した時に指定した100という識別子の値ですが、これはViewの生成時に設定している値です。また、アタッチメントを付けるのもViewの生成直後に行っているわけです。
     MyApplication.cpのDoSpecificCommand()の中にその実際のコードがありますので、参考にしながら読んでいただきたいのですが、アタッチメント(MyViewAttachment)は単純にnew演算子で生成を行います。そして、初期化をしてからViewにアタッチします。
     アタッチメントを外す時にはこの逆の手順になります。アタッチされていたViewを見つけたら、今度はそのViewに対して外すべきアタッチメントの検索をします。何故いちいち検索などということをする必要があるかと言えば、アタッチメントは一つのオブジェクトに対して複数アタッチすることができるからです。
     今回のプログラムでは、MyViewAttachmentのインスタンスを特定するために、kMyViewAttachmentという定数を指定しています。これはUInt32の値です。
     外すべきアタッチメントが見つかったら、Viewに対してそれを取り外すように依頼するわけです。MyWindow.cpのDoWindowDeactivated()、これは前回まで説明していた部分です。ここで、Viewの取り外しを行っていますが、コードは以下のような感じです。

     

      MyViewAttachment *attachment =
           PPx::SafeDynamicCast
           (view->FindAttachmentByID(kMyViewAttachment));
       if (attachment) {
           view->RemoveAttachment(attachment);
           delete attachment;
       }
    


     RemoveAttachment()という関数が、取り外しを行う処理ですが、そのあとにdelete演算子でattachmentを消去していますね。何故これがあるかと言えば、Viewはアタッチメントをポインタの配列として保持しているからで、単に“外した”だけではアタッチメントのインスタンスが存在したままだからです。いわゆるメモリリークの状態です。
     ところが、このdelete演算子には、単にメモリリークを防ぐというか、メモリの後始末をするという以上の意味があるのです。
     実際、このdeleteの行をコメントアウトしてプログラムを動かしてみると、不思議や不思議、ボタンにかぶさった青い覆いは何度Windowを切り替えようが、ずっと残ったままになります。ちゃんとRemoveは行われているのに、です。
     アタッチメントという名前が付けられているこの仕組みですが、実のところ、特定のオブジェクトにアタッチされているかどうかは関係がなく、単に、Initialize()の時に対象のオブジェクトを指定しただけでこのアタッチメントの“動作を変更する”対象は決まってしまっています。
     ただ、Viewにアタッチしておかないと、後で外す時にそのアタッチメントを特定することが難しいために、“便宜上”Viewに持たせる格好にしているということなのです。
     以上の説明でお分かりになった方もおいでと思いますが、PPxのアタッチメントは、そのインスタンスが消去される時点で内部に仕組まれていたイベントハンドラが始末されます。アタッチメントによって暫定的に加えられていた、このイベントハンドラが取り除かれることにより、“本来の”イベントハンドラがそのまま機能するようになるわけです。
     といった感じで、「説明は終わり」と言いたいところですが、ここで素朴な疑問。では、アタッチメントにおけるイベントハンドラはどこに仕込まれていて、消去される時にどのようにイベントハンドラが取り除かれるのでしょう?
     常識的に考えれば、MyViewAttachmentかそのいずれかの継承元のどこかに、イベントハンドラを保持する何らかのクラスがメンバ変数として保持されていると考えるのが自然です。ところが、いくら探してもそのようなメンバ変数はありません。これは一体どうしたことでしょうか?
     実は、この辺にも、PowerPlant Xのちょっとした面白い仕組みが隠れています。次回はその辺を探ってみたいと思います。

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

     

     MOSA Developer News   略称[MOSADeN=モサ伝]
            配信停止 mailto:mosaden-ml@mosa.gr.jp
     記事内容に関するご意見 mailto:mosaden-toukou@mosa.gr.jp
          記事投稿受付 http://www.mosa.gr.jp/?page_id=850
    Apple、Mac OSは米国アップル社の登録商標です。またそのほかの各製品名等
    はそれぞれ各社の商標ならびに登録商標です。
    このメールの再配信、および掲載された記事の無断転載を禁じます。
    特定非営利活動法人MOSA  http://www.mosa.gr.jp/
    Copyright (C)2007 MOSA. All rights reserved.

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

    2008-11-04

    目次

    • 「Wonderful Server Life」    第80回   田畑 英和
    • 小池邦人のCarbon視点でCocoa探求
    • ターミナルの向こうから      第35回  海上 忍 

    「Wonderful Server Life」  第80回  田畑 英和

      〜「iCalサーバ」編〜

     Leopardがリリースされてから1年になります。そろそろLeopard Serverの導入も増えてきているかと思いますが、せっかくLeopard Serverを使うのでしたら新サービスにもチャレンジしてみたいところです。
     そこで今回からLeopard Serverで新しく追加されたサービスについて解説していきます。まずはiCalサービスから解説いたします。

    ◇iCalサービス
     そもそもiCalサービスとはなにかということですが、iCalサービスを利用すれば、Mac OS Xに標準でインストールされている「iCal」を使って作成したスケジュール情報を、サーバに保存して一元管理することができます。
     もちろん複数のユーザをサポートしていますし、制約はありますが他のユーザのスケジュールも確認することもできます。つまりユーザごとのスケジュールをサーバ上で一元管理するわけですが、iCalサービスはOpen Directoryと統合されていますので、Open Directory上に登録したユーザであればiCalサービスを利用することができます。

    ◇iCalサービスのセットアップ
     iCalサービスを動かす方法は非常に簡単です。まずサーバが標準構成であればシステムをセットアップするだけで自動的にiCalサービスが起動します。
     また、実際にiCalサービスを利用するにはユーザごとの設定も必要になりますが、標準構成の場合は「サーバ環境設定」でユーザを登録するだけで自動的に必要な設定が行われます。もっともこれはユーザ登録時にiCalサービスが起動していることが前提となります。もしユーザ登録時にiCalサービスを停止していた場合には、「サーバ環境設定」のユーザ管理画面のサービスの設定でiCalサービスを有効にすれば自動的にiCal関連の設定が行われます。

     次にサーバが詳細構成だった場合です。少し手間は増えますがかといって特に難しいわけではありません。まず「サーバ管理」でiCalサービスを開始します。設定可能なオプションがいくつかありますがとりあえず起動するだけなら、デフォルトの設定のままサービスを開始するだけです。セキュリティを高める場合はSSLを有効にするといったこともできます。iCalはWebDAVをベースとしたCalDAVというプロトコルを使っていますが、デフォルトでは8008番ポートを、SSLを有効にした場合には8443番ポートで通信を行います。
     サーバが詳細構成の場合はさらにユーザごとの設定も必要になります。ユーザを登録した後に「ワークグループマネージャ」の「詳細」設定画面で使用するカレンダーホストの設定を行います。iCalサービスを起動していればカレンダーホストのリストに自動的に適切な候補が表示されます。

    ・カレンダーホストの設定
    http://www.htabata.com/img/MXS105/iCal/WGM_01.png

     この設定項目がちょっと分かりにくく、日本語環境では「スケジュール管理を有効にするメンバー」という名前の設定項目になっています。ところが英語環境での表示をみてみると「Enable calendaring」となっています。いったいどう翻訳すればこうなるのでしょうか。とにかくユーザごとの設定も必要になるということです。これはサーバが標準構成の場合でも、「ワークグループマネージャ」でユーザを追加した場合にはやはり手動での設定が必要になります。また、標準構成の場合はデフォルトでサービスのACLが有効になっていますので注意が必要になります。標準構成の場合はとにかく「サーバ環境設定」で設定をしたほうがなにかとお手軽です。

    ◇iCalサービスへのアクセス
     サーバ側の準備が整ったら次はクライアント側のセットアップです。まずクライアントをOpen Directoryのサーバにバインドします。サーバが標準構成であればこのときにiCalのアカウント設定も自動的に行うことができますが、今回は手動での設定方法をみておきましょう。
     まず「iCal」を起動して環境設定の「アカウント」画面を表示します。ウインドウの左下にある「+」ボタンをクリックしてあらかじめOpen Directory上に登録しておいたユーザのユーザ名とパスワードを入力します。デフォルトの状態ではこのときセキュリティに関する警告が表示されますが、SSLを有効にしたりKerberos認証を使用することによってセキュリティを高めることができます。

    ・アカウントの登録
    http://www.htabata.com/img/MXS105/iCal/iCal_01.png

     アカウントの設定が完了すれば、ローカルのカレンダーに加えiCalサービスを利用してサーバ上のカレンダーも使えるようになります。サーバ上のカレンダーとしてはデフォルトで「calendar」という名前のカレンダーが用意されています。名称を変更したりサーバ上のカレンダーを追加することもできます。

     とうわけで今回はiCalサービスのセットアップについて解説しました。次回も引き続きiCalサービスについて解説する予定です。
    次回へつづく                             

    小池邦人のCarbon視点でCocoa探求(2008/10/24)

     〜 起動時とドラッグ&ドロップでの登録 〜

    今回は、ImageBrowserへの画像登録の「別の道筋」である「アプリ・アイコンへのドロップで新規ウィンドウを開き画像を登録」と「ドラッグ&ドロップでウィンドウに画像を追加登録」について解説いたします。

    まず最初は「アプリ・アイコンへのドロップで新規ウィンドウを開き画像を登録」についてです。この処理の実行には、NSApplicationのデリゲート(NSApplicationDelegate)であるapplication:openFiles:メソッドを実装します。ユーザが、画像ファイルやフォルダをアプリ(もしくはドッグ)アイコン上にドラッグ&ドロップすると、このメソッドが呼ばれるわけです。
    NSApplicationにどのようなデリゲート・メソッドが存在しているかは、NSApplication.hを参照してみてください。

    - (void)application:(NSApplication *)sender openFiles:(NSArray *)filenames
    {
       MyDocument        *mydoc=nil;
       NSMutableArray    *files=nil;
       NSError           *err=nil;
       NSString          *path;
       int               i,ct;
       BOOL              dir;
    
       ct=[filenames count]; // 情報にいくつのパス名が含まれているのか?
       for( i=0;i
    


    この場合、アイコンにドロップされるファイルは画像ファイルやそれを含んだフォルダだけではなく、「しんぶんし 3.0」自身のドキュメントファイルである可能性もありますので注意してください。その場合には、通常のドキュメント・オープン処理となります。

    続いて「ドラッグ&ドロップでウィンドウに画像を追加登録」する方です。Cocoaアプリケーションで「ドラッグ&ドロップ」を実現するには、ドロップ先のオブジェクト(例えばNSViewなど)に、以下の6つのメソッド(NSDraggingDestinationプロトコル)を実装します。ちなみに、Mac OS X 10.5以降では1つ増えて7つになったようです。

    - (NSDragOperation)draggingEntered:(id )sender;
    // ドラッグがエリアに入った場合
    - (NSDragOperation)draggingUpdated:(id )sender; 
    // エリア内にいる場合
    - (void)draggingExited:(id )sender;
    // エリアから出た場合
    - (BOOL)prepareForDragOperation:(id )sender;
    // 受け入れ処理がOKかどうか
    - (BOOL)performDragOperation:(id )sender;
    // 受け入れ処理を実行
    - (void)concludeDragOperation:(id )sender;
    // 処理が終了した
    - (void)draggingEnded:(id )sender;
    // Mac OS X 10.5以降のみ
    


    Carbonでドラッグ&ドロップを経験されている方は、どのメソッドがどんな処理を担当するのか、そのメソッド名からほぼ理解できると思います(笑)。ImageBrowser上へのドラッグ&ドロップに関しては、このうちの3つだけを、デリゲートとして用意したオブジェクトに実装すればOKです。デリゲートは、MyDocumentクラスのawakeFromNibメソッドにおいて
    setDraggingDestinationDelegate:メソッドを使いセットします。今回のセット先は自分自身(self)です。

    - (void)awakeFromNib
    {
       [imageBrowser setDraggingDestinationDelegate:self]; // デリゲートをセット
       [imageBrowser setAllowsMultipleSelection:NO]; 
       [imageBrowser setAllowsEmptySelection:NO];
       [imageBrowser setZoomValue:0.5];
    }
    


    以下が、実装しなければいけない3つのメソッドですが、そのうち2つの実装は簡単でして、単純にNSDragOperationCopy(定数)を返すだけです。

    - (NSDragOperation)draggingEntered:(id )sender
    {
       return NSDragOperationCopy;
    }
    
    - (NSDragOperation)draggingUpdated:(id )sender
    {
       return NSDragOperationCopy;
    }
    


    最後のperformDragOperation:メソッドに実際の画像登録処理を記述します。このメソッドでNOを返すと、ドロップしたアイコンが元の場所へ戻っていくアニメーションが実行されるわけです。

    - (BOOL)performDragOperation:(id )sender
    {
       BOOL            ret=NO;
       NSArray         *paths;
       NSData          *data;
       NSString        *err;
       NSPasteboard    *pb;
    
       pb=[sender draggingPasteboard]; // 渡されたペーストボード・オブジェクト
       if ([[pb types] containsObject:NSFilenamesPboardType] )  // ファイル名ある?
       {
           if( data=[pb dataForType:NSFilenamesPboardType] ) // そのデータを抽出
           {
               paths=[NSPropertyListSerialization propertyListFromData:data
                       mutabilityOption:kCFPropertyListImmutable format:nil 
                                                     errorDescription:&err];
                                                   // 対象となるパス名を得る
               [self addImagesPaths:paths]; // パス名を使い画像の登録を行う
               ret=YES; // ドラッグ&ドロップ処理は正しく実行された
           }
       }
       return ret;
    }
    


    次回は「ImageBrowserで選択した画像をいかに対称表示させるのか?」についてCore Graphics APIに関する解説をしたいと思います。が、ここからの話は少しCocoaから離れてしまいいますので、iPhone SDKのNDAも解除されたことですし、ひょっとすると連載そのもを方向転換するかもしれません(笑)。

    ターミナルの向こうから      第35回  海上 忍

    〜 いま敢えて学ぶTerminalのイロハ(2) 〜

    ・シェルのお約束

     ターミナルを起動すると、コンピュータ名に続いて「$」が表示され、カーソルが点滅するコマンド入力待ちの状態となります。キーボードからの情報を受け付け、必要であればdeleteキーやカーソルキーなどを利用した編集を行い、プロンプト横に表示したうえでコマンドとして実行する、という一連の流れはシェルの機能によるものです。
     ここで理解しておきたいのは、シェルは基本的に「スクリーンエディットに非対応」ということです。たとえば、適当な文字列を入力し、その途中から編集を行おうとマウスでクリックしても、その位置へカーソルを移動することはできません。
    これは、シェル(bash)がCocoa/CarbonのAPIを使用しないためであり、行編集機能を依存するGNU readlineライブラリの操作体系に従う必要があります。
     ターミナルの画面にコピー&ペーストできるが? と疑問を持つ方もいらっしゃるかもしれませんが、ターミナルは(テキスト情報の)表示を担当するに過ぎません。その意味で、シェルはIME(Input Method Editor)的な役割を担うプログラムであり、IMEとしてのシェルの機能を理解することがターミナルに慣れる最初の一歩、ということができます。

    ・bash/readlineの編集機能(1)

     それでは、シェルの編集機能を具体的に説明してみましょう。前述のとおり、bashはGNU readlineの機能を利用するため、正確にはreadlineの使い方であることをあらかじめお断りしておきます。
     例として、「mosaden」と入力してください。「n」の右横でカーソルが点滅/入力待ちの状態になると思います。ここでControl-a(以下、Controlキーは「C」と省略)を押すと……カーソルは、行頭の「m」の上に移動するはずです。これは、readlineの持つ編集機能の1つです。同様に、C-e(行末への移動)、C-b(1文字後退)、C-f(1文字前進)など、カーソルの移動にはショートカットキーを利用できます。
     それら編集機能は、キーを押下しreadlineの内部コマンドを発生することにより処理されています。C-aでカーソルを行頭へ移動する処理は、実際にはreadlineの「beginning-of-line」という内部コマンドを実行しています。1文字前進は「forward-char」、1文字後退は「backward-char」です。それら内部コマンドが、bash/readlineの初期設定にしたがい、C-aやC-bなどのキーコンビネーションが割り当てられた(キーバインディング)うえで呼び出されているにすぎません。
     それらキーバインディングを一覧することもできます。次に示すbashの内部コマンド「bind」に、オプションの「-p」を与えて実行すれば、450行前後の設定情報が表示されるはずです。

    - - - - -
    $ bind -p
    - - - - -
    


    ・bash/readlineの編集機能(2)

     シェルの基本機能は、入力された文字列を解釈しコマンドとして実行する「コマンドインタープリタ」ですが、GUIがない/洗練されていない時代はシェルが主要なユーザインターフェイスとして利用されていたこともあり、ユーザビリティ向上のために多くの支援機能が追加されてきました。
     実行したコマンドラインを記憶しておく「ヒストリ(履歴)機能」は、数ある支援機能のなかでも覚えておきたいものの1つです。試しに適当なコマンドを実行し、C-pを押してください。直前に実行したコマンドラインがプロンプト横に現れ、enterキーを押下するだけで実行可能な状態にお膳立てしてくれます。この機能を使えば、長くなりがちなコマンドラインを何度も入力せずに
    済みます。
     ヒストリ機能は、bash/readlineが実行したコマンドを、ホームフォルダ直下の「.bash_history」というファイル(~/.bash_history)に保存しておき、「previous-history」という内部コマンドを使い参照することにより実現されています。前述の「bind -p」で調べるとわかりますが、上方向のカーソルキー(↑)を押すことでも、まったく同じ操作が可能です。

    ・機能を組み合わせると……
     最後に、編集機能とヒストリ機能を使った「合わせ技」を紹介してみましょう。GUIと目指すところは異なりますが、シェルの操作性に洗練を感じることができると思います。
     たとえば、「docs.zip」というZIPファイルを(unzipコマンドで)内容確認し、安全と判断したうえで解凍する状況を考えてみましょう。素直に作業すれば、以下のコマンドラインを1文字ずつ入力しなければならないはずです(「-t」は書庫ファイルの内容を確認するためのオプション)。

    - - - - -
    $ unzip -t docs.tgz [enter]
    $ unzip docs.tgz [enter]
    - - - - -
    


     このコマンドラインを見ると、「unzip」と「docs.tgz」という文字列が完全に重複していることがわかります。そこで利用するのが、bash/readlineのヒストリ機能と編集機能です。以下のコマンドラインを見てください。かなり効率化されたことがわかります。例ではファイル名が短めでしたが、長い場合にはさらに作業時間を短縮できると思います。

    - - - - -
    $ unzip -t docs.tgz [enter]
     [C-p]  ←直前に実行したコマンドラインを呼び出す
    $ unzip -t docs.tgz  ←履歴が現れる
     [C-b]を何度か押し、カーソルを「-」の上へ移動
     [delete]を2回押す
    $ unzip docs.tgz [enter]  ←履歴を編集した
    - - - - -
    

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

     

     MOSA Developer News   略称[MOSADeN=モサ伝]
            配信停止 mailto:mosaden-ml@mosa.gr.jp
     記事内容に関するご意見 mailto:mosaden-toukou@mosa.gr.jp
          記事投稿受付 http://www.mosa.gr.jp/?page_id=850
    Apple、Mac OSは米国アップル社の登録商標です。またそのほかの各製品名等
    はそれぞれ各社の商標ならびに登録商標です。
    このメールの再配信、および掲載された記事の無断転載を禁じます。
    特定非営利活動法人MOSA  http://www.mosa.gr.jp/
    Copyright (C)2007 MOSA. All rights reserved.