MOSA Multi-OS Software Artists

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

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

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

MOSADenバックナンバー 2009年6月発行分

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

    2009-06-30

    目次

    • WWDC2009初参加レポート           今井 敬子
    • 「Wonderful Server Life」    第95回   田畑 英和
    • 小池邦人のCarbon視点でiPhone探求
    • ターミナルの向こうから      第50回  海上 忍 

    WWDC2009初参加レポート                 今井 敬子

    始めまして。コムシス東北テクノの今井敬子と申します。
    昨年からiPhoneアプリの開発を始めました。他には、Android、Nintendo DSi、PSP等のアプリ、Webアプリの調査、開発等にも携わっております。今年、初めてWWDCに参加しましたが、このたび、初参加の感想を書かせていただけるとのお話をいただきました。
    以下の項目ごとに、感じたこと、考えたことをお伝えできればと思います。

    1.出発前

    出発前に、MOSAで企画された「事前交流会」と「英会話&異文化マナー講座」に参加させていただきました。
    事前交流会は、MOSAに入会したばかりで、かつ初めて参加させていただいた企画だったので、初めこそ緊張しましたが、色々な方とお話をすることができました。また、渡航前にやること等の説明や、WWDCの歩き方等の資料をいただき、WWDCまでにやっておくべきことを整理できたのが良かったです。

    英会話&異文化マナー講座では、ネイティブの講師の方と英語で沢山会話させていただいたことも良かったですが、現地の人の会話の特徴や「名刺は最初に渡すものではない」「握手が弱いと変に思われる」等、日本とは異なる習慣や考え方についてレクチャーしていただけたのが大変ためになりました。(実際、現地の方の握手はかなり力強かったです。2回ほどしかその機会はあ
    りませんでしたが・・・)

    私は今回、弊社からは一人で参加したのですが、WWDC開催中は、これらの企画の場で知り合った方々と日程の多くをご一緒させていただくことができ、大変心強かったです。
    また、一人で行動していたら気付かなかったであろう様々な事を教えていただきました。
    WWDC前に、多くの方とお知り合いになれて本当に良かったと思っています。

    2.英語に関して

    WWDC参加にあたって、一番不安だったのが「英語のセッションを聞いて果たして分かるのか」という点でしたが、プレゼンの資料を見ながらだったせいか、思っていたよりもセッションは理解できました。ただ、スピーカー次第の部分もあり、セッションによっては、ついていくのが困難だったものもあります。かなり楽しみにしていたセッションで、喋るのは早い、メモを取っているうちにスライドが2、3枚進んでしまう、といった感じになってしまい、途中でメモするのを放棄したものもありました。

    Attendeeサイトで資料が公開されているのである程度フォローできますが、やはりもう少し耳で理解できるようになりたいと思います。また、プレゼン後に質問を受け付けるセッションが多数ありましたが、プレゼン時の話し方よりもスピードが速く感じられ、あまり理解できなかったのが残念です。

    3.WWDCで得られた事

    いざ参加すると、「せっかくここまで来たんだから、モノにして帰ろう」という欲が湧きます。
    また、何よりもAppleの担当者から情報を入手できる、またとない機会です(社会人になってしまうと、興味のある技術の説明を受ける機会自体、貴重だと思います)。セッションで聞いた事などは、想像していた以上に頭に入ってきた感じがします。まだ新機能のほとんどは使っておらず、実践はこれからですが、OSリリース後にドキュメントを自力で読み始めるのとは比べ物にならないくらいの収穫を得たと思っています。

    また、多くのデベロッパと交流できたことが、大変良い刺激になりました。色々な方が作ったアプリを見せていただき、直接質問等できるのが大変楽しかったですし、有意義でした。

    一方、反省点もあります。
    何より悔やまれるのは、準備不足であったことです。
    今回私は、ほとんどiPhone OS3.0に触れないまま参加してしまいましたが、もし、もう少し新機能の概要等掴めていれば、深い切り口でセッション等に臨めたと思います。

    また今回、iPhone OSのオーディオ関連で質問したい点があったのですが、質問するためのサンプルコードの準備がオーディオ関連のラボまでに間に合わず、Open Hoursに質問するのが精一杯でした。何とか聞きたかったことの半分くらいは達成したのですが、いざ持ち帰って再度試してみると別の疑問が出てきてしまいました。
    ちゃんと準備ができていれば、ターゲットのラボで質問し、追加の疑問はOpen Hoursで解消する等、もっと有意義にラボを活用できたのではないかと思います。

    ひとつ想定外だったのは、WWDC期間中、思ったほど時間の余裕がなかったことです。
    出発前には、「間に合わない分はWWDC期間中の夜にでも準備すればよい」とのんきに構えていましたが、WWDCが始まってしまうとそんな余裕は全くありませんでした。恐らく、セッションを聞くのに想像以上の体力・気力を使ったことが一番の原因だと思います。
    もし次回も参加できるならば、ちゃんと備えをして臨みたいです。

    4.気候について

    涼しいとは聞いていたので、日本でWWDCの時期に着ていたら暑いと感じるであろう程度の衣料は持っていきました。しかしそれでも寒いと感じる時がありました。日中の一瞬だけ、日が差して汗ばむ陽気になりますが、朝も夜も結構冷えます。また、風が吹いている時間が長く、それも寒く感じる一因でした。キーノートで朝から並ぶ際や、野外でのパーティなどは、薄手のコート等あった方が安心かもしれないと思います。

    気温の低さは予想以上でしたが、幸い天候に恵まれ、きれいな空の下で、気分良く一週間を過ごすことができました。
    あまり観光はできませんでしたが、お昼休みが長いので、会場付近の散策ができました。
    パウエル駅周辺の、様々なショップを見ているだけでも楽しかったです。

    以上を持ちまして、感想とさせていただきます。
    最後になりましたが、WWDC期間中にお世話になった皆様に、この場をお借りしてお礼申し上げます。
    本当にありがとうございました。

    ◆執筆者プロフィール
    コムシス東北テクノ 今井敬子

    昨年からiPhoneアプリの開発を始めました。Macでの開発はこれが初めてで
    す。その前は、主にWebアプリケーションの開発を行っていました。
    http://www.comsys-tt.co.jp/

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

    〜「Snow Leopard Server」編〜

     WWDCで発表のあったiPhone 3GSが6/19に米国で発売されました。最初の週末で100万台以上の売上を達成し、そして6/26には日本での発売も始まりました。
     WWDCで発表のあったのはiPhoneだけではありません。次期OSのSnow Leopardもその詳細が明らかになってきました。今回は予定を変更してサーバ版のSnow Leopard Serverについて紹介していきます。

    ◇Snow Leopard Server
     まず発売時期などの概要ですが、クライアント版のSnow Leopardと同様9月に出荷開始とだけアナウンスされています。これまでクライアント版とサーバ版は同時に発売されていましたから、おそらく今回もそうなるでしょう。
     クライアント版はMac OS X Leopardからのアップグレードが29ドルというこれまでにない超低価格で発売されることが発表され話題になりましたが、サーバ版のMac OS X Server Snow Leopardは無制限ライセンスが499ドルとこれまでの半額程度の金額になります。日本円での価格はまだ発表されていませんが、Mac miniと組み合わせれば10万円台からサーバが構築できることになりそうです。
     これまでは、AFPおよびSMBに接続数の制限があった10クライアントライセンス版もあったのですが、Snow Leopard Serverではどこにも記述がないことから無制限ライセンス版のみに統一されるのではないでしょうか。ちなみにこれまでは10クライアントライセンス版の価格が499ドルでした。

     Snow Leopard Serverの動作環境ですが、Leopard Serverと比較すると以下のようになっています。

     Snow Leopard Server:Intel CPU、2GBのRAM、10GBのディスクスペース
     Leopard Server:Intel/PowerPC G5/PowerPC G4(867MHz以上)
             1GBのRAM、20GBのディスクスペース

     まずCPUがIntel専用となっています。すでにすべての製品ラインがIntelに移行しているわけですが、いよいよPowerPCが動作環境から外れることになります。メモリは最低2GBのRAMが必要となっていますが、これはLeopard Serverの倍の容量となっています。ただしハードディスクのディスクスペースは半減し少なくとも10GBとなっています。OSがスリム化したことでディスクスペースが節約できるということですね。

    ◇Snow Leopard Serverの新機能
     クライアント版のSnow Leopardは新機能の追加よりも、基盤の強化に力を入れていますが、サーバ版では色々と新機能の追加があります。まず新サービスとしてAddress Book ServerとMobile Access Serverが追加されます。
     Address Book Serverではユーザごとに「アドレスブック」で管理するコンタクト情報をサーバで管理できるようになります。これにはCardDAVというプロトコルを使用します。
     Mobile Access Serverでは、VPNを使わずにインターネットから会社内などのプライベートなネットワークに安全にアクセスできる環境を提供します。クライアント側でのソフトウェアのインストールや設定は必要なく、メールやカレンダーサービスなどにアクセスでき、iPhoneからも利用可能です。

     既存のサービスもさらに強化されます。Leopard Serverで新登場したiCal Server、Podcast Producer、Wiki Serverがそれぞれバージョンアップします。
     iCal Serverではこれまで「iCal」などCalDAVに対応したクライアントソフトが必要でしたが、これからはWebブラウザベースでの利用も可能になり、さらにiPhoneからのアクセスも可能です。
     Podcast Producerでは新たにデュアルソースのキャプチャに対応し、カスタムワークフローを作成する「Podcast Composer」が新たに搭載されます。
     Wiki ServerではなんとQuick Lookを搭載し、Webブラウザ上でプレビューが表示できるようになります。またiPhoneからのアクセスにも対応しています。
     
     さらにメールサービスがプッシュメールに対応するなど、他のサービスでも様々な改良が加えられています。またパフォーマンスの向上も期待できます。

    ◇アップル技術者認定資格試験・認定トレーニング
     さて話は変わりまして、最後に認定試験/トレーニングについて取り上げます。日本ではPantherのころからアップル社のIT技術者向け認定トレーニングが実施されてきましたが、ようやくLeopardに対応したコースが実施されることになりました。ダイワボウ情報システムが新たにアップル公認のトレーニングセンターを開設し、2つのトレーニングコースを7月から東京と大阪で開催
    し、順次全国7カ所に展開する予定になっています。
     またトレーニングだけではなく、アップル技術者認定試験も実施され、こちらも全国展開が予定されています。
     
    ・ニュースリリース
    http://www.pc-daiwabo.co.jp/release/090624.html
                                 次回へつづく

    WWDC 2009に思う(2008/06/26)       小池邦人

    6月8日(日本では 6月9日の深夜)Steve Jobs CEO不在のまま、Philip Schiller副社長によるキーノート(基調講演)でWWDC 2009が開幕しました。
    「今回はJobs不在だからねぇ…」と油断していると痛い目に遭うと思い、キーノート待ち行列には午前6時前から並びました(前回より早い)。予想は的中、待ち行列は昨年以上の延びを示し、大きな会場をぐるりと一回り囲んでしまいました。今年の参加状況も「満員御礼!」です。会場に遅く到着した人の中には「オーバーフロールーム」(会場へ入れなかった人が映像のみ鑑賞す
    る部屋)からもオーバーフローしそうになったという話も流れていました(笑)。行列の付近には、お馴染みのMacTechマガジン配布チーム、Tシャツや小物の投げ込みチーム、ドングルSDKを配布するメーカ、iPhone用ポルノサイトを宣伝する水着のお姉さんを乗せた馬車まで登場し、退屈な待ち時間を存分に楽しむことができました。

    Philip Schiller副社長(このために少し痩せたのか?)のちょっと緊張気味の司会と、担当重役のそつのないナビゲートでキーノートも順調に進みました。何とか笑いを取ろうとした場面がことごとく失敗に終わったのは、まあ愛嬌です(笑)。WWDCのセッション内容はNDA(秘密保持契約)扱いで詳細開示は不可ですが、キーノートはNDA適用外なので、その概要については、既に関連サイトに多数掲載されています。今回も詳細については、そちらにお任せしたいと思います。噂通りにiPhone 3GSが登場しましたし、低価格MacBook Proの発売、Snow Leopardの最終日程と驚きの$29バージョンアップの発表など、ネタ的には十分満足できるキーノートだったと感じました(不満はCEOの不在のみ?)。ただし、iPhone OS 3.0やSnow Leopardの機能は既に発表済みの内容だったわけで、ソフト屋としては「次の一手」が何も示されなかった点に、若干のモヤモヤを感じたことも事実です。

    初日はiPhoneのみを所有している参加者が多かったのですが、2日目からは、会場の多くの人がMacBook Pro(17インチ多し)を持ち歩いていました。キーノートでお買い得13インチMacBook Proが発表されたおかげで、それを現地調達して使う人もいたようです(会場のゴミ箱に空き箱が捨てられていた)。ほとんどの人は、セッション内容のメモ取りなどでMacBookを活用しています
    が、後ろから画面を覗くと、自作アプリを一生懸命デバッグしている人も結構いて「ちゃんとセッション聞けよ!」とか、声をかけたくなります(笑)。また「変なデスクトップだな?」と見ると、そのまんまのWindows XPが走っていたりして(昔からLinuxは結構いた)吹き出すことも多々ありました。そうそう、今はやりのネットブックをハックしてMac OS Xをインストール(大胆)している人にも結構遭遇したことも追加しておきましょう。

    昨年のWWDCでは、Apple社のWebサイト(参加者のみ入れる)へと最新スケジュールがアップされ、それをiPhoneやiPod touch(もしくはMac)で参照していたのですが、今回は、iPhone&iPod touch専用の「WWDC09」アプリが用意されていました。それをダウンロードし自分のiPhoneにインストールすることで、参加者は最新のイベントやセッションスケジュールを参照できるわけです。アプリへは逐次最新情報が転送され、未読情報は画面の数値バッチで忠告してくれます。また、別途デバイスへインストールする「Provisioning Profiles」(認証ファイル)も同時配布されたのですが、これがオールマイティ版(デバイス識別子のUIDIを判断しない)と分かり、デベロッパーの中から「この仕組みを利用できるサービス形態が欲しいぞ!」と言う「大きな声」が上がっていたことも付け加えておきましょう(後に追記有り)。

    昨年のWWDCの感想で「美しきスツールのために、次のWWDCでは4本目の足(ビジネス分野への進出)についての戦略を公開して欲しい!」と書いたのですが、残念ながらそちら方面については、Snow LeopardのExchange対応が強調された程度で、これといった大きな発表はありませんでした。当然「Mac OS Xのライセンシング」の話などはこれっぽっちも出ていません。また「パソコンを生産をしていないSunやIBMとMac OS Xがらみで提携したら?」とも書きましたが、そのSunも既にOracleに買収されてしまったわけでして、状況の変化の速さに驚かされる今日この頃です。まあ、Apple社のことですから「抜き足、差し足、忍び足」で、知らない間に自社製品をビジネス分野へジワジワ浸透させていくための準備をしているかもしれません…。iPhoneがらみに関しても、その傾向が見え始めている気もしています。

    今回開催された多くのセッションは「iPhone OS 3.0」関連が中心です。また、全体の60%が初参加だと言うこともあり、「入り口」としての開発環境(Xcode Tools)関連のセッションも活発だったようです。しかし、十数年もWWDCへ通い続けているデベロッパーから見ると、それ以外は「成熟」の極みといった雰囲気が漂っていました。今まで何度も主役を演じてきたQuickTimeも
    QuickTime Xがらみのセッションがひとつだけ、今回はCocoaにしても目新しいトピックスはほとんど無い状況でした(当然Carbonセッションなどは皆無)。
    Snow Leopardで導入予定の、64Bitカーネル、OpenCL、Grand Central Dispatchなども、企業や大学のサイエンス系研究室では大いに力を発揮しそうな技術なのですが、コンシューマに直接結びつくトピックスではないことから、盛り上がり方も今ひとつ限定的なようです。

    しかし、こうした地味なテクノロジーが、OS自身や付属アプリの開発に大いに生かされている可能性は無視できません。つまり、Apple社の自社開発におけるソフトの処理速度の改善や、より強固なシステム構築に大きく貢献しているわけです。そのことは、間接的ですがコンシューマにとっても大きなメリットとなるはずですから、Snow Leopardの登場が本当に楽しみになってきました。さらに気になった点は、キーノートでも見え隠れしていた、Mac OS XとiPhone OSの「統合」の流れです。現在、両OSでは「Core OS」と呼ばれているシステムモジュールが共通で存在しており、その割合は全体の80%を占めます。後は、両OSのユーザインターフェース・フレームワークであるAppKitとUIKitの差異を縮めれば、2つのOSは割と簡単に統合の道を歩むことになります。つまりCPU依存でコンパイルし直せば、MacでiPhoneのアプリが起動し、iPhoneでMacのアプリが起動することになります。

    まあ、統合自体は少し未来の話かもしれませんが、「一歩先を行く」iPhoneアプリの開発を目指し、その先行メリットを得たい開発者は、iPhone OSと同時にMac OS Xの最新テクノロジーも勉強しておくことをお勧め致します。iPhone OS 2.0から3.0では「Core Data」「Spotlight」「OpenGL 2.0」「Pastebord」「VoiceOver(Accessibility)」などが、Mac OS X側から降りてきました。次の機会には「QTKit」「ImageKit」「CoreImage」「QuartzComposer」「Binding」「OpenCL」などが降りてくる可能性があります。逆に、Mac OS Xではトラックパッドによる「Multi Touch」機能が充実してきており、将来的
    にはiPhone OS特有の機能「MapKit」「GameKit」「StoreKit」「LibraryAccess」などが実装されるかもしれません。MacやiPhone(将来登場するかもしれない新デバイスも)を区別せず、総合的にApple社のテクノロジーを習得しておくことは、今後さらに重要性を増すことになるかもしれません。

    今回のWWDCで一番残念だった点は「App Store」の改善について何も言及されなかったことです。iPhone 3.0でアプリ内からコンテンツを購入できる機能は追加されましたが、 App Store自体の機能拡張については何も新しい発表がありませんでした。現在、5万以上の商品が店頭に並べられているApp Storeですが、どうひいき目に見ても、自分の欲しているアプリを簡単に見つけて購入できるという「ショップ」の心地良さはありません。商品数が多くなっていくペースに店舗のリソースの整備が追いついていないわけです。やはり「欲しい商品を見つけてくれる優秀な店員」が絶対に必要です。まあ、AIを駆使した検索エージェントを搭載しろとまでは言いませんが、もう少し買う人に優しい店舗に改築して欲しいところです。これはiPhoneアプリ開発者とユーザのために早急に改善すべき問題だと思うのですが、Apple社はいったいどうするつもりなのでしょうか?

    もうひとつの不満点は「iPhone Developer Program」契約形態の拡充が示されなかったことです。現在、このプログラムには「スタンダードプログラム」と「エンタープライズプログラム」の2種類が存在しています。このうち「エンタープライズプログラム」は社員数500人以上の大企業(加入している企業を聞いたことがないが…)が対象なので、ほとんどのiPhoneアプリ開発者は
    「スタンダードプログラム」へ加入しているはずです。しかしこの契約では、開発したiPhoneアプリはApp Store経由でしか販売できません。それ以外の手段としては、デバイス100台限定でAdHocによる配布が利用できます。「あれ、AdHocは200人までじゃないの?」と思われる方も多いでしょうが、現状のAdHocでは配布用リストには200人まで登録可能ですが、対象デバイスの方は何故だか100台までしか登録できないのです(Portalサイトのバグ?)。そんな訳で、AdHoc対象者は100人までに限定されてしまいます。

    システムインテグレートを生業としているMac関連企業が、iPod touchに独自の自社アプリをインストールし、Mac関連ソフトや周辺機器と一緒に販売しようと立案したとします。 例えばMacで組んだPOSシステムの端末にiPod touchを使い、そこに専用アプリをインストールするようなケースを考えましょう。
    さて、このiPhoneアプリをどうやってデバイスにインストールするのか?
    「App Storeに無料アプリとして置き、ユーザにダウンロードしてもらえば良い…」という考えもあるでしょう。しかし、何らかの理由 で(配布タイミング、セキュリティ、環境設定、ライバル対策など)、それが不可能だと判明したら…そう、AdHocを使うしか手がないのです。つまり、商品が100セット売れる度に、さらに1万円を支払って「iPhone Developer Program」を追加契約するといった冗談のような話が現実となります。

    Apple社が「それはレアケース」と考えているなら大間違いです。例えば一番の例は、今回参加者に配布された「WWDC09」アプリです。これは、不特定多数にApp Store経由以外でアプリを配布するケースです。こうした状況は、iPhoneが想定する「ビジネスシーン」でも頻繁に起こるでしょう。これを無料としてApp Storeに置かなかった理由は「一般ユーザによるダウンロードを避
    けたい」「プロファイル設定でWWDCが終われば起動不可にしたい」などが考えられます。つまり、自社でアプリをきめ細かくコントロールするのには、App Storeによる配布形態は大変不向きなのです。より多くの用途にiPhoneを活用したいと考えた時、現在の「iPhone Developer Program」の契約には大きな不備があります。会場でも多くの参加者の方に「何か良い方法はありませんか?」と尋ねられたのですが、現状ではうまい解決方法はありません。Apple社には、早急に何とかしてもらいたいものです。

    どうやらiPhoneの改訂ペースは1年毎で確定したようなので、次回もWWDC開催時期とも重なる可能性があります。また、Macがらみの次なる展開(Snow Leopard後)にも注目が集まるでしょう。加えて、噂の「新デバイス」が登場しており、そのOSやSDKの話題で、いつも以上に盛り上がっていることを期待したいと思います。
                                     以上

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

    〜 ローカルでPHPを使う(1) 〜

    ・PHPとMac OS X
     Macユーザの間でも、自身が運営または関与するWebサイトにPHPを利用している、というケースは少なくないはずです。自前のサーバならいざしらず、LAMP(Linux / Apache / MySQL / {Perl|PHP|Python|})ベースのレンタルサーバを使おうとなると、避けては通れないことすらあります。
     PHPは、ひとことで言えば「動的にWebページを生成するためのプログラミング言語」です。サーバサイドで動作し、生成されたデータは通常のHTMLとしてクライアント(Webブラウザ)に送信されるため、ユーザ側には特別な準備は必要ありません。この点が、JavaScriptなどのクライアントサイドで動作する処理系との大きな違いといえます。
     一方で、サーバサイドで動作するがゆえの難点もあります。HTTPサーバと連携することが前提にあるため、記述したスクリプトをテストするときには、PHP本体にくわえApacheなどのHTTPサーバが必要になります。出力されたHTMLを確認するためのWebブラウザも必要です。レンタルサーバの多くはこの条件を満たしていますが、公開サーバでテストするわけにはいかないため、ローカルにPHPのテスト環境を構築することが一般的です。
     Leopard(クライアント版)には、PHPとApacheの両方が標準装備されているため、PHPのテスト環境としての条件を満たしています。しかし、デフォルトではPHPが無効化されているため、これから述べる作業が必要になります。

    ・PHPを有効化する
     Mac OS X 10.5.7には、PHP 5.2.8が収録されています。これを有効化すれば、HTTPサーバ(Apache 2.2.11)をシステム環境設定からONにするだけで、PHPスクリプトの実行環境がMac上に出現します。
     Leopardでは、Apacheの設定ファイル(httpd.conf)は/etc/apache2ディレクトリに置かれています。ただし、管理者以外は書き込めないようファイルパーミッションが設定されているため、以下に示すとおり、sudoコマンド経由でテキストエディタ(ここではpicoを使います)を起動したうえで、編集作業を行います。

    - – - – -
    $ sudo pico /etc/apache2/httpd.conf
    Password:
    - – - – -

     sudoは、引数として与えたコマンドライン(ここではpico /etc/apache2/httpd.conf)を、管理者権限で実行するコマンドです。管理者権限でテキストエディタを起動することにより、一般ユーザには読み書きが制限されているファイルであっても、フルアクセスが可能になります。一方では、安易にアクセスされるべきではない重要なシステムファイルを自由に改変/削除できるこ
    とも意味するため、慎重な運用が求められます。
     なお、sudoコマンドを実行すると、管理者のパスワードの入力が促されます。5分以内であれば、再度sudoを実行してもパスワードの入力は求められません。

     picoで行う作業は、httpd.confの114行目行頭にある「#」を削除し、上書き保存することです。114行目までカーソルキーで移動してもかまいませんが、Control-Wをタイプして「php」+enterと入力(「php」で検索)したほうが効率的です。deleteキーで「#」を削除したあと、Control-Xでpicoを終了するとき「Y」と答え、続けてenterを押せば、ファイルの上書き保存は完了で
    す。

    - – - – -
    #LoadModule php5_module libexec/apache2/libphp5.so
     ↓ ↓ ↓
    LoadModule php5_module libexec/apache2/libphp5.so
    - – - – -

    ・動作を確認する
     これで、システム環境設定の「共有」ペインで「Web共有」にチェック(すでに有効化されていた場合はチェックボックスをいちど外して再度チェック)を入れれば、PHPのテスト環境は準備完了です。念のため、以下の1行のみ記述したテキストファイル(仮に「checkme.php」とします)を、「ホーム」→「サイト」フォルダ(~/Sites)に保存し、動作の確認を行いましょう。適当なWebブラウザで「http://localhost/~ユーザ名/checkme.php」にアクセスし、システム情報が表示されれば作業は完了です。

    - – - – -

    - – - – -

     なお、環境によっては、Apache2のアクセスログ保管用ディレクトリが消失していることがあります。筆者のMacBook Proも、ふと気付けばそのようになっていました。原因を特定してはいませんが、Time Machineで復旧したことが原因かも……とりあえず、以下のコマンドラインを実行し、復活させることができました。Web共有を有効化しても「サーバに接続できません」と表示される場合には、/var/log/apache2ディレクトリの有無をチェックしてみましょう。

    - – - – -
    $ sudo mkdir /var/log/apache2
    $ sudo chown root:wheel /var/log/apache2
    - – - – -

    ◇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)2009 MOSA. All rights reserved.

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

    2009-06-23

    目次

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

    MOSA新会長ご挨拶           有限会社オッティモ 小池 邦人

    iPhoneが登場して以来、そのデバイスやシステム、もしくはビジネスモデルに対して様々な場所で色々な評価がなされています。その中で、あまり大きくは取り上げられていないのですが、「Mac + Cocoa + Objective-C」を経験したデベロッパーの数が格段に増えたという事実はかなり重要でしょう。Apple社の発表によると、本年度のWWDCは早々に満員御礼となり(参加者5,200人)、その60%が初めての参加者だったそうです。また、iPhone SDKのダウンロード数も100万を超えました。

    iPhone登場以前と比較し、Apple社製品にからむデベロッパーの数は10倍以上になったそうです。Apple社は、MacやiPhoneを中心としたエコシステムに対して大きな基盤を得たことになります。つまり、iPhoneアプリだけではなく、iPhone+Macソリューション構築時のMac OS X用ソフト、iPhone用周辺機器のソフト、そしてApple社が次に準備しているだろう「まったく新しいデバイス」用ソフトなどなど、それらの開発を担うことができるデベロッパーを一定数確保したことになります。

    その一方で、iPhoneアプリの開発は、手軽に作品発表ができるApp Storeの存在や、多くの関連書籍の出版のおかげで、あの懐かしいHyperCardの様な雰囲気も醸し出しています。確かに、そこまで簡単ではないのですが、プログラミングという「創造の結果」を手軽に体験できるツールとしては、久しぶりに登場した大物です。そのため、iPhoneユーザの中には、アプリ開発にチャレンジしてみようと思い立ったプログラミング初心者の方も多いようです。また、往年のプログラマーの中には、密かに「現役復帰」を画策する人も少なくありません(笑)。

    MOSAは、職業デベロッパーの方々だけではなく、プログラム初心者や学生の方の参加も大歓迎です。iPhone登場により、久しぶりに目が向けられた「プログラミングの楽しさや面白さ」を、さらに多くの方々と共有できればと考えています。そのためには、技術セミナーや各種イベント、そしてWebやオフラインによる会員同士のコミュニケーションを積極的にサポートしていきます。スタッフ一同「MOSA会員が作り上げるMOSA」を目標にがんばりたいと思いますので、会員の皆様のご協力、よろしくお願い致します。

    好きこそ物の上手なれ!     MOSA会長 有限会社オッティモ 小池邦人

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

    iPhone 3.0 がリリースされましたね。iPhoneとRubyといえば、森琢磨さんがRuby と RubyCocoa を iPhone に移植した iPhone RubyCocoa を公開しています。iPhone RubyCocoa には、リモートirbという機能が組み込まれています。この機能により、実行中のiPhoneアプリケーションのオブジェクトシステムに対して、リモートコンピュータ(リモートプロセス)からtelnet経由で、irbによるアクセスが可能です。

    今回から、この iPhone RubyCocoa をiPhoneアプリケーションの開発に活用する方法を考えてみることにします。

    ■ iPhone RubyCocoa のダウンロード

    iPhone RubyCocoa のソースコードは、githubで公開されています。githubというのは、分散型バージョン管理システム git によるソースコード管理を提供しているホスティングサービスです。では、github上の iPhone RubyCocoa のページ:

    http://github.com/takuma104/iphone-rubycocoa/tree/master

    から iPhone RubyCocoa のソースコードを入手しましょう。

    git コマンドを使う場合には:

     $ cd どこか作業用のディレクトリ
     $ git clone git://github.com/takuma104/iphone-rubycocoa.git
     $ open iphone-rubycocoa
    
    

    でソースコードをダウンロードできます。

    といっても、OS X 10.5 には git がインストールされていませんので、git を使っていない(インストールしていない)場合は、上記ページの download ボタンを押して、zip形式(あるいはtar形式)のファイルをダウンロードして展開してください:

     $ unzip takuma104-iphone-rubycocoa-ユニークID.zip
     $ mv takuma104-iphone-rubycocoa-ユニークID iphone-rubycocoa
     $ open iphone-rubycocoa
    


    (注: 「ユニークID」の部分には、ダウンロード時のソースコードのリビジョンを表す16進数番号が入ります)

    ■ Xcode でビルド

    では、最新の Xcode 3.1.3 を使ってビルドしてみましょう。Xcodeのプロジェクトファイル rubycocoa4iphone.xcodeproj を開いて、そのままビルドしてください。たくさんの警告(私のところでは28個)がでましたがリンクは通っているので、警告の解決は後回しにしてとりあえず実行してみます。iPhoneシミュレータの画面に「hello RubyCocoa world」と表示されたでしょうか?

    ■ リモートirb

    iPhone RubyCocoa のリモートirb機能は、デフォルトでは(おそらくセキュリティ上の理由から)機能しないようにコメントアウトされています。しかし、この機能こそ、iPhone RubyCocoa で一番使いたいところでもありますから、使えるようにしてみましょう(注: この機能はリモートコンピュータに対してIP接続のポートを公開することになるので、その点注意してください)。プロジェクト内のmain.rbファイルの 3,4行目:

     # require 'remote_irb'
     # RemoteIRB.new(6000).start
    
    の部分のコメントを外して:
    
     require 'remote_irb'
     RemoteIRB.new(6000).start
    


    にします。これをビルドして実行しましょう。先ほどと同じく、iPhone シミュレータの画面に「hello RubyCocoa world」と表示されたでしょうか(注: ここでシミュレータ内のiPhoneアプリケーションが落ちてしまう場合があるのですが、それについては後述します)。さらに、Xcode のデバッガコンソールを見ると:

     [remote_irb] listening on 192.168.xxx.xxx:6000
     #
     #
     #
    
    と表示されています。 IPアドレス 192.168.xxx.xxx のポート番号6000で接続
    を待ち受けているということなので、telnet で接続してみましょう:
    
     $ telnet 192.168.xxx.xxx 6000
     Trying 192.168.xxx.xxx...
     Connected to 192.168.xxx.xxx.
     Escape character is '^]'.
     >> 
    


    どうやら、iPhoneシミュレータ上で動く irb に接続することができたようです。
    さっそく、アプリケーションオブジェクトにアクセスしてみます:

     >> app = OSX::UIApplication.sharedApplication
     => #
     >> view = app.keyWindow.contentView
     => #
     >> view.class
     => OSX::UILabel
    
    contentViewには UILabelがセットされているようです:
    
     >> view.text.to_s
     => "hello RubyCocoa world"
    
    UILabelのテキストと背景色を変更してみましょう:
    
     >> view.setText Time.now.to_s
     => nil
     >> view.setBackgroundColor OSX::UIColor.blueColor
     => nil
    


    というような感じで、実行中のiPhoneアプリケーションのオブジェクトを操作することができました。

    ところで、このプロジェクトは、iPhone Simulator 2.2.1 向けになっています。
    ここは 3.0 で動かしたいところですが、残念ながらリンクエラーになってしまいます。コンパイル時の警告も含めて、次回は 3.0 で動かせるように修正することにします。

    ■ (補足) ビルドしたiPhoneアプリケーションが落ちてしまう場合の対策

    iPhone上のRubyがkconvライブラリを要求して落ちてしまうようで、言語の設定(localeなど)が関係しているようですが、これを書いている時点でははっきりと解決はできていません。私のところでは、iPhoneシミュレータを、XcodeからではなくFinderから起動して、ビルドしたiPhoneアプリを起動したら立ち上がるようになりました。

    ■ 参考URL

    iPhone で Ruby/RubyCocoa を動かしてみた
    http://d.hatena.ne.jp/takuma104/20090225/1235584788

    iphone-rubycocoaで、実機動作中のアプリをリモートから動的に変更する
    http://d.hatena.ne.jp/takuma104/20090301/1235927945

    github の iPhone RubyCocoa ページ
    http://github.com/takuma104/iphone-rubycocoa/tree/master

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

     承前……と言って皆さんWWDC前にモサ伝で読んだことなど憶えてないかも知れないので(なに憶えてなくても恥ぢゃない、書いてるオレが今前回のを読み返してからこれを書き始めてんだから)、「前回までの『24』は……」的にちょいとおさらいをする。まず我々は以下のような真実を確認した。

    「ソフトウェア技術者は昔も今も『高度で専門的な知識や経験を要する』職業である」
     
     しかるに現状はこうである。

    「ソフトウェア技術者は『高度で専門的な知識や経験を要する』職業にふさわしい扱われかたをしていない……安くコキ使われている」

     で、それはなんでだ? という設問に対する粉砕すべき仮説1として以下のものを提示したところまで、である。

    仮説1:ソフトウェア技術者の待遇が悪いのは受給のバランス、つまり供給が過剰だからである。「高度で専門的な知識や経験」も数が増えれば安くなるの
    が当然やんけ。

     で、上の仮説どー思います? その通りだと思いますか? ここで読者処刑……ハリツケ獄門食らってどうする、諸兄に納得されてしまうとオレも立つ瀬がないんだが、どうですか、実感としてこの仮説に首肯できるかたはおられましょうか。ワタクシはと言えば到底首肯できない、バン!(机を叩いた)。

     なんつかな、ひどく卑近かつ個人的怨念びしばしの話をさせてもらうと、そんなに「高度で専門的な知識や経験」を持ったヒトが増えて安く使えるようになってるのなら、あの時オレはもっと楽できたはずだと思い起こし、枕をくやし涙で濡らすような(濡らしやしないがね)仕事というのが数多あるのである。

     オレ思うに、仮説1はこう書き換えられるべきではないか。

    仮説1(改):ソフトウェア技術者の待遇が悪いのは、「需要」に対して業界が、実際には「高度で専門的な知識や経験」を持たない人材までを「供給」したことに起因する「見かけの供給過剰」が原因である。

     どっすか? これ、裏を返せばあの「IBM/システム360の父」フレデリック・P・ブルックスJrがその名著「人月の神話」の中で喝破した問題そのものである。読んでないヒトのために(読んだ方がいいよ)その部分だけかいつまむと、ブルックスはこう言ってる。

    「コストは人数と月数の積(人月)である。が、進捗はそうではない」

     もう涙が出るほど簡潔でしょ?

     そして彼は、「コスト(人月)」と「進捗」を混同して「人月を仕事の大きさを測る単位として使う」ことを「人月の神話」として戒めてる。……んだけど、この本が最初に出版された1975年からもう30年以上経っているにも関わらず、そして日本人の「教科書ダイスキ体質」にも関わらず、この悪弊だけは改善されずに残っているのである。

     でもこのブルックスの言葉、他の仕事に当てはめると別に特段珍しいことを言ってるわけではないのだ。例えばあなたが家を建てるとする。どうせ例えばの話なんだから田園調布あたりに300坪くらいの土地があり、建築資金も潤沢にあるとしよう。

     友人の建築家(そういう金持ちにはたいがい建築家の友達がいる)に図面をひいてもらい、腕のいい工務店を紹介してもらう。その時工務店が持ってくる見積もりは「大工何人が何ヶ月仕事しますからいくらです」ぢゃなくて「仮設工事いくら、基礎工事いくら、地盤改良工事いくら……」ですよ。

     次回より、なぜ日本のソフトウェア産業では「人月の神話」がまかり通るのかちゅうコトを追求しよう。
                           (以下次回 2009_06_19)

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

    これから始めようとする人へ(11)

     皆さんこんにちは、高橋真人です。今回はリファレンスカウントという考え方についてのお話です。
     前回、「次回はretainカウントについて説明します」と予告しましたが、Cocoa特有の用語であるretainカウントを説明する前に、もっと一般的な概念の方を説明しておく方がいいと思いますので、先にリファレンスカウントを説明します。

     さて、malloc()によってヒープ領域から動的に確保したメモリーをfree()で解放するということについては前にお話をしましたが、実際のプログラムにおいては、この動的に確保されたメモリー領域が複数の個所から参照されるために話がややこしくなり、「解放のし忘れ」や「既に解放済みの領域にアクセスしようとする」といったバグの温床となります。
     具体的に見てみましょう。

    // バグあり、注意!
    01: #include 
    02: #include 
    03: 
    04: int main (void)
    05: {
    06:     int *a = NULL, *b = NULL;
    07: 
    08:     a = malloc(sizeof(int));
    09:     *a = 10;
    10:     printf("*a = %d\n", *a);
    11:     b = a;
    12:     ++(*b);
    13:     printf("*b = %d\n", *b);
    14:     free(b);
    15:     printf("*a = %d\n", *a);
    16: 
    17:     return 0;
    18: }
    


     intを指すポインタaとbを用意し、aに対して動的に確保したメモリ領域を割り当てます(6、8行目)。その領域に10という値を書き込んで、結果を確認します(9、10行目)。
     次に、bにもaの指している先をコピーし、bを経由して書き込んであった値をインクリメント(値を一つ増やすこと)します(11、12行目)。bの値を確認して(13行目)、bの指している先を解放します(14行目)。そして、aの指している先の値を確認する(15行目)というのが、このプログラムでやっていることです。
     さて、どこにバグがあるのか、お分かりですか?

     その答えは、14行目と15行目、確保した領域を解放してしまったあとでaを経由して値にアクセスしているところです。(実際に上記のコードを自分で試してみられた方、プログラムが落ちることはなかったかもしれませんが、それでこのプログラムにバグがないということにはなりません。理由を説明するのは話の本筋から外れるので省略しますが。)
     「あれ? 解放しているのはbだから、aの方は大丈夫なのでは?」と思われた方、11行目の代入文でbにコピーされているのは、領域を表すアドレス値であり、aもbも同じ場所を指している(つまり、aとbの値は同じである)ことをしっかりと認識してください。
     つまり、上記のコードでは意図的に混乱を引き起こすために(笑)、bを使って領域の解放を行っていますが、free(a)と書いてもfree(b)と書いても、11行目が実行された後であれば、a、bそのものの値が変更されない限りにおいて両者は同じ意味を持つのです。

     さて、上記の例をリファレンスカウントという観点からもう一度見てみます。
     まず、malloc()により確保された領域を何らかのオブジェクトだと言い換えてみます(今回は、オブジェクトの実体は単なるintの値ですが)。そして、このオブジェクトは、aというポインタによって参照されていることになります。
     bにaを代入するということは、bもまたこのオブジェクトに対する参照を得るということを表します。
     さて、件のオブジェクトはこの段階でaとbという二つのポインタから参照されています。この状態をリファレンスカウントが2であると表現します。
     a、b二つのポインタがこのオブジェクトを参照している以上、たとえばaにとってもう必要なくなったからと言って、勝手にこの領域を解放してしまうと、bの立場がなくなります(笑)。

     aにとって、この領域への関心がもうなくなったならば、ここはいきなりfree()を呼び出してしまうのではなく、単に

    a = NULL;

    とでもして、もうその領域を指すことをやめるだけにとどめておけばいいのです。この時点で件のオブジェクトを参照しているポインタはbだけですので、リファレンスカウントは1となります。
     そして、もしbにとってもこのオブジェクト不要となった場合、このオブジェクトをいよいよ解放するべきときが来たということになります。もちろん、それまでの間に別のポインタが新たにこのオブジェクトに対する参照をすることがないということが前提です。
     ちなみに、この場合においても

    b = NULL;

    とするのみで、free()を呼び出すことなくbがオブジェクトへの参照を放棄してしまえば、最早オブジェクトを参照するものが一つもない状態になるため、このオブジェクトの格納されている領域を解放することは永久にできず、いわゆるメモリーリークが発生することとなります。

     さて、今までのお話で「リファレンスカウント」という言葉を使って、「今、このオブジェクトを参照しているポインタはいくつ」ということを数えていましたが、それをしていたのは、あくまでこのコードを見ている人間の側でしかありませんから、コードがもっと複雑になって、「えっと、ここでこのポインタが参照を得て、この部分でこっちのポインタが参照を放棄しているから…」などといちいちやっていたら必ず間違えが起こりますし、何よりも面倒この上ありませんよね。
     そこで、このリファレンスカウントという考え方を実際にコードの中に組み込んで、プログラムに自動で管理させようというのが、本来のリファレンスカウントの考え方です。

     次回は、簡単なプログラムで実際にこのリファレンスカウントの使い方を見ていこうと思います。

    ◇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)2009 MOSA. All rights reserved.

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

    2009-06-09

    目次

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

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

    〜「Deployment」編〜

     この記事が配信されることはWWDC 09の基調講演はもう終了していることでしょうが、今年ははたしてどのような発表が行われているんでしょうか。さて、これまでNetBootのサーバ側の解説をしてきましたが、今回はクライアント側について解説します。

    ◇NetBoot起動
     NetBootのシステムが構築されている環境でクライアントをNetBootするには3つの方法があります。もしクライアントにすでに何らかのシステムがインストールされていれば、「システム環境設定」の「起動ディスク」からNetBoot起動を設定できます。「起動ディスク」には内蔵ディスクや外付けディスクなど、システムがインストールされていて起動可能なボリュームの一覧が表示されます。これらに加え、ネットワーク上でNetBootサービスが稼働していれば、NetBootサービスが提供している使用可能なNetBootイメージも一覧に表示されます。つまり、「起動ディスク」でNetBootイメージを選択して再起動すればクライアントをNetBoot起動することができるというわけです。
     この方法でNetBoot起動した場合、起動ディスクの変更は記録されますので再び起動ディスクを変えないかぎりクライアントは毎回NetBootで起動します。

    ・起動ディスクの選択
    http://www.htabata.com/img/MXS105/netboot/system_pref_01.png

     2番目の方法ですが、クライアントを起動するときにCommand + Nキーを押しながら起動します。この場合、ネットワーク上でNetBootサービスが稼働していればクライアントは自動的にNetBootイメージを検出して起動します。もしサーバで複数のNetBootイメージを運用している場合には、NetBootサービスのイメージの設定でデフォルトに指定されているイメージから起動します。
     3番目の方法は2番目の方法と少し似ています。クライアントの起動時にOptionキーを押しながら起動します。このとき起動マネージャが動作してまず起動可能なボリュームの一覧が表示されます。ネットワーク上でNetBootサービスが稼働していれば、ボリュームの一覧にNetBoot起動用のアイコンが表示されますので、このアイコンからNetBoot起動することができます。
     ただしサーバ上にNetBootイメージが複数あったとしても、起動ボリュームの一覧にはNetBoot用のアイコンは1つしか表示されません。この場合NetBoot起動すると2番目の方法と同様に、デフォルトとして設定されたイメージから起動します。
     2番目と3番目の方法でNetBoot起動した場合、1番目の方法とは違い起動ボリュームの変更は記録されません。つまりクライアントをNetBoot起動した後に再起動すると、元々設定されていた起動ボリュームを使ってクライアントが起動します。一時的にNetBoot起動したい場合には便利な方法です。

    ◇NetBoot起動の流れ
     では次にクライアントがどのような流れでNetBoot起動するのかをみていきましょう。上記のいずれかの方法でクライアントをNetBoot起動すると、まずDHCPを使ってIPアドレスを取得します。DHCPから取得したIPアドレスを使ってネットワーク接続できるようになると、TFTPというプロトコルを使ってNetBootサーバからクライアントの起動に必要なbooterファイルをダウンロードします。
    booterファイルは「システムイメージユーティリティ」を使ってNetBootイメージを構築したときに作成されています。
     booterファイルでクライアントが起動すると、NFS(またはHTTP)を使ってサーバ上のNetBootイメージをネットワーク経由でマウントします。NFSを使用するかHTTPを使用するかは前回解説しましたように、イメージごとにサーバ側で設定できます。
     NetBootのイメージは全てのデータが起動時にクライアント側にダウンロードされるわけではありません。クライアントからネットワークマウントし、必要に応じてネットワーク経由でデータが転送されます。NetBootイメージからクライアントが起動すると再びDHCPからIPアドレスを取得してネットワークの自動設定が行われます。

     以上がNetBoot起動の流れです。起動の流れを理解しておくことはトラブルシューティングにとって重要です。これまで解説してきましたようにNetBootは複数のサービスとともに使用しますので、どこか一部のサービスに問題があるとNetBoot起動に失敗します。起動に失敗した場合、その原因をつきとめる必要がありますが、起動の流れを正確に理解しておくことで原因の切り分けがやりやすくなります。

    ◇本格的な運用に向けて
     これでNetBootシステム構築の基礎の解説が一通り終わりました。基礎はあくまでも基礎なので実用的なシステムを構築するにはさらにいくつかのハードルが待ち受けています。例えばイメージのカスタマイズ作業やさらに他のサービスとの連携が必要になるケースがあります。
     NetInstallの場合、ネットワーク経由でインストールをしてしまいますので、インストールさえ完了してしまえば後は通常通りクライアントを使用できるわけですが、NetInstallではなくNetBootで毎回クライアントを起動する場合、クライアントからはシステムイメージ上での変更を再起動後も保存しておくことができません。そこでディレクトリサービスによるユーザの一元管理やネットワークホームの運用も必要となってきます。

     またNetBootでのクライアント起動をDeploymentの手段として使用することもできます。ディスクレスでクライアントコンピュータを起動するとクライアントの内蔵ハードディスクを未使用の状態にできます。そこでNetBootでクライアントを起動してから、クライアントの内蔵ハードディスクにシステムをインストールするといったこともできます。このような作業はシステム標準の機能だけでも実現できるでしょうが、作業を効率化するためのツールを利用することもできます。というわけで次回以降はDeploymentの応用について解説していきます。
                                 次回へつづく

    小池邦人のCarbon視点でiPhone探求(2009/06/05)

    〜 UITableViewControllerを実装していく 〜

    本アプリケーションは「Navigation-Based Application」テンプレートを使用しています。今回は、このテンプレート内容を解説した後、UINavigationControllerが管理しているUITableViewControllerのサブクラス(RootViewController)の実装へと進みます。

    「Navigation-Based Application」テンプレートの場合、UINavigationControllerオブジェクトはMainWindow.xibに含まれており、
    管理対象としてUITableViewControllerのサブクラスであるRootViewControllerが指定されています。 Interface BuilderでMainWindow.xibをオープンし、ウィンドウに表示されたNavigation Controllerアイコンをダブルクリックすると、デバイスサイズのウィンドウがオープンします。そこに…

    Loaded From “RootViewController.nib”

    と記載されていますが、これは、この場所に “RootViewController.nib”ファイルのFile’s Ownerとして定義されているビューコントローラ(クラス)が読み込まれて表示されることを示しているわけです。これを変更したい場合には、先んじてUINavigationControllerのビュー表示(点線の角丸で囲まれている領域)を選択しておき、Inspectorウィンドウの「Root View Controller Attributes」(ひとつ目アイコン選択)で表示される「NIB Name」のクラス名を入力し直します。アプリケーションを起動すると、一番最初に、ここに入力されているビューコントローラの管理ビューが、スクリーンに表示されることになります。

    さて、RootViewController本体の方はRootViewController.xibの方に用意されています。このnibファイルは、Xcodeから直接オープンできますが、UINavigationControllerの “RootViewController.nib”表記(青文字部分)をクリックすることで即座にオープンすることも可能です。必要とされるアウトレット(Outlets)の接続はテンプレート自体が準備してくれていますが、自分自身で調整する場合もありますので、重要な箇所をピックアップしておきたいと思います。アウトレットの接続状況は、Inspectorウィンドウの「Root View Controller Connections」(2つ目のアイコン選択)で確認できます。

    まず最初に、File’s Owner(RootViewControllerクラス)のtableViewとviewアウトレットが、同じnibファイルに登録されているテーブルビューアイコン(Table Viewと表記されている)に接続されていることを確認してください。
    このアウトレットの設定が正しく行われていないと、アプリケーション起動時にテーブルビューが表示されません。次にテーブルビューのアイコンをクリックして、同じくアウトレットの接続状態を確認します。こちらは、dataSourceとdelegateアウトレットが「File’s Owner」アイコンに接続されていることを確認してください。こちらのアウトレットの設定が正しくないと、後からソースコードでクラス実装を行った時に、関連メソッドが正しく働かないことになります。

    次に、ソースコード処理を順番に追いかけてみます。まず、ナビゲーションコントローラを準備する処理は、アプリケーションデリゲートクラス(SymmetryAppDelegeta.m)のapplicationDidFinishLaunching:メソッド(デリゲート)に記述されています。

    - (void)applicationDidFinishLaunching:(UIApplication *)application
    {
      //  ここにアプリケーション起動時に必要な処理を記述する
    
      [window addSubview:[navigationController view]];
      [window makeKeyAndVisible];
    }
    


    ここで使われているwindowとnavigationControllerという2つのアウトレットは、テンプレートにより用意されており、MainWindow.xibの「App Delegate」アイコンに接続されています。処理内容は、ウィンドウ(UIWindow)のサブビューにナビゲーションコントローラのビューを配置し、そのウィンドウをキーウィンドウとします。つまり、ナビゲーションコントローラで指示したテーブルビューコントローラ(RootViewControlle)がnibファイルから読み込まれ、最終的には、それが管理しているテーブルビュー(UITableView)が表示されるわけです。

    ここから、ようやRootViewController.mに実装したメソッドの出番となります。まずは、クラス定義のRootViewController.hの方ですが、今のところインスタンス変数はひとつも定義されていません。クラスが対応しているプロトコルについては、以前お話した「画像の取り込み処理」に必要とされるクラスのものが3つ定義されています。

    #import 
    
    @interface RootViewController : UITableViewController
                                < UINavigationControllerDelegate,
                                  UIActionSheetDelegate,
                                  UIImagePickerControllerDelegate >
    {
    }
    
    @end
    


    次は、クラス実装をするRootViewController.mです。すでに、テンプレートがオーバライドすべきメソッドを幾つかピックアップし、コメント行として用意してくれています。このうちどれをオーバライドすべきなのかは、クラスの処理内容によって違ってきます。

    - (void)viewDidLoad
    {
      [super viewDidLoad];
    }
    


    viewDidLoadは、ビューコントローラがnibファイルから呼び込まれる時に一度だけ呼ばれます。通常、ビューコントローラの「初期化」処理に用いられます。

    - (void)viewWillAppear:(BOOL)animated
    {
      [super viewWillAppear:animated];
    }
    


    viewWillAppear:は、ビューコントローラに属するビューがスクリーン上に表示される直前に呼ばれます(この時点でまだビューは表示はされていない)。このメソッドは、一番最初だけでなく、別のビューコントローラから切り替わる時にも呼ばれますので御注意ください。 通常、ビューコントローラの「準備」処理に用いられます。

    - (void)viewDidAppear:(BOOL)animated
    {
      [super viewDidAppear:animated];
    }
    


    viewDidAppear: は、ビューコントローラに属するビューがスクリーン上に表示された直後に呼ばれます。

    - (void)viewWillDisappear:(BOOL)animated
    {
      [super viewWillDisappear:animated];
    }
    
    


    viewWillDisappear:は、ビューコントローラに属するビューがスクリーンから消える直前に呼ばれます。このメソッドはアプリの終了だけでなく、別のビューコントローラへの切り替え時にも呼ばれます。通常、ビューコントローラの「後始末」処理に用いられます。

    - (void)viewDidDisappear:(BOOL)animated
    {
      [super viewDidDisappear:animated];
    }
    
    


    viewDidDisappear:は、ビューコントローラに属するビューがスクリーンから消された直後に呼ばれます。

    - (BOOL)shouldAutorotateToInterfaceOrientation:
                                      (UIInterfaceOrientation)interfaceOrientation
    {
      return (interfaceOrientation == UIInterfaceOrientationPortrait);
    }
    


    shouldAutorotateToInterfaceOrientation:は、ビューコントローラの向き(デバイスに対して縦方向なのか?横方向なのか?)を指示します。デフォルトは縦向きだけを容認するソースコードの記述となっています。

    - (void)didReceiveMemoryWarning
    {
      [super didReceiveMemoryWarning];
    }
    


    didReceiveMemoryWarningは、メモリの使用状況がタイト(メモリ不足)になった場合にOSから呼ばれます。開発者は、ここに不用になったメモリ(キャッシュやテンポラリ作業領域など)を開放する処理を記載します。ただし、間違ったメモリ解放(まだ必要なのに…)をするとクラッシュの原因となりますので、くれぐれも注意してください。ここで何もしなくとも、スーパクラスのビューコントローラではメモリ領域を増やすために不用ビューを解放するといった処理が実行されます。

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


    deallocでは、通常のクラスと同じく、このビューコントローラクラスで仕様したインスタンス変数を解放します。

    上記メソッドの中には、先んじてスーパクラスを呼び出す必要の無い種類もありますが(スーパクラスは何もしていないと言うこと)今後仕様変更があるかもしれませんので、必ずスーパクラスを呼ぶようにしましょう。ちなみに、didReceiveMemoryWarningやdeallocでは今でもスーパクラスの呼び出しは必須です。

    ところで、少し上級者向けの話となりますが、initWithNibName:bundle:でnibファイルからUIViewControllerを読み込んで表示する時にpushViewController: animated:を使うと、最初の処理ではUIViewController側でオーバライドしたメソッドが…

    - (void)viewDidLoad 
    - (void)viewWillAppear:
    - (void)viewWillDisappear:
    


    の順番で呼ばれます。しかし呼び出しにpresentModalViewController:animated:を使うと、何故だか…

    - (void)viewWillAppear:
    - (void)viewDidLoad 
    - (void)viewWillDisappear:
    


    の順番でメソッドが呼ばれます。この現象はv2.2になってから起こるようになり、v2.1では問題ありませんでした。iPhone OS 3.0では修正されている様ですので、この現象はバグだったようです。v2.2をアプリ起動対象とされている方は御注意ください。

    次回は、テーブルビュー(UITableView)に必要とされるデータソース(dataSource)とデリゲート(delegate)メソッドの解説を行います。これらの仕組みは、Mac OS XのNSTableViewと似ているのですが、iPhone OS独自の仕組みも沢山見受けられますので、そちらを中心に話を進めたいと思います。

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

    〜 リモートでシェルを使う(4) 〜

    ・sftpでファイルを一括転送
     前回紹介した手順で鍵ペア登録などの作業を行えば、つどパスワードを入力することなく安全にリモートサーバと通信できるようになります。これだけで、Webサイトを更新する目的でファイルを転送する場合などリモートサーバとのやり取りが簡略化されますが、複数のファイルを一括して送受信する用途には不向きです。
     そのような場面で利用したいのが「sftp」です。sftpは、SSH実装系におけるファイル転送プロトコルの一種で、Mac OS Xには同名のクライアントソフト「sftp」がコマンド(/usr/bin/sftp)として収録されています。つまり、ターミナルからsftpコマンドを実行することで、大量のファイルを安全かつ効率的にリモートサーバとやり取りできます。
     sftpとscpとの機能差ですが、暗号化された経路を通じてファイルを転送するという機能自体に違いはありません。しかし、リモート(SSHサーバ)上のシェルでコマンドとして実行されるscpは、1つのコマンドが完了しなければ次のコマンドを実行できない、すなわちファイル転送を一時停止したり再開したりすることはできません。一方のsftpは、SSHサーバ上で起動されたSFTPサーバがサブシステムを介してSSHサーバと接続し、通信路を確立したうえでファイル転送に関する内部コマンドを実行するスタイルのため、ファイル転送の一時停止/再開といった処理にも対応できます。

    ・sftpを起動する
     sftpの起動はかんたんです。sshコマンドでログインする(リモートシェルを実行する)ときと同様に、引数を「ユーザ名@サーバのドメイン名」の形式にしたうえでsftpコマンドを実行すれば、セッションが開始されます。鍵ペアの登録が完了していれば、パスワードの入力は必要ありません。

    - – - – -
    $ sftp yourname@dokka.com
    Connecting to dokka.com…
    sftp>
    - – - – -

     セッションが開始されると、プロンプトは「sftp>」に変化し、sftp内部コマンドの入力待ち状態となります。基本的な操作方法はCUIのFTPクライアント(ftpコマンド)と同様で、以降セッション終了までは内部コマンドを利用します。まずは「help」を実行し、内部コマンドを確認しましょう。

    - – - – -
    sftp> help
    - – - – -

    ・sftpの使い方
     ふだんsftpを使うとき、最初に実行すべきは「pwd」と「lpwd」コマンドです。前者でリモートホスト(サーバ)上の、後者でホーカルホスト上のカレントディレクトリを確認し、これから行うファイルの転送に備えます。続けてcd / lcdコマンドでアップロード / ダウンロード先のディレクトリを変更しますが、「~」や「..」といった記号やディレクトリ名の入力補完など、シェルでお馴染みの機能は利用できません。

    - – - – -
    sftp> pwd
    Remote working directory: /virtual/yourname
    sftp> lpwd
    Local working directory: /Users/shinobu
    - – - – -

     ファイルのアップロード(ローカル→リモート)には、「put」コマンドを利用します。最初の引数がローカルホスト上のファイル名、2番目の引数がリモートホストへコピー後のファイル名となるため、「put A B」の要領でコマンドを実行しても、2つのファイルをアップロードすることにはなりません。
    複数のファイルをまとめてアップロードする場合には、「*」や「?」といったメタキャラクタを使用します。たとえば、拡張子「.pdf」のファイルを一括アップロードする場合には、次のとおりコマンドを実行します。

    - – - – -
    sftp> put *.pdf
    - – - – -

     ファイルのダウンロード(リモート→ローカル)には、「get」コマンドを利用します。引数の指定方法はputコマンドと同様で、複数のファイルをまとめてダウンロードする場合にはメタキャラクタを利用します。

    - – - – -
    sftp> get *.html
    - – - – -

    - – - – -
    表:sftpの主要な内部コマンド

    cd <パス> リモートホストのディレクトリを指定のパスに変更する
    lcd <パス> ローカルホストのディレクトリを指定のパスに変更する
    ls リモートホストのディレクトリの内容を一覧する
    lls ローカルホストのディレクトリの内容を一覧する
    help 有効なコマンドと用例を一覧する
    get <名前> リモートのファイルをローカルへ転送する(ダウンロード)
    put <名前> ローカルのファイルをリモートへ転送する(アップロード)
    rm <名前> リモートホストのファイルを削除する
    mkdir <名前> リモートホストにディレクトリを作成する
    rmdir <名前> リモートホストのディレクトリを削除する
    pwd リモートホストのカレントディレクトリのパスを表示する
    lpwd ローカルホストのカレントディレクトリのパスを表示する
    exit sftpを終了する(quitも同様)
    - – - – -

    ◇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)2009 MOSA. All rights reserved.

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

    2009-06-02  

    目次

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

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

    引き続き、Ruby+RubyCocoaを使って「CoreGraphicsによるPDFの描画」を記述するための簡易言語(DSL)を作ります。今回で完成します。

    ■ CGPDFContext.file の実装

    目標とする簡易言語のプログラム例(第42回または45回参照)のうち、まだ実装していないのは、クラスメソッド CGPDFContext.file のみとなりました。このメソッドは、ブロックで渡された描画コードを実行して、指定されたファイル名(パス名)にPDFファイルとして出力するというものです。さくっと実装してしまいましょう (注: 第45回では CGPDFContext.file の部分を PDFDrawer.fileとしていましたが、説明をシンプルにするために変更しています):

    class CGPDFContext
    def self.file(path, rect, &block)
      url  = OSX::NSURL.fileURLWithPath(path)
      rect = OSX::NSRect.new(*rect)
      context_ref = CGPDFContextCreateWithURL(url, rect, nil)
      pdf = self.new(context_ref)
      block.call(pdf)
    end
    end
    

    ◇ (補足) RubyCocoaとMacRubyのメモリ管理について

    前々回(46回)に実装した CGPDFContext#page が、beginPage と endPage の組み合わせを1つにまとめるためのメソッドであるのに対して、CGPDFContext.file は、描画コンテキストリソースの確保と解放のためのAPIの組みである CGPDFContextCreateWithURL と CGRelease をひとつにまとめるという位置づけに近いかもしれません。

    実際には、RubyCocoaでは、CGPDFContextCreateWithURL を使って確保した描画コンテキストは自動的に解放されるので、CGRelease(あるいはCFRelease)を明示的に呼び出す必要はありません。もう少し細かく説明すると、描画コンテキストを持つRuby オブジェクト(上記のコードの場合context_refが指すオブジェクト)が、Rubyのオブジェクトシステムによってガベージコレクションされるタイミングで、描画コンテキストは自動的に解放されます。ほっといても自動的に解放されるので、むしろ明示的に呼んではいけません。

    このあたりは、明示的に呼ぶ必要がある(現時点での)MacRubyと少し違うところなので注意が必要です。この違いの背景を少し説明します。

    RubyCocoaは、ガベージコレクション無効のObjective-Cを前提に、Objective-Cの参照カウンタ方式によるメモリ管理の規約を、RubyのガベージコレクタをベースにしてRubyCocoa自体が自動的に実行するように実装されています。その流れで、CoreFoundationフレームワークのようなC言語によるAPIに対応すべく拡張されたときにも、同様の自動処理がなされるように実装されました。

    MacRubyは、ガベージコレクションが有効なObjective-Cを前提に実装されています。MacRubyでは、RubyオブジェクトもObjective-Cオブジェクトなので、Objective-Cのガベージコレクタによって自動的にメモリ管理されます。
    RubyCocoaの場合と違って、ガベージコレクタの管理の外にある参照ポインタに関して、MacRuby自体ではとくに何もしていません(MacRubyを利用したライブラリとして実装することは可能でしょう)。したがって、CGPDFContext.fileのようなコードをMacRubyで実装する場合には、CGRelease(もしくはCFRelease)を明示的に使う必要があります。

    ■ 完成!

    以上で、ようやく、Ruby+RubyCocoaを使った「CoreGraphicsによるPDFの描画」のための簡易言語ライブラリが完成しました。簡易言語という言い方はちょっと大げさな気もするたった52行のプログラム(cg_context.rb 本文末尾を参照)です。このcg_context.rb を使った簡単なサンプルとして、1984年から現在までのAppleの株価のグラフを描画するプログラムを書いてみたので試してみてください:

    ------------------------ aapl_chart.rb
    # -*- coding:utf-8 -*-
    require 'cg_context'
    require 'open-uri'
    
    url = 'http://ichart.finance.yahoo.com/table.csv?' +
      's=AAPL&a=08&b=7&c=1984&d=04&e=29&f=2009&g=m&ignore=.csv'
    
    csv = open(url){ |io| io.read }
    prices = csv.split(" n")[1..-1].
             map{ |row| row.split(',').last.to_f }.reverse
    
    width, height = 600, 400
    CGPDFContext.file("aapl.pdf", [0, 0, width, height]) do |pdf|
    pdf.page do
    scale_x = width  / prices.size
    scale_y = height / (prices.max - prices.min)
    pdf.scaleCTM(scale_x, scale_y)
    pdf.translateCTM(0, -prices.min)
    pdf.setRGBFillColor(0.0, 0.0, 1.0, 1.0)
    points = [ CGPointMake(prices.size-1, 0), CGPointMake(0,0) ]
    prices.each_with_index { |v,i|  points << CGPointMake(i, v) }
    pdf.beginPath
    pdf.addLines(points, points.size)
    pdf.fillPath
    end
    pdf.flush
    end
    ---------

    このプログラムは、Yahoo! Finance から Apple の株価の履歴をcsv形式でダウンロードして、簡単な折れ線グラフとして描画しています。

    CSV形式でダウンロードして株価の配列にしてしまうコードを、3行で書けてしまうあたりがRubyマジックといったところでしょうか? このようなグラフは、PDFよりもむしろ画像ファイルにした方が使い勝手がいいような気がしますね。cg_context.rb を少し改造するだけで PNG画像なども生成できるはずですので、興味のある方は挑戦してみてください。

    ■ PDF描画簡易言語ライブラリ完成版

    ------------------------------- cg_context.rb --
    # -*- coding: utf-8 ; indent-tabs-mode:nil -*-
    require 'osx/cocoa'
    include OSX
    
    class CGContext
    # context_type 宣言構文の定義:
    #   コンテキストの種類(PDFなど)を宣言するとCG(種類)Context関数のイン
    #   スタンスメソッドを生成する
    class << self
    private
    def methodnize(original_name, name)
      method_name = name[0].chr.downcase + name[1..-1]
      define_method(method_name) do |*args|
        OSX.__send__(original_name, @context, *args)
      end
    end
    def context_type(type)
      pattern = / ACG#{type}Context(.*) Z/
      OSX.methods.each do |func_name|
        matched = pattern.match(func_name)
        methodnize(func_name, matched[1]) if matched
      end
    end
    end
    
    # デフォルトの context_type 宣言
    context_type ''
    
    # CGContextクラスのインスタンスオブジェクトの初期化
    def initialize(context)
    @context = context
    end
    end
    
    class CGPDFContext < CGContext
    context_type :PDF
    
    def page(page_info={}, &block)
    beginPage(page_info)
    block.call(self)
    ensure
    endPage
    end
    
    def self.file(path, rect, &block)
    url  = OSX::NSURL.fileURLWithPath(path)
    rect = OSX::NSRect.new(*rect)
    context_ref = OSX::CGPDFContextCreateWithURL(url, rect, nil)
    pdf = self.new(context_ref)
    block.call(pdf)
    end
    end
    # ------------------------------ cg_context.rb --
    

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

     突然だがみなさんは、インフレ……近頃は「豚インフル」とかいう略語が流行って来てるんで混同するかもしれんが「インフレーション」のほうね、と聞くとまず何を連想されるだろうか。昨今の不景気はデフレのせいなんだからってんで、政治家とか経済評論家とかテレビキャスターとか一応テレビキャスターになったということにされてるお笑いタレントとかが一時「インフレターゲット論」というのを振り回してたのをご記憶の方も多かろう。

     インフレってのはデフレの逆だからモノの値段が上がることである。これ、ものは言いようでね。「モノの値段が上がる」ってのと「お金の価値が下がる」っての、同じことを言ってるのに文字通り「聞こえ」が違う。

     ポール・クルーグマンあたりが書いてるようなことばっかり読んでると「そうだインフレを目指さなければ」と思うかも知れないが、スプーンという渾名で知られるブルースマン、ジミー・ウィザースプーンの「Money's Getting Cheaper」という歌には「♪墓堀人まで組合作りやがって死ぬのも高くつく」なんて文句もある。

     インフレもデフレも要は需要と供給のバランスの崩れであって自由経済の宿命みたいなものやないの。インフレターゲット論者の言う「適度なインフレ」なんてものが政策で実現できるもんだったら最初から不況だのデフレだの起こさないで済むんぢゃないかと思うが、どうも経済学という学問の世界ではそういうことは言ってはいけない決まりになっているらしい。

     あ、このバカなにをトチ狂って付け焼き刃の経済学なんか講釈はじめたのかって? そりゃもちろん前回最後に提示した設問「ソフトウェア技術者はなぜ『高度で専門的な知識や経験を要する』職業ではなくなってしまったの?」に対する答えを出すためである。そのために上のインフレ/デフレ論議を覚えてて欲しいのね。

     いっすか。まず最初に「真実」をおさえておくべきだ。真実とはこれね。「ソフトウェア技術者は昔も今も『高度で専門的な知識や経験を要する』職業である」。これは身びいきでなく、そうでしょ? 少なくともオレは、自分の名刺に「プログラマ」と印刷することに関して「ある水準を保ってる」ことを旨としているし、これを読んでる多くの技術者もオレと同じように考えると思う。

     次に事実を指摘する。上の真実にも関わらず、なぜワレワレが「ソフトウェア技術者は『高度で専門的な知識や経験を要する』職業ではなくなってしまった」ようだと感じるかというと、それは「ソフトウェア技術者が『高度で専門的な知識や経験を要する』職業にふさわしい扱われかた」をしていないから、もっとハッキリ言えば「安くコキ使われている」からである。

     そこで問題は、この真実と事実のギャップがどーして生じたのかである。まず最初に検討してみたい仮説は、これである。

    仮説1:ソフトウェア技術者の待遇が悪いのは受給のバランス、つまり供給が過剰だからである。「高度で専門的な知識や経験」も数が増えれば安くなるのが当然やんけ。

     どっすか? みなさん、タケナカ元大臣とか、カツマカズヨとかが言いそうな言葉だけど、これにガッテンできますか? この仮説、オレたち当のソフトウェア技術者にしてみると到底首肯しかねるシロモノだが、オレが見るところいわゆる「企業経営者」という肩書きを持つヒトたちの少なくとも50%は、この仮説を聞いて「正しい」と答えるような気がする。でっかい企業に勤めてるヒトは機会をとらえて社長とかに聞いてみて欲しいが(できないか)、なんてのかな、そういうヒトが好んで読む「日経ビジネス」とか「週刊ダイヤモンド」とかって、だいたいこういう認識だと思うのだ。

     でもこの仮説には大きな誤謬が潜んでいる。次回はそこをつっついてみる。
                           (以下次回 2009_05_29)

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

    これから始めようとする人へ(10)

     皆さんこんにちは、高橋真人です。
     今回は、Cocoaのフレームワークに備わっている自動解放プール(Autorelease Pool)という仕組みについてのお話です。ちなみに、この「プール」という言葉ですが、最近は「資金をプールしておく」などという使い方も日常的に耳にしますのでお分かりと思いますが、ここでは「貯めておく場所」という意味で使われています。

     さて、いきなりですが、以下のような関数を考えてみます。

    NSString *sjis2string(const char *sjis)
    {
    NSString *str = [[NSString alloc] initWithBytes:sjis
        length:strlen(sjis) encoding:NSShiftJISStringEncoding];
    
    return str;
    }
    
     これは、通常のC文字列として与えられたシフトJISの文字列をNSStringに変換して返す関数です。
    
    使い方としては、以下のような感じになります。
    
    int main (int argc, const char * argv[])
    {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    
    const char hello[] = "\x82\xb1\x82\xf1\x82\xc9\x82\xbf\x82\xcd\x81\x49";
    NSString *s = sjis2string(hello);
    NSLog(@"%@", s);
    
    [s release];    // 注:後半の例では、不要になります
    
    [pool release];
    
    return 0;
    }
    


     文字列helloに入っているのは、シフトJISコードで「こんにちは!」となるバイト並びです。
     それをsjis2string()に渡すと、NSStringのオブジェクトとして返ってきます。sという変数で受け、NSLog()で表示してから解放しています。
     つまりこのコードでは、sjis2string関数を呼び出した側で関数が返したオブジェクトをreleaseしています。確かに、sjis2string()の上記の実装では、allocをしているのにreleaseがありませんから、これは正しい解放です。
     ですが、このように「呼び出す側に必ず解放することを要求する」ような関数の仕様はあまりよいとは言えません。できるならば、sjis2string関数の内部でallocとreleaseのバランスを完結させたいところです。
     そこで登場するのが、Autoreleaseという仕組みです。Cocoaのフレームワークには、自動解放プールという、任意のオブジェクトを登録できるメモリ管理用のオブジェクトを作って利用することができます。
     上記のmain関数の中にも例があるように、

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    
    という要領で作成します。こうしておいて、あとは任意の場所でこの自動解放プールを使ってメモリ解放をしたいオブジェクトに対して、releaseの代わりにautoreleaseというメッセージを送るだけです。(これによって何が起こるかは、以下で説明します)
     上記の関数をこれを利用して書き換えてみると、以下のようになります。
    
    NSString *sjis2string(const char *sjis)
    {
    NSString *str = [[NSString alloc] initWithBytes:sjis length:strlen(sjis) encoding:NSShiftJISStringEncoding];
    
    return [str autorelease];
    }
    
     または、NSStringのオブジェクトを作る場所でメッセージを送っても構いません。
    
    NSString *sjis2string(const char *sjis)
    {
    NSString *str = [[[NSString alloc] initWithBytes:sjis length:strlen(sjis) encoding:NSShiftJISStringEncoding] autorelease];
    
    return str;
    }
    


     さて、このように任意のオブジェクトに対してautoreleaseメッセージを送ると、そのオブジェクトが自動解放プールに登録されることになります。
     自動解放プールのオブジェクトは、自身が解放される際に、登録されているオブジェクトに対してそれぞれreleaseメッセージを送ります。前述のmain関数の例で言うと、関数の終わりの部分の[pool release]によって、自動解放プールが開放される時に、一緒にNSStringのオブジェクトも後始末されるというわけです。
     sjis2string()が返してくるNSStringのオブジェクトは、関数から戻ってきた時点ではまだ解放されていませんから、上記例のNSLog()に渡してちゃんと出力ができますし、その後の[s release];がなくても(むしろ、あるとまずいのですが)、[pool release];のところできちんと解放されるわけです。

     ところで、自動解放プールにオブジェクトを登録する際に、明示的に登録先となる自動解放プールのオブジェクトを指定しないところに、違和感を覚える方もおいでかもしれません。「一体、いまautoreleaseメッセージを投げたこのオブジェクトは、『どの』自動解放プールオブジェクトに登録されるのだろうか?」と。
     もしくは、「プログラム全体の中で自動解放プールのオブジェクトは一つしか存在しないのかな?」と疑問をお持ちになる方もいらっしゃるかもしれません。

     自動解放プールのオブジェクトは、プログラムの中でいくらでも好きなだけ作ることが可能です。オブジェクト自体も軽量なので、あまり深く考えずにポンポン作ってしまっても、問題になることはあまりないでしょう。
     実際、Cocoaのフレームワーク自体も、内部でいくつもの自動解放プールオブジェクトを作ります。
     複数のオブジェクトを作った場合、autoreleaseメッセージは最も直近に作られた自動解放プールオブジェクトに対しての登録を意味します。

     さて、こうして自動解放プールのことを知り、それなりに使えるようになってくると、あるとき「あれ、このオブジェクトはいつ解放されるんだろう?」と疑問を感じることがあります。「ちゃんと必要な間、このオブジェクトは解放されずに残っているんだろうか」という不安を私自身も持ったことがあります。

     そんな時、先輩やドキュメントは「メモリが解放されてしまうと困る場合は、retainを呼びなさい」とアドバイスしてくれています。(この辺、リファレンスカウントという考え方が絡みますので、次回に説明します)
     結論から言いますと、一つの関数やメソッド、または自分が制御している一連の処理の間は、自動解放プールが勝手に解放されることはありません。(自分で作った自動解放プールを解放する場合は、もちろん別です)
     Cocoaの一般的なプログラムでは、イベントループというのが常に回っていてユーザーの操作などを監視しています。このイベントループの繰り返しごとにも自動解放プールが使われています。つまり、ループの1回が回り始める先頭で新しい自動解放プールオブジェクトが作られ、繰り返しの終わりのところでオブジェクトが解放されるのです。
     通常の処理、例えばユーザーのボタンクリックなどによって起動されるメソッドは、そのメソッドの末尾まで実行されるまでの間はよそから割り込まれることはなく、その間の主導権はずっと保持したままですから、知らないうちに自動解放プールが働くことはありません。(マルチスレッドが絡むと、この限りではない)
     そもそも、イベントの処理は複数のループにまたがって行われるのではなく、繰り返しの1単位の中で完結するものですから、処理の途中で気付かないうちに自分の使っているオブジェクトが解放されてしまうことはありませんから、安心してautoreleaseを使ってください。

     そうは言うものの、プログラム側の事情で、複数のイベントループをまたいで存在する必要のあるオブジェクトというのもありますよね。そういう場合はどうしたらいいのでしょう? こういったオブジェクトには自動解放プールを使ってはいけないのでしょうか?
     もちろん、そんなことはありません。そのためにCocoaのフレームワークにはretainカウントというものが備わっています。次回はそれについて説明します。

    ◇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)2009 MOSA. All rights reserved.