MOSA Multi-OS Software Artists

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

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

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

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

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

    2009-07-14

    目次

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

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

      

    〜「Deployment」編〜

     今回からDeploymentの応用編について解説します。あらためてDeploymentの課題について振り返ってみますが、コンピュータをセットアップするときまずはシステムのインストールをどうするかという問題があります。
     NetBootでクライアントコンピュータを起動して運用する場合には、これまで解説してきましたようにサーバ上にのみシステムのイメージを設置しておけばよいということになります。

     内蔵ハードティスクにシステムをインストールする場合、インストール方法は色々と考えられますが、どのような方法にしてもポイントはシステムを起動中のディスクにはシステムをインストールすることはできないということです。あたりまえのことではありますが、例えばインストールディスクからシステムをインストールする場合、いったんインストールディスクからコンピュータを起動して内蔵ディスクを未使用の状態にしてからインストールを実行します。

     NetInstallではこの作業をネットワーク経由でおこないます。つまりまずはクライアントをネットワーク経由で起動し、内蔵のハードティスクにシステムをインストールするわけです。

    ◇他のソリューション
     システム標準の機能だけでもある程度のことはできますが、他のツールを組み合わせることにより、より高度な使い方ができます。以前はこのようはツールとして「NetRestore」が有名でしたが、2008年に開発が打ち切られています。じつは次期バージョンのSnow Leopard ServerにはNetRestoreという同じ名称の機能が搭載されることがすでに公表されていますが、その詳細はまだ明らかになっていません。

    ・NetRestore開発終了のお知らせ
    http://www.bombich.com/software/netrestore.html
    ・Snow Leopard Server
    http://www.apple.com/server/macosx/features/client-management.html

     NetRestoreのWebサイトでも紹介されているのですが、「DeployStudio」というDeploymentをサポートするソフトがありますので、こちらを取り上げてみたいと思います。DeployStudioは柔軟に設計されていますので、色々な使い方ができるのですが、例えばNetBootと組み合わせて使用することができます。
     DeployStudioでは専用のNetBootイメージを作成することができ、クライアントをDeployStudio用のNetBootイメージから起動するとDeployStuioのランタイムが起動して、システムのリストアを実行することができます。ランタイムではカスタマイズ可能なワークフローを利用することができ、システムのリストア以外にもパッケージのインストールや、NetBoot起動したクライアントのシステムからイメージを作成してサーバにアップすることもできます。
     また標準でサポートされているものの、GUIからは利用することのできないマルチキャストによるリストアにも対応していたり、NetBoot起動したクライアントでVNCを起動してリモートで画面共有ができたりします。

    ◇DeployStudioのインストール
     ではまずインストール方法ですがDeployStudioのWebサイトからインストーラをダウンロードします。トップページの左下にダウンロードリンクがありますので、ここから「DeployStudio Server」をダウンロードします。原稿執筆時点での最新版はv1.0rc12(stable)となっています。対応するOSのバージョンは10.4.11および10.5.0以降となっています。

    ・DeployStudioのWebサイト
    http://www.deploystudio.com/Home.html

     ではこのインストーラをどこにインストールするかですが、NetBootと組み合わせて利用するにはまずNetBootサーバ上でインストールします。さらにリモートでDeployStudioを管理したい場合には、管理用のMacにもインストールします。
     DeployStudioをインストールすると「/アプリケーション/ユーティリティ」に以下の3つのツールがインストールされます。

    ・DeployStudio Admin:管理ツール
    ・DeployStudio Assistant:セットアップツール
    ・DeployStudio Runtime:ターゲットコンピュータ上で実行されるツール

     さらに「システム環境設定」にも「DeployStudio Server」という項目が追加されます。ここでは、次のようなシステム構成を例に解説をしていきたいと思います。

    ・NetBootサーバ(Mac OS X Server)
    ・管理用Mac(Mac OS X)
    ・ターゲットコンピュータ

     NetBootサーバと管理用MacにはそれぞれDeployStudioをインストールしておきます。またNetBootサーバにはあらかじめリストア用のシステムイメージが用意されているものとします。ターゲットコンピュータとはDeployStudioでシステムをリストアするためのコンピュータです。
     まず最初の設定ですが、NetBootサーバで「システム環境設定」>「DeployStudio Server」を表示し、スイッチをOnにします。これでNetBootサーバ上でDeployStudioServer daemonが起動します。この手順はNetBootサーバ上のみでよく、管理用Macでは行う必要はないです。またこの時点ではレポジトリへのアクセスに失敗したとのメッセージが表示されますが、これはこの後の設定で解消されます。レポジトリとはリストア用のイメージなどを格納しておくフォルダのことです。レポジトリをNetBoot以外のサーバで運用することも可能です。

    ・Daemonの起動
    http://www.htabata.com/img/MXS105/ds/Pref_01.png

     さて、それでは次回は設定方法の続きを解説いたします。
                                 次回へつづく

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

    〜 UITableViewのデータソースとデリゲート 〜

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

    データソースには、UITableViewDataSourceプロトコルに準拠したメソッドを実装します。またデリゲートには、UITableViewDelegateプロトコルに準拠したメソッドを実装します。Interface Builderでテーブルビュー(UITableView)のdataSourceとdelegateアウトレットを「File’s Owner」(UITableViewControllerのサブクラスであるRootViewController)に接続したことを思い出してください。よって、両プロトコルに準拠したメソッドはRootViewControllerクラスに実装することになります。

    まずはデータソースからです。UITableViewDataSourceプロトコルには、全部で11のメソッドが用意されています。これらのメソッドは、UITableViewに内容を表示するために必要となるデータを提供します。このうち、絶対に実装しなければいけないメソッド(必須)が2つ、実装しなければデフォルト値が使われるメソッド( オプション)が9つ定義されています。

    ・データソースの必須メソッド(2)

    - (NSInteger)tableView:(UITableView *)table numberOfRowsInSection:
                                                              (NSInteger)section;
    


    指定セクション(テーブルの表示グループ)内のデータ配列数を返す。つまりテーブル表示が何行あるのかを返します。何も表示されていなければゼロを返します。

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:
                                                        (NSIndexPath *)indexPath;
    


    テーブルビューは、表示内容(文字列や画像)を配置したUITableViewCell(UIViewのサブクラス)が順番に並びます。指示された行番号(indexPath.rowで参照)に対して、そこに表示すべきUITableViewCellオブジェクトを返してやります。

    ・データソースのオプションメソッド(9つ)

    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;  

    セクション数(テーブル表示のグループ分け数)を返します(デフォルトは1)。

    - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:
                                                              (NSInteger)section;

    指定セクションに表示したいヘッダータイトル(文字列)を返します。

    - (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:
                                                              (NSInteger)section;

    指定セクションに表示したいフッタータイトル( 文字列) を返します。

    - (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView;

    テーブルビューの右側に表示されるインデックス(A,B,Cなどの索引)の文字列を含んだ配列を返します。インデックスを使わない場合には実装しません。

    - (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:
                                        (NSString *)title atIndex:(NSInteger)index;

    インデックス(索引)に対応するテーブルのセクション番号を返します(Bは1とか)。

    - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:
                                                        (NSIndexPath *)indexPath;

    行の挿入や削除に用います。行が編集可能かどうかの判断(YESかNO)を返します。NOだと(+)や(ー)マークは表示されません。

    - (void)tableView:(UITableView *)tableView commitEditingStyle:
                                    (UITableViewCellEditingStyle)editingStyle
                                   forRowAtIndexPath:(NSIndexPath *)indexPath;

    挿入や削除などの行の編集が行われた場合に呼ばれます。実際の編集処理を、このメソッド内に記述します。どのような種類の編集かはeditingStyleで判断します。

    - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:
                                                        (NSIndexPath *)indexPath;

    行の順番の入れ換えに用います。行が移動できるかどうの判断(YESかNO)を返します。YESを返すとテーブル編集時に行の右側に移動用タップエリアが表示されます。

    - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)
                sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath;

    行の順番の入れ換えに用います。行が移動させられた時の実際の処理を、このメソッド内に記述します。

    続いてデリゲートです。UITableViewDelegateプロトコルには全部で19のメソッドが用意されています。デリゲートの方には必須は無くすべてがオプションですが、iPhone OS 3.0で新規に追加されたメソッドが3つ、廃止(Deprecated)されたメソッドが1つ含まれています。

    ・デリゲートのオプションメソッド(19)

    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:
                                                      (NSIndexPath *)indexPath;

    その行番号(indexPath.row)の行の高さを指示する(デフォルトは44ピクセル)。

    - (NSInteger)tableView:(UITableView *)tableView
                  indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath;

    行のインデンテーションレベルを返す(グループタイプのテーブルビューのみに有効)。

    - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell
                                   forRowAtIndexPath:(NSIndexPath *)indexPath;

    行に表示するセル( UITableViewCell )内容をカスタマイズすることが可能。このメソッドはセル描画時に呼ばれる。

    - (void)tableView:(UITableView *)tableView
          accessoryButtonTappedForRowWithIndexPath:(NSIndexPath*)indexPath;

    アクセサリー(行右側の小さなボタン)がタップされた時の処理を実装する。

    - (UITableViewCellAccessoryType)tableView:(UITableView *)tableView
                  accessoryTypeForRowWithIndexPath:(NSIndexPath *)indexPath;

    行の右側に表示されるアクセサリーのタイプ(>など)を指示する。iPhone OS 3.0で廃止(Deprecated)された。

    - (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:
                                                      (NSIndexPath *)indexPath;

    行の選択(行をタップ)開始時に実行する処理を実装する。nilを返すと選択拒否となる。

    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:
                                                      (NSIndexPath *)indexPath;

    行の選択(行をタップ)終了時に実行する処理を実装する。

    - (NSIndexPath *)tableView:(UITableView *)tableView 
                          willDeselectRowAtIndexPath:(NSIndexPath *)indexPath;

    行の選択解除(別の行をタップ)開始時に実行する処理を実装する(セレクション開始)。nilを返すと選択解除拒否となる。iPhoen OS 3.0から利用可能。

    - (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:
                                                      (NSIndexPath *)indexPath;

    行の選択解除(別の行をタップ)終了時に実行する処理を実装する(セレクション開始)。iPhoen OS 3.0から利用可能。

    - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:
                                                              (NSInteger)section;

    セクションヘッダーに配置するカスタムビュー(UIView)を指示する。

    - (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:
                                                              (NSInteger)section;

    セクションフッターに配置するカスタムビュー(UIView)を指示する。

    - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:
                                                              (NSInteger)section;

    セクションへッダーの高さを指示する(デフォルトは24ピクセル)

    - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:
                                                              (NSInteger)section;

    セクションフッターの高さを指示する(デフォルトは24ピクセル)

    - (void)tableView:(UITableView*)tableView willBeginEditingRowAtIndexPath:
                                                      (NSIndexPath *)indexPath;

    編集開始時に呼ばれる(例えばナビゲーションバーの編集ボタンをタップした
    時)。

    - (void)tableView:(UITableView*)tableView didEndEditingRowAtIndexPath:
                                                (NSIndexPath *)indexPath; 

    編集終了時に呼ばれる。

    - (UITableViewCellEditingStyle)tableView:(UITableView *)tableView
                      editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath;

    追加や削除などの編集スタイルを返す。これにより編集時に行の左側に(+)や(ー)などのマークが表示される。

    - (NSString *)tableView:(UITableView *)tableView
    titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath;

    編集時に行の右側に表示される赤い「削除」ボタンの文字列内容を変更する。iPhoen OS 3.0から利用可能。

    - (BOOL)tableView:(UITableView *)tableView
            shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath;

    編集時に行をインデントさせ(+)や(ー)マークを外に表示させるかどうか判断する。グループタイプのテーブルビューのみに有効(デフォルトはYES)。

    - (NSIndexPath *)tableView:(UITableView *)tableView
    targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath
            toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath;

    編集モードで行の移動や並び替えを実行した場合に呼ばれる。必要ならば、実際のモデルオブジェクトの順序入れ換えをここで実行する。

    iPhone OS 3.0で廃止されたtableView:accessoryTypeForRowWithIndexPath:メソッドを使っていたアクセサリータイプの変更は、UITableViewCellのaccessoryTypeプロパティで指示するよう推奨されています。また、iPhone OS 3.0になり、行の選択解除時に呼び出されるデリゲートメソッドが追加されているのですが、UITavleViewのヒューマンインターフェースガイドラインによると、テーブル行の選択状態はそのまま残しておいてはいけないはずでした。
    なぜ追加されたのでしょうか? サブクラス対策でしょうか?

    次回は、本アプリのビューコントローラー(RootViewController)に、必要とされるデータソースとデリゲートメソッドの実装を行います。テーブルビューに表示する内容は、モデル(Model)オブジェクトに登録されていいる画像ファイルの名称やサムネイルとなる予定です。

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

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

    ・コマンドラインからPHPを使う
     前回紹介した方法は、WebブラウザなどのクライアントサイドからPHPを実行できるよう、ApacheモジュールのPHPをセットアップするものです。Leopardには、コマンドライン版のPHP(/usr/bin/php)も収録されているため、
    /etc/apache2/httpd.confを編集してApacheの設定を変えることなく、つまりはWebサーバ(システム環境設定でいえば「Web共有」サービス)を動作させることなく、PHPスクリプトを実行することが可能です。
     たとえば、お約束の「Hello World」は、以下に示すとおりphpコマンドを実行すれば表示できます。ここで使用するオプション「-r」は、続く引数をPHPコードとして評価 / 処理する役割を果たします。なお、PHPのタグ()を入力する必要はありません。
    【編集部注:以下円記号はバックスラッシュに置き換えてください】

    - - - - -
    $ php -r 'print "Hello World¥n";'
    - - - - -
    


     LeopardにはPHP 5が収録されていますから、PHP 5の豊富な関数も利用できます。たとえば、以下のコマンドではPHP 4.3からサポートされたstr_shuffle関数を利用し、与えられた文字列(ここでは「mosa」)をランダムに入れ替えて返しています。

    - - - - -
    $ php -r 'echo str_shuffle("mosa"),"¥n";'
    - - - - -
    


     ファイルとして存在するPHPスクリプトを処理することもできます。オプション「-f」(省略可)に続けてファイル名を指定すれば、結果が標準出力(ターミナルの初期値ではターミナルの画面)へアウトプットされるので、次に示すように結果をファイルへリダイレクトして保存することもできます。なお、PHPスクリプトの拡張子が「.php」である必要はなく、適当なものでも正しく処理されます。

    - - - - -
    $ php -f ~/Sites/info.php > phpinfo.txt
    - - - - -
    


    ・PHPスクリプトをチェックする
     phpコマンドは、スクリプトの構文チェックにも利用できます。使用するオプションは「-l」、スクリプトを引数に指定して実行すれば、結果が表示されます。「)」の記述漏れなど単純なミスの発見に役立ちますが、未定義関数の使用などといった構文以外に起因するエラーは検出できません。

    - - - - -
    $ php -l wp-comments-post.php 
    No syntax errors detected in wp-comments-post.php
    - - - - -
    


     複数のスクリプトをまとめてチェックするときには、findコマンドと組み合わせて実行すると効率的です。以下のコマンド実行例では、カレントディレクトリ以下にある拡張子「.php」のファイルすべてを対象に、構文チェックを行っています。

    - - - - -
    $ find . -name '*.php' -exec php -l {} ¥;
    - - - - -
    


    ・処理内容を1行ごとに入力する
     Leopardに収録されているPHP 5は、phpコマンドに「-R」オプションを追加しています。このオプションを使用すると、標準入力から1行ごとにデータを取り込み、それを順に処理することが可能になります。
     以下に示すコマンド実行例は、lsコマンド(ファイルリストを表示するコマンド)とphpコマンドをパイプし、lsコマンドの結果をPHPのstrtoupper関数(引数の文字列に含まれる英字すべてを大文字に置換する)で変換し、ターミナルの画面に出力するものです。このように「-R」オプションを使用すれば、mb_convert_variables関数でテキストファイルのエンコーディング形式を一括変換する、といったPHPの処理がターミナル上で実行できます。

    - - - - -
    $ ls | php -R 'echo strtoupper($argn),"¥n";'
    - - - - -
    
    


    ・シェルスクリプト風に使う
     phpコマンドは、bashなどのシェルと同様、テキストファイルの先頭にパスを記述(#!/usr/bin/php)したうえで実行権限を与えておけば(chmod + x 〜)、シェルスクリプトとして活用できます。
     反対に、PHPスクリプトからUNIXコマンド/シェルスクリプトを呼び出し、クライアントであるWebブラウザに結果を返すこともできます。次回は、そのときに使用されるPHPの関数「shell_exec」の使用例を紹介する予定です。

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

    2009-07-07

    目次

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

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

    今回は、既存のiPhoneアプリケーションのプロジェクトに、iPhone RubyCocoaを組み込んでみることにします。例として、iPhoneのサンプルコードの1つViewTransitions をリモートアクセスできるようにしてみましょう。

    その前に、前回作った iPhone RubyCocoa のプロジェクトフォルダは使い回すことができるので、再利用しやすいように適当な名前(ここではiphone-rubycocoa-sim とします)をつけてどこかに保存しておいてください。

    ■ iphone-rubycocoaフォルダのコピー

    まず、iPhoneのサンプルプロジェクトViewTransitionsを準備してください。このサンプルは、Xcodeのメニューの「ヘルプ/Xcodeの製品ドキュメント」からダウンロード(といってもすでにローカルのディスク内にあるはず)できます。

    準備ができたら、Finderで、ViewTransitionsフォルダの中にiphone-rubycocoa-simフォルダをコピーしてください。

    ■ rubyとrubycocoaの組み込み (1) — C/Objective-Cプログラム部分

    次に、Xcodeで、ViewTransitions.xcodeproj とiphone-rubycocoa-sim/rubycocoa4iphone.xcodeproj の両方を開きます。

    まず、rubyを組み込みます。rubycocoa4iphoneプロジェクトウィンドウの右側にある「ruby」グループを、ViewTransitionsプロジェクトウィンドウのViewTransitionsにドラッグドロップします。表示されるダイアログパネルの設定は変えずに、そのまま「追加」してください。

    さらに、rubycocoaを組み込みます。「rubycocoa」グループをrubyグループと同様にドラッグドロップして追加します。

    これで、rubyとrubycocoaのうち、C/Objective-C で書かれている核心部分が組み込まれました。

    ■ rubyとrubycocoaの組み込み (2-1) — Rubyプログラム部分

    次に、RubyCocoaのRubyプログラム部分やremote-irbなどのrubyライブラリを組み込みます。rubycocoa4iphoneプロジェクトウィンドウの右側のResourcesグループから、以下の3つ:

    ・main.rb
    ・rubycocoa.rb
    ・utils

    を、ViewTransitionsプロジェクトのResourcesグループにドラッグドロップします。さきほどと同様、パネルの設定は変えずそのまま追加してください。

    ここまで完了した時点で、以降の作業では rubycocoa4iphone プロジェクトは使わないので閉じておくとよいでしょう。

    ■ rubyとrubycocoaの組み込み (2-2) — ビルドフェーズの追加

    最後にrubyの添付ライブラリを組み込みます。rubyのライブラリを正しく動かすためには、ディレクトリの階層構造を保ったままコピーする必要があります。Xcodeで階層構造を保ったままコピーするより良い方法がわからなかったため、ここでは、ビルドフェーズで実行されるスクリプトとして組み込むことにします。

    ViewTransitionsプロジェクトウィンドウを選んでおき、プロジェクトメニューの「新規ビルドフェーズ/新規スクリプト実行」コマンドを実行して、以下の1行のスクリプトを設定してください。

    cp -R iphone-rubycocoa-sim/ruby/lib $BUILT_PRODUCTS_DIR/$PRODUCT_NAME.app/

    ■ main.m の変更

    あとは、main.rb の Rubyプログラムが実行されるように main.m を変更すればすべて完了です。main.m を以下のように変更してください。

    #import 
    #import "RBRuntime.h"
    int main(int argc, const char *argv[]) {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    int ret = RBApplicationMain("main.rb", argc, argv);
    [pool release];
    return ret;
    }
    


    元の main.m との違いは、RBRuntime.h を import していることと、UIApplicationMain の代わりに RBApplicationMain を読んでいることの2点だけです。UIApplicationMain は、main.rb の中で、remote_irb を起動したあとに呼ばれます(main.rb を見てみてください)。

    ■ ビルド

    ではビルドしてみましょう。困ったことに、29個の警告と2個のエラーが発生してしまいました。ViewTransitions は iPhone Simulator 3.0 向けなので、2.2.1 をベースとした iPhone RubyCocoa ではエラーが発生してしまったわけです。

    これらの警告やエラーのほとんどは、自動生成された Objecitve-Cコードである rb_Foundation.m の中で、廃れつつあるAPIを使っていることに起因しているのですが、とりあえず警告は無視します。2つのエラーは、完全に廃れた定数(NSDateFormatterBehavior10_0, NSNumberFormatterBehavior10_0)のRuby側インターフェースを定義しようとして発生しています。この定数はなくても良いので、それぞれの行(rb_Foundation.mの338行目と1554行目、をコメントアウトしてください。

    では、ふたたびビルドしてみましょう。今度はリンクでエラーがでました。エラーの原因になっている_NSConstantStringClassReference という値も、ここでは不要なので、rb_Foundation.m から関係する関数を削除してしまいます。

    コメントアウトする部分をまとめると以下の4カ所になります:

    ・rb_Foundation.m 338行目、NSDateFormatterBehavior10_0 の定義
    ・rb_Foundation.m 1554行目、NSNumberFormatterBehavior10_0 の定義
    ・rb_Foundation.m 2288行目、_NSConstantStringClassReference の定義
    ・rb_Foundation.m 2241-2246行目、osx__NSConstantStringClassReference

    再度、ビルドしてみしょう。今度はビルドに成功するはずです。

    ■ リモートアクセス

    では、iPhone Simulator で ViewTransitions を走らせて、telnetでリモートアクセスしてみましょう。

     $ telnet localhost 6000
     Trying ::1...
     Connected to localhost.
     Escape character is '^]'.
     >> app = OSX::UIApplication.sharedApplication
     => #
     >> app.delegate.nextTransition(nil)    # アクションを実行
     => nil
     >> app.delegate.performTransition      # アクションの中身を直接実行
     => nil
    


    nextTransition は、UI上にただ一つ存在するボタンから接続されているアクションです。performTransition はnextTransition から呼ばれて実際のtransition を実行します。どちらも ViewTransitionsAppDelegate.m で定義されています。

    このように、Objective-Cで書かれたiPhoneアプリケーションのプロジェクトにiPhone RubyCocoa を組み込むことにより、状態の確認や操作などの試行錯誤的作業を、アプリケーションを実行させたまま出来るようになります。

    今回紹介した方法は、他のサンプルプロジェクトやXcodeのプロジェクトテンプレートで生成したプロジェクトについても、おおよそ同様の手順で組み込むことができるでしょう。

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

     前回の続き、なぜ日本のソフトウェア産業では「人月の神話」がまかり通る……言い換えればプログラマの売り物である「技術」(オレを含めプログラマ自身はこれこそ自分の売り物だと思ってるはずだ)ではなく「人月」というカタチの「時間」を売るのであろうか。

     ……いきなり手前味噌な話を始めてマコトに恐縮なのだが、ワタシが以前書いた「プログラマを笑え!」という本の中に以下の如きくだりがある。ちょい長くなるが引用するね。

     他の業界は知らずこのソフトウェア業界の営業パーソンたちは、まずソフトウェアに関する商品知識を培おうとしないどころかそれが持てないからこそオレは営業をやっているんだとうそぶくようなヤツが一般的であり、かつ業界動向なんてモノにもほとんど興味がない、のである。
     特にソフトウェアの受託開発をするような会社において、営業に商品知識がないということ、すなわち自分トコのプログラマたちの腕とコストを把握していないというのは致命的なことである。誰が考えたってわかる理屈だろう。「高いモンを安く売ってしまう」かも知れないからだ。
     ところがである。不思議なことにこの業界においては、安いものを高く売ろうが高いものを安く売ろうがとにかく営業は売れば褒められることになっており、その仕事が赤字になった責任はすべて実作業を行うプログラマ側が負わされるのである。いや、他の業界のヒトはそんな馬鹿なと思うだろうがそうなのだ。

     5年ほど前の本だけどさして状況は変わってない。つうか、オレがこの業界にはいった1983年、あるいは前回紹介した「人月の神話」が出版された1975年からこのアタリの事情はぜーんぜん変わってないでしょ。

     図らずもこの文中でオレが喝破しておるように、つまるところこの業界が「技術」の代わりに「時間」を売るのは、「売る仕事」をしている連中が「技術」の価値を評価できないからなのである。もっとわかりやすく言えば八百屋のおやっさんが、旬のモノだろうとハウス栽培だろうと有機農法だろうと農薬びしばしの中国産だろうとええいかまうもんかオレに区別がつかないんだから客にも区別なんかつくもんか、とにかくオレが売るネギはどんなネギでも1本50円だぁ、と言って売っちまってるようなものなのだ。

     で、最も大きな問題は上の啖呵のなかにある「オレにも区別がつかないんだから客にも区別なんかつくもんか」というのが、恐ろしいほど正鵠を衝いていることなんだよね。

     一昨年(もう一昨年なんだよね)、いわゆる「宙に浮いた年金問題」が明るみに出たとき「コンピュータ上での照合に必要なプログラムの開発費用」として厚生労働省がNTTデータに払った金額を憶えておいでだろうか? 10億円である。あのあとオレんとこにも「ねんきん特別便」ちうのが来たが、あれに記載されているくらいのデータの類似レコードを抽出してひとまとめにするくらいのプログラム、そーんなに難しいと思いますか? オレもそうだが「1億くれたら、いや5千万でも喜んでやります」ってヒトが多いんぢゃない?

     こういうことを言うと、かならず「それは違う、おっきな会社はその仕事に対する責任も含めて巨額の費用をもらうのだ」とか眠たいこと言うオッサンがいるんだが、責任なんて取ってないぢゃん。年間650億もかかってる年金記録システムが、名寄せ失敗データを10年間も放置してきた結果の問題を修正するために、あらためて10億もらっておいて「責任」なんておこがましいだろ。

     おっと、怒りのあまり話が逸れた。結論として、売り手(この産業における営業パーソン)も買い手も、ソフトウェア(とその開発作業)の価値をキチンと評価できないから、ジッパヒトカラゲ(人月)に、そしてブランド(あれはNTTデータだから10億なのだ)重視でペイメントが決められるのである。
                           (以下次回 2009_07_03)

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

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

     皆さんこんにちは、高橋真人です。今回はリファレンスカウントについての説明をしていきます。
     では、以下のサンプルコードをご覧ください。(実際に動かしてみたい方のための説明が記事末尾にあります)

    #include 
    #include 
    #include 
    
    #define LIST_LENGTH 20
    
    typedef struct {
      char name[50];
      int age;
    } Person;
    
    void make_list(Person *list[]);
    void print_list(Person *list[]);
    void clear_list(Person *list[]);
    
    int main (int argc, const char * argv[])
    {
      srand(7);   // 乱数生成(make_list)のための準備。タネをあえて固定。
      Person *list[LIST_LENGTH];
      memset(list, 0, sizeof(list));
    
      make_list(list);
    
      print_list(list);
    
      clear_list(list);
    
      return 0;
    }
    
    
    void make_list(Person *list[])
    {
      int i;
      for (i = 0; i < LIST_LENGTH; ++i) {
          list[i] = malloc(sizeof(Person));
          if (list[i] != NULL) {
              list[i]->age = rand() % 30 + 20;    // 20〜49の間の乱数
              char buf[BUFSIZ];
              snprintf(buf, sizeof(buf), "Sample name_%d_.", i + 1);
              strcpy(list[i]->name, buf);
          }
      }
    }
    
    void print_list(Person *list[])
    {
      int i;
      for (i = 0; i < LIST_LENGTH; ++i) {
          printf("[%02d] age: %d, name: %s n",
                 i + 1, list[i]->age, list[i]->name);
      }
    }
    
    void clear_list(Person *list[])
    {
      int i;
      for (i = 0; i < LIST_LENGTH; ++i) {
          if (list[i] != NULL) {
              free(list[i]);
              list[i] = NULL;
          }
      }
    }
    


     分かり易くするために作為的なプログラムですが(笑)、簡単に解説します。
     人の名前と年齢を持った構造体Personを定義し、Person構造体へのポインタを20個保持する配列listを用意します。
     対話的にデータ入力をするのは省略して、単純に乱数を利用して年齢を作り、特に意味のない(だけど、識別だけは可能な)名前としての文字列を格納します。

     実際のところ、この程度のデータ量であれば、あえてポインタの配列にせず、直接Person型を20個格納してしまう配列を作れば充分ですが、そこは、あくまでも説明のための例なので(笑)。
     ここが話のスタートとなるわけですが、このプログラムにおいてはすべてのPersonデータ(のために確保されたメモリ領域)は、それぞれ一カ所からしか参照されていないので、全く問題はありません。シンプルなものです。
     問題は、1つのPersonデータが複数の個所から参照されるところから始まります。まず、上記のシンプルな例をしっかりと把握して、今後の複雑化に備えてください(笑)。

     注:コードを実際に動かしてみないと理解できない人のために。Xcode(3.1)で動かすためには、ファイルメニューから「新規プロジェクト...」を選び、Mac OS XのCommand Line Utilityというテンプレートを選びます。表示されたアイコン一覧の中から、Standard Toolというのを選び、適当な名前(英数字のみの名にしておいた方が無難)を付けて保存します。
     プロジェクトのウインドウが開きます。右側のファイル一覧からmain.cというファイルをダブルクリックして開きます。main.cの中身を上記のサンプルコードとまるごと置き換えてください。
     実行メニューから「実行」(コマンド+オプション+R)を選べば、コンパイル、リンク、実行が一気に行われます。出力結果は、実行メニューの「コンソール」(コマンド+シフト+R)で見ることができます。

     次回への振り:「今回は、これだけなの?」と、まだまだ余裕のある方へ。
    上記のプログラムに以下のような処理を加えてみてください。

    ・20代の人のみを抽出し、別途リストを作る
    ・リストを年齢順にソートする
    ・リストを20代、30代、40代に分離し、最初に作ったリストは廃棄する

    ◇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.