伊藤清徳の垂直落下式ムーンサルトプレス

PerlとかPHPとかMySQLとか…がんばっても8割だ。
4月 7

iPhoneでNSTimerでタイマー処理を行うアプリを作っている
http://d.hatena.ne.jp/moto_maka/20081210/1228855024
↑この辺が役に立った。

実際に動かしてみると、1/100秒程度はうまくいくのだが、ミリ秒単位で処理するともはやアウト。ここまでは上記のURL内の記述どおり。では、と思い色々タイマーの中で動作を記述すると、実際には1/100秒でもうまく動かない。かなり「揺れ」がある(T_T)

調べるとNSTimerはハード的な割り込みができず、信頼できないタイマーだそうだ。それってタイマーって言ってよいのか??

スレッドをつかって云々も結構問題があるみたい。やるとすれば、信頼できないタイマーを起動しっぱなしにして、NSTimeIvervalで時間計測しながらやっていくしかないかな。。。うがぁ。。。

12月 29

このところは、PhoneGapというHTML+JavascriptでiPhoneアプリを作れるものにハマっています。

HTMLでGUIを組み上げていくわけですが、
画像などを自分で用意し、CSSや<img>タグを駆使すれば、
リッチなGUIが簡単に完成します。

Javascriptで実装されている機能はほぼ完璧に使えますので、
煩わしいObjective-Cのソースを書くという作業は、相当数少なくなります。

速度はどうかなと思ったんですが、

SafariはPCの世界でも評判の速度。
そのパワーを借りるわけですから、
心配するほど遅いことはありません。

驚くべきライブラリです。
この前の記事にも書いていますが、
MITライセンスってとこがまたいいですよね!

、、、とまぁここまで散々褒めちぎっていたわけですが、
たとえばファイルの入出力などは、Javascriptの範疇じゃないので、
Objective-Cの力を借りたくなるのです。

さてどうしたものか、、、調べたところ、
PhoneGapのJavascriptAPIを拡張する方法が分かりましたので、書いておきます。
ある程度Objective-CとJavascriptの知識が必要ですので、
そのあたりは心してごらんください。

PhoneGapでは、JavascriptAPIを実行したとき、
gap.js(PhoneGapのJavascriptAPIファイル)が、

「gap:」を文頭につけたURLがリクエストされたものとしてWEBViewオブジェクトへリクエストし、
WEBViewは、受け取ったURLの頭が「gap:」だったら、
通常のURLリクエストとは別の動作(ここがAPIの実働部分)をするように構築されているようです。


PhoneGapにデフォルトで実装されている関数「Device.soundPlay()」を例に話をすすめましょう。

gap.jsを開くと、
Device.soundPlay関数の部分を見ると、

Device.exec()関数というのが実行されているのが分かります。
この関数が、WEBViewへのリクエストを出してくれる関数です。
そしてこの関数への引数は、「gap:sound:鳴らしたい音のファイル名」となっています。
これがWEBviewへ渡すリクエストです。

このリクエストがどのObjective-Cのメソッドで受け取られるかというと、
「GlassAppDelegate.m」の中の、
「- (BOOL)webView:(UIWebView *)theWebView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType」というメソッドです。
このメソッドの中で、渡されたURLを「:」で分割し、配列「parts」へ格納されます。

NSArray * parts = [urlString componentsSeparatedByString:@":"];

▲この部分ですね。

このpartsのインデックス0が「gap」なら通常のHTTPリクエスト以外の処理が行われるわけです。

//LOCATION
if([(NSString *)[parts objectAtIndex:1] isEqualToString:@"getloc"]){

▲この部分以降は、partsのインデックス1の値によって、機能を切り替えるわけです。

soundPlay()関数の場合、「gap:sound:ファイル名」というURLが渡されるので、
partsのインデックス1が「sound」だったときに、指定した音を鳴らす機能を実装してやっているわけです。

else if ([(NSString *)[parts objectAtIndex:1] isEqualToString:@"sound"]) {

// Split the Sound file
NSString *ef = (NSString *)[parts objectAtIndex:2];
NSArray *soundFile = [ef componentsSeparatedByString:@"."];

NSString *file = (NSString *)[soundFile objectAtIndex:0];
NSString *ext = (NSString *)[soundFile objectAtIndex:1];
// Some TODO’s here
// Test to see if the file/ext is IN the bundle
// Cleanup any memory that may not be caught
sound = [[Sound alloc] initWithContentsOfFile:[mainBundle pathForResource:file ofType:ext]];
[sound play];
}

▲それがここですね。
まず、ここで勘のいい人は気付いていると思いますが、
「gap:呼び出したい機能:疑似的な引数1:疑似的な引数2:疑似的な引数3…」
とリクエストするURLの2番目の「:」以降は、
「:」区切りで疑似的な引数を与えることができるのです。
soundPlayの場合は、最初の疑似的な引数へ鳴らしたい音ファイルのファイル名を渡しています。
上記のソースでは、このファイルを「Audio Queue Services」へ登録して鳴らしているわけです。
(Audio Queue Servicesの説明は、cocoaプログラムの作成方法をごらんください)

ざっと説明するとこんな感じです。はいめっちゃ分かりづらい!!笑)
しかし、これくらい読めないといいアプリは作れない!ってことで、
そういう意見はスルーします!

