2012年12月11日火曜日

[Titanium奮闘記8日目]requireとexportsを使ってシングルコンテキスト #TitaniumJ

○シングルコンテキストであたふた

とりあえずいろんな人のページを見ながらコードを書いていく事に。

exports.spotWin = function(){
     〜あれこれコード〜
     return spotwin;
}

これだと謎のエラーが発生。

[object Object] is not a constructor (evaluating 'ほげほげ'

そこで一度関数を作り、それを後からexportするとエラーが出なくなった。

function spotWin(){
   
     〜あれこれコード〜

     return spotwin;
}

module.exports = spotWin;



しかし今度は表示されて欲しい画面が出てこない…なんでや。

ここでもう一度呼び出し元のソースを確認。

/* テーブルをクリックでタブが開く */
table.addEventListener('click', function(e){
     if (e.rowData.hasChild) {

          var nextWin = require('spotwin');
          win = new nextWin();
          win.barColor = '#000';
       
               〜中略〜

          spotWinBtn.addEventListener('click',function(){win.close()});

          win.open({modal:true});
     }
});

あれ、こっちでwin開いてるじゃん。

というわけで、spotwin.jsに書いてあった「spotwin.open();」を削除。
すると今度はこんなエラーが。

[ERROR] Script Error = Can't find variable: module at spotwin.js (line 23).

なんだこれ。。。

moduleがオブジェクトじゃなくて変数として見られてる?でも前のテストバージョンではうまく行ったのになんで?

もうやけくそでmodule.exportsをexportsのみにしてみた。すると普通に通りました。なぜだ…orz

とりあえず通ったからいいや…(注・まだ続きます↓



○さすがAndroid!俺たちに出来ないことを平然とやってのけるッ!

そこにシビレもしないし憧れもしないよ。

実は上記の方法だとエラーが出てしまいます。



Uncaught TypeError:Object is not a function.

win = new nextWin();

winの前にvarを入れたりとか、小さい頭でいろいろ試してみましたが、全部ダメ。

結局またやけくそでうまく通っていた時のうまく行ってた場所をまんまパクってみたところ…

通ったよ!
なんなんだよもぅ!

そもそもテスト段階で上手くいったソースを見てる限り、外部モジュールは利用していないし、moduleを定義していないのに使えるようになってること自体おかしいですよね。

これ多分CommonJSで定義されてるんだろうな…だから当然require以下も書き方が決まっていたってこと?

あくまで推測なんですが…教えて偉い人…

多分ここに詳しいことが載ってるんだろうけど…後で読む…
http://d.hatena.ne.jp/donayama/20111230/commonjs_modules_in_titanium



○tableViewのどの行が押されたのかを取得する

table.addEventListener('click', function(e){
     Ti.API.info(e.index);
}

e.indexってやつで何番目の行が押されたのかが分かります。

これを利用して、子windowに値を引き渡します。


ここを参考にしながら…
http://ti.masuidrive.jp/topic.php?id=174





よっしゃー!一発で通った!




またお前か。



もう考える気力がなくなったので、結局Ti.App.を使うことに。

まぁシングルコンテキストは一応出来るようになった(はず)だし、まぁいっか…(´・ω・`)



○明日の予定

・2点間から方角を指す部分を導入。
・あとリアルタイムで距離を測定するところも実装。

とりあえずそこが出来れば修論のプロトタイプとしては最低ラインができることになります…長かった…。

2012年12月6日木曜日

[Titanium奮闘記7日目シングルコンテキストと連想配列 #TitaniumJP


○つまづく人が多いと聞いてたものの


tableViewはかなりつまづく人が多いと聞いていたんですが、ここら辺に関してはほとんどつまづくことなく実装できました。ギターでいうところの「Fコードが押さえられない」的なことだと思ってたんだけどなぁ。
それ以前に、プログラミングって開発環境を整えるだけで挫折する人多いですよね…実際すっごい難しいと思います…。



○前回の画面遷移で言えば良かった話

シングルコンテキストとマルチコンテキストの話です。

Titaniumで切り分けた別のクラスでグローバル変数を用意したいとき、どうしますか?
window間でどうやって変数を共有するか、ですね。
Titanium2.0からはシングルコンテキストが推奨され、それを利用すると変数受け渡しが随分ときれいになりそうなので、まとめてみます。
http://yuriponx.com/2012/06/01/titanium-mobile2-0%E3%81%A7%E3%82%B0%E3%83%AD%E3%83%BC%E3%83%90%E3%83%AB%E5%A4%89%E6%95%B0%E3%82%92%E8%80%83%E3%81%88%E3%82%8B/
シングルコンテキスト?マルチコンテキスト?なんですかそれ。
っていうか女子大生でこのくらい情報量のあることが書けるのかぁ…すげーなぁ…

自分なりの解釈ですが、シングルコンテキストは一つのウィンドウで済むことはそれだけで完結させなさいってこと。
つまり昨日していた、新しいウィンドウを作ってオープンさせる方法はあまり良くないってことですよね。ガーン…orz

一方で欠点としては

* コードを書くのが若干難しくなる
というものがあると思う。
特に非プログラマにとっては敷居が高い気がする。
まあ変化の速いTitanium界隈で現状そんな話がありますよということで。
マルチコンテキスト、ダメ絶対。とかそういう話ではない。
http://higelog.brassworks.jp/?p=1724



まぁそれにTi.Appでうまく行けてるみたいだし…強行突破するか…?



○連想配列を並び替える

これはTitaniumというよりJSのお話ですね。

JSでは配列のソートをさせる関数としてsort()というものがあります。

hogeArr =[1, 5, 8, 3];
alert(hogeArr); // 1, 5, 8, 3
hogeArr.sort();
alert(hogeArr); // 1, 3, 5, 8

カッコの中に関数を入れると並び方の条件を加えることが出来ます。

hogeArr =[1, 5, 4, 3, 9];
alert(hogeArr); // 1, 5, 4, 3, 9
hogeArr.sort(revSort);
alert(hogeArr); // 9, 5, 4, 3, 1

function revSort(a,b){
    if (b > a){ return 1} else { return -1};
}

ただ、連想配列の場合はなんかうまく行きません。
僕はこんな感じで回避しました。

var dataArr = [
{nearDist:586,nearId:0},
{nearDist:1067,nearId:1},
{nearDist:381,nearId:3},
{nearDist:3950,nearId:4},
{nearDist:2886,nearId:5}
];

dataArr.sort(renSortFunc);
alert(dataArr);

function renSortFunc(a,b) {return (a.nearDist > b.nearDist) ? 1 : -1;}

そういえば「?」を使った条件分岐初めて使ったなぁ。
条件が短いとこっちのほうが書きやすいし分かりやすいかも。



○明日の予定

・スポット情報の部分の実装
・答え合わせボタンの実装と閾値設定

今週はTitanium以外にしないといけないことがいくつかあるのでなかなか進まないですね…。
とは言いつつ、アプリ自体は少しずつですが確実に出来てきているのでこの調子で行きたいと思います。

2012年12月4日火曜日

[Titanium奮闘記6日目]ウィンドウを切り替える(画面遷移) #TitaniumJP

○今さら画面遷移について考える

そういえば画面遷移について全く考えてなかったので考えてみます。

現状は、最初app.jsが読み込まれたときに位置情報が取られるボタンが表示されて、それを押すと位置取得&マップと緯度経度が表示される(find.js)。

窓が下からニュッと出てきて(モーダルウィンドウって言うらしいです)find.jsを取ってきてるんですが、僕の小さな脳みそでは階層が増えるだけでとたんにややこしくなりそうだったので、ワンウェイな作りにしてみようと思います。こんな言い方していいのかな…というか伝わってるのかな…。
どうせいつか画面遷移は勉強しないといけないので、たくさんウィンドウを作っていきます(もちろん階層が増えた場合のも勉強しないといけないんですが)



■first.js
次の窓に飛ぶと位置情報が取られるため、そのクッションとしての窓。

■find.js
位置情報を取得、自分の現在地が分かったらボタンを押す。

□table.js
現在地から半径○キロ以内のスポットをテーブル表示。
その内の一つを選択するとスポットデータが表示される。

□spotwin.js
スポットデータが表示される(名前などは伏せられている)。
ヒントはタップすると表示される。

□success.js
スポット近くまで行くとボタンが表示され、ポイントが加算される。

(■:実装済 □:未実装)



これを実装するには、TabGroupを使う方法と、NavigationGroupを使う方法の2パターンのやり方があるそうな。

参考→http://bowz.info/3555

自分もTabGroupを採用しました。こっちを使ってる人が結構多そうだったので。



○ここでもAndroid特有のエラー

で、サンプルコードを参考にして早速起動してみると、iOSではうまくいきましたが、Androidではエラーが出ます。
どうやらhideTabBar()がAndroidでは対応していないみたいですね。なんでやねん。

代わりにcreateWindow()のプロパティでtabBarHiddenというのを使えば良さそうです。

var win1 = Ti.UI.createWindow({
     url: "first.js",
     tabBarHidden: true
});

しかし、これでエラーは出ないんですが、最初の画面で謎の灰色のバーが出てきました。

ただ問題は残っていて、Androidの方でtabBarHiddenが動作せず、タブが1つ表示されてしまって微妙です。なんとかならないのと調べてみると、公式フォーラムに解答がありました。
まず(app-project-dir)/platform/android/res/layout/というディレクトリを作成して、その中にtitanium_tabgroup.xmlというファイル名で下記を追加すればタブバーを消す事ができます。
http://taichino.com/programming/javascript-programming/titanium/3568

なんだかなぁ。
Androidのこと嫌いなんじゃないかって思うくらい面倒なことさせるよね、Titaniumって。

とりあえず言われた通りにxmlファイルを入れるとタブバーが消えてすっきりしました。よかったよかった。

(追記)
ほかにもダミーウィンドウを使う回避の仕方もあるようです。
AndroidでのTabGroupはTabBarが消せないなどの問題もあって使い勝手がよくありません。(中略)かなり汚い実装になりますが,Tiatnium側で改善されるまでは仕方がなさそうです。
http://gihyo.jp/dev/serial/01/titanium/0014



○口ではヤバいと言ってるものの

画面遷移をしっかり決めたせいで、Ti.App.を使った変数を入れた途端エラーが出たりして、バグ取ってたらやる気が底をついちゃいました。

結局なんでうまくいったかは分からずじまいで、今日はそのままふて寝することに。
あぁ…明日はテーブルビューの実装だ…。

2012年12月3日月曜日

[Titanium奮闘記5日目]2回に1度出るエラーが治りました! #TitaniumJP


○いろんな人を巻き込みながら

プログラムって本当にちょっとのミスで全く動かなくなりますね(´・ω・`)
以下いろいろつまづいたところをつらつらと。

・Androidで「Application installed. Launch from drawer on Home Screen」と出るのに、実機ではインストールされていない or 違う名前でインストールされる

これはtiapp.xmlの設定をいつの間にかいじっていたのが原因でした。
<ti:app xmlns:ti="http://ti.appcelerator.org">内の<id>や<name>を確認してみてください。
これがいつの間にか(多分ファイル移動時にミスって)違う名前になっていたため、いくら書き出しても違う名前でインストールされていたようです。

・「'undefined' is not an object (evaluating '変数名')」が出る。

for文を回してるときに起こったエラーです。原因は単純で、回し過ぎでした(´・ω・`)
要は、入れた変数が「undefined」だからここにそれ入れたらダメ!というエラーなので、変数かループ条件をチェックしてみましょう。

・グローバル変数的なものを使いたい。

JSだと関数内で定義した変数は関数外で使えませんよね?
まずそこら辺が分かっていなかったんですが、Titaniumでは「Ti.App.メソッド又はプロパティ名」でどこからでも使えるようになるみたいです。

ただ、アプリの終了までメモリを使い続けるし、グローバル変数だからこそ複雑なバグが生まれる場合もあるので、何でも使えばいいってモンじゃないみたいです。

…え、僕ですか? チキンなので外部定義にしましたがなにか?

・JSSに関するいろいろなこと

後輩の「JSSは使うな」の一言ですべてが解決しました。



○2回に1度出るバグの直しかた

前回のポストで「そんなファイルねーだろコラ」と言ってましたね。

[ERROR] Error: Traceback (most recent call last):  File "/Users/(ユーザー名)/Library/Application Support/Titanium/mobilesdk/osx/2.1.3.GA/iphone/builder.py", line 1341, in main    cleanup_app_logfiles(ti, log_id, iphone_version)  File "/Users/(ユーザー名)/Library/Application Support/Titanium/mobilesdk/osx/2.1.3.GA/iphone/builder.py", line 503, in cleanup_app_logfiles    os.remove(i)OSError: [Errno 2] No such file or directory: 'bad path 4ACC2000-0000-0000-0000-006B00000000'
中略
あれ、でもbuilder.pyがないんですが…(´・ω・`)


よくよく考えてみると、「Liberary」フォルダが見つからず、そこから以下の階層に行けなかったので諦めただけでした。
んで、見つからないのはないのではなく、見えていなかったみたいです。隠しフォルダですね。

Macは、ドットファイルが隠しファイルになります。「.bash_profile」とか。隠しファイルは、Finderに表示されません。Windowsのエクスプローラだと、隠しファイルを表示するオプションがあります。しかし、Macには見えるところに設定がないようです。
http://d.hatena.ne.jp/shunsuk/20090714/1247567640


自分はターミナルから打ち込んで非表示を消しました。
あとは前回の記事でも掲載したこの方法でエラーが出なくなります。

上記エラーメッセージ中に出てくる builder.py を変更したら直った。パス中の空白をバックスラッシュでエスケープする。 
変更前
simulator_dir = os.path.expanduser('~/Library/Application Support/iPhone Simulator/%s' % iphone_version)
変更後
simulator_dir = os.path.expanduser('~/Library/Application\ Support/iPhone\ Simulator/%s' % iphone_version) 
http://3.1415.jp/node/142



バージョンによって異なりますが、該当箇所はTitaniumのバージョン2.1.2だと467行目にありました。
コマンド+Fで「simulator_dir」を調べていった方が早いかもね。

あ、ちなみにXcodeでコードを変更させました。
Xcodeで行番号を表示するには「環境設定(preferences)→Text Editing」の「Show: Line numbers」にチェックをいれてください。

ついでにバックスラッシュの打ち方も覚えた。OS Lion & Xcodeでも「option(alt) + ¥」で打てましたよ。

あまり普通の人には関係のないバックスラッシュですが、たまーに必要な時があります。
ソフトウェアの環境にもよりますが、 optionキー(alt) + \ で、バックスラッシュになります。
http://mactips-lib.net/m/macosx/035.html



○明日の予定
・テーブル表示
・UIの見直し
・実際に使うデータベースを作る←全然進んでない

さて、今週はすることがいっぱいです…がんばろうっと><