Mac OS X wi-fi tips
Mac OSではネットワークの設定はLocationという単位で切り替えることができます。
terminalからは /usr/sbin/scselect コマンドで現在の設定を確認できます。
$ scselect xxxxxxxx-44F6-4EFE-BE5C-B5E0B91B7CDC (foo) * xxxxxxxx-1D83-4E30-A533-77C2CE1E59EA (Automatic) xxxxxxxx-FAE4-4D87-9014-D1012E0807A5 (bar)
scselectコマンドの後にLocation名を書くとその設定に切り替わります。
自分は頻繁に切り替えるのでエイリアスを設定しておきました。
$ echo 'ailas foo-net="scselect foo"' >> ~/.bashrc
またwi-fiの調子が悪い時はAirMacのON-OFFを繰り返すとたまに改善することがあるので、
これもエイリアスに登録しておきます。
AirMacの操作は /usr/sbin/networksetup コマンドを使うと可能です。
$ echo 'alias wifi="networksetup -setairportpower en0"' >> ~/.bashrc # en0はMacBookの場合です。 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $ wifi on # AirMac起動 $ wifi off # AirMac停止
【iOS】バックグラウンドでBluetoothのコネクションを維持する
iOSデバイスでのBluetooth通信は基本アプリが画面内に表示されている'フォアグラウンド'の時のみ有効です。
今回はアプリがバックグラウンドに隠れた間でも、Bluetooth通信を可能にする裏技的な(?)tipsを紹介します。
バックグラウンドで実行可能な処理
まずiOSでバックグラウンド実行が可能なものを見てみましょう。
iOSでは、バックグラウンドで行える処理が以下のものに限られています。
Apple iOS App Programming Guide
- 音楽の再生
- 位置情報の取得
- VoIP
- Newsstandを使用するアプリ
- 外部アクセサリから定期的に情報をアップデートするアプリ
このような、バックグラウンドでの動作が重要なサービスに限り許されています。
iOS Bluetoothフレームワークの種類
iOSが提供するBluetoothのフレームワークには大きく分けて2種類あります。
名称 | 使用可能なデバイス | バックグラウンド通信 |
---|---|---|
Game Kit | Bluetoothが使用可能なiPhone全て | × |
Core Bluetooth | iPhone4S以降 | ○ |
CoreBluetoothはBluetooth LE(Low Energy)に対応した外部機器との通信のみに使われます。
今回のターゲットはGame Kitフレームワークでのバックグラウンド通信です。
Bluetoothのコネクションを維持する方法
ではバックグラウンド通信を可能にするにはどうしたらいいのでしょうか。
実は、音楽をバックグラウンドで再生している間は、Bluetoothの通信が可能となっています。
以下、無音の音楽を永遠と再生し続けるサンプルコードです。
// オーディオデータフォーマットを表す構造体を作成 AudioStreamBasicDescription dummyASBD; dummyASBD.mSampleRate = 44100.0; dummyASBD.mFormatID = kAudioFormatLinearPCM; dummyASBD.mFormatFlags = kAudioFormatFlagsCanonical; dummyASBD.mBytesPerPacket = 4; dummyASBD.mFramesPerPacket = 1; dummyASBD.mBytesPerFrame = 4; dummyASBD.mChannelsPerFrame = 2; dummyASBD.mBitsPerChannel = 16; dummyASBD.mReserved = 0; OSStatus status; // AudioQueueの作成 status = AudioQueueNewOutput(&dummyASBD, dummyAudioQueueCallBack, self, NULL, NULL, 0, &dummyAudioQueue); if (status) { NSLog("error @AudioQueueNewOutput"); } // 再生 status = AudioQueueStart(dummyAudioQueue, NULL); if (status) { NSLog(@"error @AudioQueueStart"); }
実際にバックグラウンドで試すときは、アプリのinfo.plistのバックグラウンドモードの項目にAudio Playが設定されていることを確かめてください。
<key>UIBackgroundModes</key> <array> <string>audio</string> </array>
この状態であれば、GKSessionクラスのsendDataToAllPeers:withDataMode:error:
メソッドや、receiveData:fromPeer:inSession:context:
メソッドでデータの送受信が可能となっています。
最後に
もしかすると、音楽の再生以外にもバックグラウンド処理が許されているもの(例えばVoIPなど)でも同じことが可能かもしれません。
尚、この方法はAppleのガイドラインには書かれていないため、明らかに不推奨な方法だと思われます。
バックグラウンドで通信することに意義があるサービスのみに適応するよう心がけてください。
template engine embedded in underscore.js
クライアントサイドのテンプレートエンジンはjQueryのものが有名ですが、 今回はUnderscore.jsに備わっているミニマムなテンプレートエンジンの使い方を紹介します。 Underscore.jsは、クライアントMVCの代表格の1つであるBackbone.jsで採用されている便利ライブラリです。 (ちなみに両ライブラリの作者はCoffeeScriptを開発しているbraddunbarだったりします。)
この記事はUnderscore.js ver1.4.3を元に記載しています。
テンプレートの構文
Underscore.jsのテンプレートの区切り文字(delimiter)はデフォルトではERB-styleです。
区切り文字を変更するには、_.templateSettings
というオブジェクトの各プロパティ(evaluate
, interpolate
, escape
)を変更することで可能です。
- 評価
- コードをテンプレートの中で評価したい場合は、<% %>で括ります。
- 埋め込み
- 変数などを評価してHTMLに埋め込みたい場合、<%= %>で括ります。
- エスケープ
- HTML文字としてエスケープする場合は、<%- %>で括ります。
例)
// テンプレート実行前 <% for (var i = 0; i < 3; i++) { %> <p>Hello <%= i+1 %> Underscore!</p> <% } %> // テンプレート実行後 <p>Hello 1 Underscore!</p> <p>Hello 2 Underscore!</p> <p>Hello 3 Underscore!</p>
HTML内での使い方
実際にテンプレートを使用してみましょう。
HTML内にインラインでテンプレートを記述する場合は<script>
タグを使用し、HTMLとして画面に出力されないようにします。
そしてテンプレートの部分を文字列として取得し、それを_.template()
関数に入れ、テンプレートをプリコンパイルします。
プリコンパイルした結果は関数となっており、その関数を実行することで最終的なHTML文字列が得られます。
また、プリコンパイルした関数は引数としてオブジェクトを渡すことができ、テンプレート内ではそのプロパティ名でアクセス可能です。
元HTMLコード
<html> <head> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script> <script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.3/underscore-min.js"></script> </head> <body> <div id="target"></div> <!-- テンプレート --> <script type="text/html" id="target_template"> <% for (var i = 0; i < 3; i++) { %> <p>Hello <%= foo %>! <%= bar %>!</p> <% } %> </script> <script> // テンプレートを文字列として取得 var $templateString = $('#target_template').html(); // テンプレートをコンパイルし、テンプレート関数を得る var template = _.template($templateString); // テンプレート関数を実行 var html = template({ foo: 'foo', bar: 'bar' }); // $('#target').html(html); </script> </body> </html>
ブラウザで見るとJavaScriptが解釈され、このように表示されます。
Hello foo! bar! Hello foo! bar! Hello foo! bar!
Underscore.jsでのテンプレートの実装
使い方は非常に簡単でした。 さて、実装はどうなっているのでしょうか。 underscore.jsはコードサイズも小さくまとまっているため、実装を追いやすく、JavaScriptのコードリーディングにも最適です。
テンプレート部分のコードを転載します。
_.template = function(text, data, settings) { var render; settings = _.defaults({}, settings, _.templateSettings); // Combine delimiters into one regular expression via alternation. var matcher = new RegExp([ (settings.escape || noMatch).source, (settings.interpolate || noMatch).source, (settings.evaluate || noMatch).source ].join('|') + '|$', 'g'); // Compile the template source, escaping string literals appropriately. var index = 0; var source = "__p+='"; text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { source += text.slice(index, offset) .replace(escaper, function(match) { return '¥¥' + escapes[match]; }); if (escape) { source += "'+¥n((__t=(" + escape + "))==null?'':_.escape(__t))+¥n'"; } if (interpolate) { source += "'+¥n((__t=(" + interpolate + "))==null?'':__t)+¥n'"; } if (evaluate) { source += "';¥n" + evaluate + "¥n__p+='"; } index = offset + match.length; return match; }); source += "';¥n"; // If a variable is not specified, place data values in local scope. if (!settings.variable) source = 'with(obj||{}){¥n' + source + '}¥n'; source = "var __t,__p='',__j=Array.prototype.join," + "print=function(){__p+=__j.call(arguments,'');};¥n" + source + "return __p;¥n"; try { render = new Function(settings.variable || 'obj', '_', source); } catch (e) { e.source = source; throw e; } if (data) return render(data, _); var template = function(data) { return render.call(this, data, _); }; // Provide the compiled function source as a convenience for precompilation. template.source = 'function(' + (settings.variable || 'obj') + '){¥n' + source + '}'; return template; };
まず、matcher
という変数が定義されています。
このmatcher
はテンプレート構文に従った正規表現オブジェクトになっています。
そしてこの関数に渡されたテンプレート文字列text
を、text.replace
でテンプレート構文にマッチする箇所を探し出します。
replace
関数にfunctionを渡すと、マッチする箇所が見つかるたびにその関数が呼び出されます。ここでのreplace
関数の使い方は元のtext
を変更するのではなく、変数source
に文字列を付け足していく処理を行なっています。
replace
関数に渡されたfunction
の中は、
- escape(エスケープ)構文が見つかった場合
'+\n ( (__t=(foo) ) == null ? '' : _.escape(__t) )+\n'
- interpolate(埋め込み)構文が見つかった場合
'+\n ( (__t=(bar) ) == null ? '' : __t)+\n'
- evaluate(評価)構文が見つかった場合
';\n var i = 0; \n __p+='`
で場合分けされ、対応する文字列が変数source
に付け加えられます。
何をやっているのかよくわかりませんね。実際に実行した時の変数source
の中身を見てみましょう。
(Chromeのデバッガを使うと便利です。)
<% for (var i = 0; i < 3; i++) { %> <p>Hello <%= foo %></p> <% } %>
上記のようなテンプレート文字列があったとき、text.replace
を通過したあとの変数source
は以下のような文字列になっています。
source = "__p+='\n';for (var i = 0; i < 3; i++) { __p+='\n<p>Hello '+((__t=( foo ))==null?'':__t)+'!</p>\n';} __p+='\n';\n"
なにやら、__p
という変数に文字列を付け加えていく処理を表す文字列のようです。
最終的にこのsource
は、Function
コンストラクタを介して関数オブジェクトへと変わります。以下、動的に作られた関数renderの内容です。
function render (obj, _) { var __t, __p = '', __j = Array.prototype.join, print = function () { __p += __j.call(arguments, ''); }; with (obj || {}) { __p+='\n '; for (var i = 0; i < 3; i++) { __p+='\n <p>Hello '+ ((__t=( foo ))==null?'':__t)+ '!</p> \n '; } __p+='\n '; } return __p; }
これでやっていることは明確になりました。
__p
はテンプレート関数の実行結果であるHTML文字列を表します。
またwith文で実行時のコンテキストがobj
になるため、引数で渡されたオブジェクトのプロパティにアクセスする際に、オブジェクト名をつけずに(obj.foo)、プロパティ名そのもの(foo)でアクセスできます。
(もしオブジェクト名を付けなければいけないとすると、必ず'obj'という固定の仮引数名をテンプレートの中で使わなくてはいけなく、柔軟性に欠けます。)
この_.template()
関数の最終的な返り値は、動的に作ったrender関数を呼ぶ関数になります。
var template = function(data) { return render.call(this, data, _); }; return template;
まとめ
Underscore.jsのテンプレートエンジンの使い方と実装を見てみました。
Backbone.jsと対に使われるUnderscore.jsですが、単体で見てもこのテンプレート機能以外にも面白い(特に関数型言語のような)関数が豊富に用意されているので、皆さんも是非使って、そして実装を追ってみてください。
iPod共有アプリ「 Listen with」リリース!
新しいiPhoneアプリ「Listen with」をリリースしました!
このアプリは自分のiPhoneに入っている曲を他の人のiPhone上でも、
同時に・一緒に 聴くことができるアプリです。
Bluetoothを使ってiPhoneの曲をもう一方のiPhoneにストリーミングするため、
地下鉄などの電波のない環境でも使用できます。
アプリのデザインに関しては、このアプリのデザイナーである@Haeyoung_SさんのHPで見ることができます。
http://vividviolethy.wordpress.com/
次回から、このアプリを作る上で技術的に困難だったことを紹介したいと思います。
具体的には、
といったあたりです。
是非お友達と一緒に使ってみてください!
Listen withはApp Storeから無料でダウンロードできます。
Phrase Mania - ver2.0.0をリリース
iPhoneアプリ「Phrase Mania」を先日ver2.0.0にアップデートしました。
以前から「耳コピをしやすくしてほしい」という意見がありましたので、ver2.0.0の新機能として「耳コピモード」という新しいモードを追加しました。
耳コピモードでは
1. リピート区間を設定してその部分を繰り返し再生したり
2. 特定の秒数(1秒〜15秒)、もしくは設定したリピートの先頭場所に瞬時に巻き戻したりすることができます。
もちろん速度調節も組み合わせて使えますので、原曲の半分のテンポで同じ箇所を繰り返し再生したり、なんてことが可能です。
耳コピモードは、再生画面上部の「PHRASE・SONG・COPY」という文字をタップすることで切り替えられます。是非使ってみてください。
次のバージョンに向けてご要望などございましたら、お気軽にコメント欄からどうぞ!
Xcode4.2 β版からXcode4.0.2に戻した時に起きるCode Sign Error対処法
アプリのアップデート版が完成したので、App Store用にアプリをアーカイブしようとするとこのような警告が出て一向に進みませんでした。
Application failed codesign verification. The signature was invalid, or it was not signed with an Apple submission certificate. (-19011)
このエラーが出た原因として考えられることは、
・Release用のProvisioning ProfileがDistributionになっていない
・Distribution用の証明書を取得していない
・上2つの有効期限が切れている
など、証明書やProvisioning Profile周りの原因が多いのですが、今回はその全てにも当てはまりません。
まさかXcode4.2からXcode4.0.2に戻したことに何か原因があるのかと思っていたら、まさしくその通りでした。
調べたところ、
Xcode4.2をAppleが薦めているアンインストール方法(ターミナルからアンインストールのスクリプトを実行する方法)でアンインストールすると、Developerディレクトリはそのまま残ってしまいます。そこにXcode4.0.2を新たに入れると、なんとXcode4.0.2を使っているのにもかかわらず、その中で一部のXcode4.2のツールを参照し続けてしまうみたいです。
解決方法としては、ターミナルで
mv /Developer /Developer.old
として、Developerディレクトリを別に移しておいてから、新たにXcode4.0.2をインストールし直すとうまくいきました。