さて、さっきのsoundPlayのAPI、
Objective-Cのソース内では、この機能が呼び出される度に、
「Audio Queue Services」へファイルが登録され、
そしてそのファイルが再生されて終わり。。。という仕様になっています。
これはこれでいいのですが、なんか効率悪いですよね。。。

ってことで次回は、

音ファイルの登録と再生を別のJavascriptAPI関数として実装してみます。
お楽しみに。

12月 26

ちょっと前に一部の界隈で話題になったHTML+JavascriptでiPhoneアプリ作成を始めてみた。

まずはこの辺(@ITの記事)を参考に・・・。
いくつかのライブラリが出ているようだ。。。

PhoneGap
QuickConnect

というのが良さげだ。

が、しかしQuickConnectはライセンスがLGPL。。。
これはAppStoreで販売・配布しようと思うと制限がありすぎ(>_<;)

一方のPhoneGapはMITライセンス。
これなら大丈夫!
ということでPhoneGap採用!




上記の@ITの記事では、簡易RADとしてのDashCodeを利用してまずHTMLを作成しているが、
この方法だと、iPhoneSDKを十分に使いこなせなさそうだったので、
Xcodeで最初から作るという前提で、
不定期に記事を書いていきます。




まずはXcodeをインストールしてください。ちなみにMacOSX10.5(Leopard)じゃないと後述のiPhoneSDKがインストールできないので、違う人はまずOSを買ってきましょう(^-^;

XcodeはOSのCDの中にあります。




はい、次。iPhoneSDKをインストールします。

だいたいここまでで、1時間くらい要します。XcodeとiPhoneSDKのアップデートはちょくちょくチェックしておいたほうがいいです。
筆者は、iPhoneSDKをアップデートしていなかったがために、PhoneGapのサンプルがビルドできないという「症状」に4時間近く悩まされて今いました(^-^;




じゃ、ここでPhoneGapを登場させます。
ダウンロードして解凍してできたディレクトリの中に「iPhone」というディレクトリがありますので、
その中にXcode用のプロジェクトファイルがあります。
PhoneGap.xcodeproj」を開きます。
もうひとつプロジェクトファイルがありましたが、
筆者の環境ではこちらはなぜか開きませんでした。

公式のwikiに従って、下準備をします。

ここで一回テストでビルドしてiPhoneシミュレータを走らせてみましょう。
Hello!Wordld!が表示されれば、準備完了!




あとは、index.htmlに改良を加えていけばいいわけですが、
いつものHTMLアプリケーションの感覚で、

<a href="javascript:;" onclick="test();">TEST</a><br />
<div id="SET"></div>
<script type="text/javascript">
function test(){
document.getElementById(‘SET’).innerHTML = ‘test!!!’;
}
</script>

って書いたら、大変なことになりました。
こまかい説明はしませんが、
<a>タグを書くとiPhoneシミュレータが落ちますんで使わないほうがいいでしょう。
テキストにonclick属性などをつけたい場合は、
<span>タグを利用します。

画像は、Xcode上で、Resourceディレクトリ内にコピーしてやる事で利用できるようになります。
あくまでコピーです。デフォルトの状態でドロップすると参照になってしまいます。
これでは利用できないので注意してください。
またフォルダの利用は不可です。
かならずindex.htmlファイルと同階層に置く必要があります。
おそらく画像だけでなくJS・CSSファイルもだと思われます。(現時点で未確認)

画像の呼び出しは通常通り、
<img src="ファイル名" />
です。
画像にonclick属性を設定するときは、<a>タグを利用せず、<img>タグの属性とします。

ということで大体全体像がつかめたところで眠くなったので終了。。。zzz

次回はObjective-Cのクラスにアクセスできるのかをやってみますねー。
あと、画像のない記事ですまぬ。

 ANZXCvg