Dropbox

Mac OS XはGUIアプリケーションが洗練されていることのみならず、shell script、PythonそれにPerlがそのまま使える事が一部のユーザーにとっては意義のあることになっています。

ターミナル上で簡単に実行出来るスクリプトも便利なものです。常用するスクリプトはパスを通したりaliasで簡単に起動させることで実用になります。しかしながら、場合によってはGUIは無くても良いけどアイコンをクリックして起動させたいと思うこともあります。

スクリプトの.app化については既に多くの情報が出回っていますが、アイコンの作成まで含めると複数の情報を組みあせなければなりませんでした。また、私の目的であるperlスクリプトの実行後に画面を残して置くためには一工夫が必要でした。というわけで、自分への覚え書きにするとともに新たな.app化サンブルの提供を行うことにしました。

細かい説明は省いて、ガシガシとサンプルの作成を行なって行きます。

[ アプリケーション・バンドルの作成 ]
参考webページ: 技術/MacOSX/シェルスクリプトを”.app”(“Bundle”)化する

ターミナルを開いて適当な作業場所に移動します。

mkdir WhatDate.app
cd WhatDate.app
mkdir Contents
cd Contents
mkdir MacOS
mkdir Resources

WhatDate.app/Contents/MacOS/WhatDate.pl を以下の内容で作成。またchmod +xで実行属性も付けておく。

#!/usr/bin/perl
system("date");
print "EPOCH: ", time, "¥n";
@localtime = localtime;
print "JULIAN: $localtime[7]¥n";

コマンドラインから実行してみて動作を確認。

WhatDate.app/Contents/MacOS/WhatDate.bash を以下の内容で作成。これも同様にchmod +xで実行属性を付ける。

#!/bin/bash
BASEDIR=$(dirname $0)
open -a Terminal "${BASEDIR}/WhatDate.pl"

コマンドラインから実行してみる。今度は別のウインドウが開いて先のPerlスクリプトが実行されます。

WhatDate.app/Contents/Info.plist を以下の内容で作成します。これがアプリケーションの詳細を記述した重要なファイルです。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>WhatDate.bash</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleSignature</key>
<string>????</string>
</dict>
</plist>

もうこれでアプリケーション・バンドルとしては成立しています。アイコンをクリックして起動できるかどうか確認してみましょう。

[ アイコンの作成 ]

インターネットで調べるとIcon Composerを使うべしという情報が沢山見つかりますが、今時は iconutil というコマンドライン・ツールを使用します。

参考リンク: MacアプリのRetina対応アイコン(*.icns)を作成する方法

まずはアイコン画像をでっち上げますが、解像度に応じて沢山作らないといけません。ガイドによると全て作らなくても良いと書いてありますが、どれを作っておけば良いかは書いてないので今回は全部用意することにします。

まずは適当な場所にフォルダー作ります。
mkdir WhatDate.iconset

その下に以下の画像ファイルを作成します。
icon_16x16.png
icon_16x16@2x.png
icon_32x32.png
icon_32x32@2x.png
icon_128x128.png
icon_128x128@2x.png
icon_256x256.png
icon_256x256@2x.png
icon_512x512.png
icon_512x512@2x.png

WhatDateIcons

ファイル名の512×512は想像通り画素数です。後ろに@2xが付いている場合は倍の画素数になります。すなわちicon_512x512@2x.pngは1024×1024の画像ファイルを作成します。icon_16x16@2x.pngとicon_32x32.pngは同じ画素数ですが、あくまでもicon_16x16.pngの高解像度版です。場合によっては解像度によって違うデザインを使うこともあります。その場合、icon_16x16@2x.pngはicon_16x16.pngと同じデザインを使用するということです。

以下のコマンドを実行するとWhatDate.icnsが出来上がります。
iconutil -c icns WhatDate.iconset

出来上がった WhatDate.iconset を WhatDate.app/Contents/Resources/ 下にコピーする。

WhatDate.app/Contents/Info.plistに以下の2行を適当な場所に追加する。
<key>CFBundleIconFile</key>
<string>WhatDate.icns</string>

改めてWhatDate.app/Contents/Info.plistを全部書き出すとこんな具合です。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>WhatDate.bash</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleIconFile</key>
<string>WhatDate.icns</string>
<key>CFBundleSignature</key>
<string>????</string>
</dict>
</plist>

これで完成です。実際のアイコンは直ぐには表示されないかも知れません。

[ 配布 ]

これを配布する場合はディスクイメージにするのが簡単です。

まず適当なところにフォルダを作ります。フォルダ名は分かりやすくアプリケーション名と同じにしたりします。その中に、作成したアプリケーション・バンドルをコピー。必要に応じてReadme.txtみたいな説明も入れておきます。

ディスクユーティリティを起動。
「ファイル/新規/フォルダからのディスクイメージ」を選択します。
ファイル・ダイアログが表示されるので先に作ったフォルダを指定すれば配布用のディスクイメージが出来上がります。
配布先ではWhatDate.dmgをダブルクリックして開いた中にWhatDataアプリケーションが見えますので、適当なところにコピーして使用します。

参考までに、 作成したWhatData.dmgをサンブルとして置いておきます。

Adobeからソースコード用のフォントSource Code Proが公開されています。Iやl, Oと0などが視認しやすくなっています。

Mac OS Xでは/Library/Fontsにファイルファイルを入れておけば良いようです。

CotEditorで早速使用してみました。すっきりとして読みやすく、かなり良い感じです。

Perlのデバッガー

前のエントリーと関連した話題です。Perlにもいつの間にかデバッガーが搭載されていました。ほぼpythonのものと同等の機能を持っていますが微妙にコマンドが違います。ということで、覚書エントリーです。

起動は、

perl -d hoge.pl

などとします。

コマンドは、

ブレークポイント設定
 b 100
行番号100にブレークポイントが設定される
ブレークポイント
 L
ブレークポイントが設定されていれば、その一覧が表示される
ブレークポイントの解除
 B 100
行番号100のブレークポイントが解除される。番号の代わりに * を指定すると全てのブレークポイントを解除できる
実行
 c
ブレークポイントに遭遇するまで実行する
ステップ動作
 s
一行だけ実行してデバッガーに戻ります。サブルーチンの内部に入り込んでステップ動作します
ステップ動作
 n
一行だけ実行してデバッガーに戻ります。サブルーチンに遭遇しても次の行に進みます
変数の表示
 p $hoge
hoge変数の内容が表示される

pythonのデバッガー

今時のpythonにはデバッガーが内蔵されているためブレークポイントを設定したりステップ動作を行いつつ変数の中身を調べるなどということを簡単に行うことが出来ます。たまにしか使わないためすぐコマンドを忘れてしまう自分のために覚書としてエントリーしておきます。

起動方法は簡単で

python -m pdb hoge.py

などとしてコマンドラインで起動します。同時にhoge.pyを行番号表示の出来るエディターで開いておくと分かりやすいです。

コマンドを自分で使う最低限のものだけ紹介します。

ブレークポイント設定
 b 100 
行番号100にブレークポイントが設定される
ブレークポイント
 b 
ブレークポイントが設定されていれば、その一覧が表示される
ブレークポイントの解除
 cl 1 
1番目のブレークポイントが解除される。番号を省略すると全てのブレークポイントを解除できる
実行
 c 
ブレークポイントに遭遇するまで実行する
ステップ動作
 s 
一行だけ実行してデバッガーに戻ります>/td>
変数の表示
 p hoge 
hoge変数の内容が表示される


この本にはデバッガーについての解説は無いと思いますが、私がpythonを始めるにあたって購入した唯一の書籍です。

SQLiteのエスケープ文字

SQLite3というサーバー要らずのDBエンジンはパーソナルにSQLを使用するのに手軽です。また、最近の多くのモバイル・デバイスの内部でも使用されています。

ということでMac OS X上でもiOSアプリ内(最近はCoreDataに移行中ですが)でも多用しています。単純な単語の場合は問題ありませんが特殊文字も含めてqueryする場合には文字のエスケープを行わなればなりません。iOSアプリの内部で多様な文字列のqueryを行う必要が出てきたために文字列のエスケープについてまとめてみました。

[ LIKE operatorの場合 ]
標準的なSQLで使用されるLIKEと同じです。ワイルドカードとして%(0個以上の任意の文字に一致)と_(任意の一文字に一致)が使用できます。そのため%_自身をマッチさせるためにはエスケープ文字の指定が必要です。 エスケープ文字の指定にはESCAPE節を使用します。

SELECT * FROM hoge WHERE key LIKE '% test^_case %' ESCAPE '^';

という具合に使用します。ESCAPEで指定した文字自体もエスケープ対象になります。

引用符の扱いはperlと同様です。
– シングルクォート ‘ で囲まれた文字列の中ではダブルクォート ” は自由に使用できる。
– ダブルクォート ” で囲まれた文字列の中ではシングルクォート ‘ は自由に使用できる。
– シングルクォートとダブルクォートが混在する場合には囲み文字自体でエスケープ出来る。

SELECT * FROM hoge WHERE key LIKE 'I''m reading the "SNOW WHITE"';

[ GLOB operatorの場合 ]
GLOBはSQLiteに特有なオペレーターです。正規表現的な表現を使用しLIKEより柔軟なパターンマッチングが行えます。またLIKEは大文字小文字の区別がありませんがGLOBでは大文字小文字を区別します。

ここではエスケープについてだけ書きます。エスケープしなければならない文字は [ ] * ? です。エスケープの方法は、それぞれを[]で囲みます。

SELECT * FROM hoge WHERE key GLOB 'How are you[?] *';

といった具合になります。'[Y/n]’のように[]自体が含まれる文字列のマッチングも同様です。

SELECT * FROM hoge WHERE key GLOB '[[]Y/n[]]';

引用符の扱いはLIKEと同じです。

Nokia 3030 (Asha 303) MIDP環境のバグ

KKJConvでエラーが発生するということで調べてみたところ、どうもMIDP実行環境側の問題のようです。

エラーが発生するのは次のようなコードです。

TextBox tb;
tb.delete(0, tb.size());

このコードはTextBoxの文字列を削除するためのものですが、TextBoxが空の時に左の写真のようにString Index Out Of Boundsというエラーが発生します。

deleteメソッドの第一パラメータはオフセット、第二パラメータは削除する文字列の長さです。

tb.size() が 0 の時の問題なので tb.delete(0, 0); のようにしてテストすると文字列が存在する時にはエラーは発生しません。言い換えるとTextBoxに文字列が存在しない時にdeleteを呼ぶとエラーするということです。一応、ドキュメントを確認しましたが呼び方には問題が無いように思えます。ましてやKKJConvの初期から存在するコードなので実績もおおいにあります。

回避策は簡単なので以下のようなコードに変更してKKJConvのエラーは回避出来ました。

if (0 < tb.size()) {
  tb.delete(0, tb.size());
}

Nokiaにバグではないの?と投げかけようと思いましたが、以前Forum Nokiaにあったバグレポートのシステムが見つかりません。もう一般開発者からのバグレポートは受け付けてないのかな?

Nokia 3030 (Asha 303) のMIDPについて

既にAyamadoriさんがブログ「書くことないです。」に最新のNokia Series 40 Touch and Type端末のMIDP開発環境について書かれています。

私はQWERTYキーボードを中心に分かったことを書いてみたいと思います。

キーボード素直です。ずっとS60 3rdからフルキーボードのキーコードには悩み続けてきました。E7に至っては訳がわからないというのが正直な感想でした。それから考えると物足りないくらいに素直な挙動です。

E90などと違うのはCtrl+Cなどでコントロール・コードでは無く”C”そのものが返ってくることです。ただしCtrlキーそのものがキーコードを発生してくれるのでMIDPのアプリケーション内で処理可能です。また、CtrlだけではなくSymや数字シフトなどもキーコードが出ています。CtrlもSymキーもMIDPのCanvasでは何も働きませんので、逆に自分の好きなように役割を与えられるとも言えます。

カーソル移動キーが無い。「書くことないです」でも触れられていますが、方向キー、所謂10字キーが無いデバイスです。その代わりに画面を上下左右にスワイプすることで対応するキーコードが得られます。また左右のメニュー・キーもありません。これも画面のタップで代用します。S60 5thのタッチデバイスで表示される、あまり使いたいとは思わないゲーム・キーなバーチャル・キーボードは無くなったようです。

QWERTYキーで文字入力中に編集のためにスワイプというのは今ひとつな気もします。KKJConvではやはりキーボード操作でカーソルを移動できるようにしたいと思います。

液晶にタッチすれば何とか今までと同様の動作が出来ると思いきやダメなケースも見つかりました。Google Mapsは未だMIDP版が配布されていますが、これが全く操作不能でした。Google Mapsは画面を大きく使うためにCanvasをフルスクリーンで動作させています。検証はしていませんが、どうもこれが災いして画面のタッチが全く効きません。10キーだけは反応するですが、起動時に表示されたダイアログを消すことが出来なかったので、全く使い物になりませんでした。

Dropbox APIが新しくなったというニュースを見かけて、とあるアプリケーションに使ってみようと重い腰を上げテストしてみました。

iOS v1.0にはドキュメントが用意されていません。SDKに添付されているサンプル・プロジェクトが動くことを確認した後はtutorialに従って基本的に動作確認です。ところがファイルをアップロードしようとしたらupLoadFileがdeprecatedであると言われてしまいました。

ChagelogやDBRestClient.hを読めば事情は把握できるので良しとしましょう。せっかくのtutorialなので最新のAPIに変更しておいて欲しいものです。

新しいupLoadFileは、

- (void)uploadFile:(NSString *)filename toPath:(NSString *)path withParentRev:(NSString *)parentRev
    fromPath:(NSString *)sourcePath;

という形式です。parentRevと言うパラメータが増えています。ここにnilを指定してアップロードすることも出来ます。その場合、同じファイル名がサーバー上に存在する場合上書きをせずファイル名の後に(1)などと付加されて新しいファイルとして保管されます。現行ファイルを上書きする場合はloadMetadataにて現在のファイルのrevを取得しなければなりません。

ものすごく単純なコード例を書いておきます。
前提としてdocDirはアプリのDocumentフォルダーを指し、そこにファイルtest.txtが存在するものとします。またTutorial通りの手順でrestClientは初期化されているものとします。

- (void)uploadFile1
{
    [[self restClient] loadMetadata:@"/test.txt"];
}

-(void)uploadFile2:(DBMetadata*)meta
{
    NSString *testfile = [docDir stringByAppendingPathComponent:@"test.txt"];
    [[self restClient] uploadFile:@"test.txt" toPath:@"/" withParentRev:meta.rev fromPath:testfile];
}

// DBRestCleintDelegte
- (void)restClient:(DBRestClient*)client loadedMetadata:(DBMetadata*)metadata
{
    [self uploadFile2:metadata];
}

- (void)restClient:(DBRestClient*)client loadMetadataFailedWithError:(NSError*)error
{
    [self uploadFile2:nil];
}

revは元々、古いバージョンのファイルをリストアしたりするためのものと思います。詳しくは考えていませんが(ぉぃ、とりあえず動いてはいるようです。

iTunes ConnectでInvalid Binaryになった

久しぶりにiOSアプリケーションを更新しサブミットしたらInvalid Binaryになってしまいました。Xcode 4.2のArchiveからValidationは問題なし。Xcode4.2上ではSubmitも問題なしですがiTunes Connectを見るとInvalid Binaryと表示されていました。以前ですと問題があると何かしらエラーの理由が記されたメールが送られてくるのですが、それもありません。

まったく、手がかりの無いところから原因を探らねばなりません。Googolで検索すると、同様の現象について沢山の事例が見つかりました。ひとつひとつ検証した結果Info.plistでのアイコン指定の問題でした。

前提としてはiOS Deployment Targetが3.0なUniversal Applicationです。

最初は、

CFBundleIconFile icon.png
CFBundleIconFiles
  Item 0 icon.png
  Item 1 icon@x2.png
  Item 2 icon-72.png

みたいな感じでした。これで以前は問題なかったと思います。

ここに下のアイテムを追加してInvalid Binaryが解消しました。

CFBundleIconFile~ipad icon-72.png

本来ならXcodeのValidationでエラーを見つけてくれるべきなんでしょうね。試しにCFBundleIconFileにファイル名を消してみるとValidationの際にかなり詳しいエラーメッセージが出ました。

E7-00 MIDP環境のqwertyは、やはりヘン

Nokia E7-00のKKJConv対応で、どうやっても解決出来無い部分が残ってしまいました(これはN97miniやN97から同じかも知れないです)。E7-00に搭載されているQWERTYキーボードがMIDPアプリケーションからどのように見えるかという問題です。

[ 改行キーでキーコードが発生しない ]

改行キーが何も役割を与えられていない訳ではありません。通常のMIDPアプリケーションで改行キーを押すと左側ソフトキーに対応するメニューが開くようになっています。タッチデバイスということで何かしらの配慮から、こうなったのかも知れませんがQWERTYキーボードとして使用する上では、かなり不自然で不便です。メニューの存在しない(正確にはリスナーを登録しない)テストプログラムも試してみましたが、やはりkeyPressed(int)やkeyReleased(int)でキーコードを得ることは出来ませんでした。

CtrlキーがあるE7-00ではCtrl+jで改行キーを代用出来るのですが、ここにも落とし穴(後述します)あるので’@’キーを改行キーの代用として割り当てています。

[ シフトモードが分からない ]

通常のシフト、数字記号用のシフト、あるいはSymキーを押すと通常の画面ではシフトモードが画面上部に表示されます。ところがMIDPでは、非フルスクリーンな表示でもシフトモードが表示されません。シフトモードは通常と同じく、一回押すとシフト、2回押すとシフトロックという動作なので、それを自分で把握して入力しなければ行けません。

E90やE63もMIDPではシフト状態の表示はありません。しかしながらシフトを押しても次に入力される英字には影響されず常に小文字が入力されました。つまりアプリケーションにシフト状態の管理が任されていました。それ故、何の表示もないことが正しかった訳です。またE63では数字記号モードはMIDPに入る前に効いていますが、それだけを使用者が自己管理すれば良かったので然程混乱することはありません。

[ 数字記号シフト、Symキーもシフトキーと同じキーコードが発生する ]

どれもシフトの仲間だからということでシフトキーと同じキーコードを割り当てたのかも知れませんが、それが役に立つ場面が思いあたりません。E90やE63では数字記号シフトは何もキーコードを発生しませんでした。それ故にシフト状態をアプリケーション内部で管理するということが容易に出来ていました。

KKJConvとしては、いっそのことシフト表示を止めてしまうかと思いましたが、今のところはシフト表示に合わせて大文字、小文字の相互変換を行っています。ロジックの都合によりシフトを押したままで英字入力が二文字目からは小文字に成ってしまいます。これも、致し方なしです。

[ Ctrl + 英字が効かない事がある ]

英字を入力する際、本体のシフトモードに応じてMIDPアプリケーションに渡されるキーコードが小文字だったり大文字だったりするのは構いません。ところが、Ctrlキーと英字キーを同時に押して発生させるコントロール・コードがシフトモードによって左右されています。シフトモードが大文字に成っている時にCtrl+Jが押されると、キーコードは’J’が発生してしまいます。E90, E63では常に期待どおりのコントロール・コードが発生します。特にE63では数字記号シフトにロックされていてもCtrl+jなら改行キーとして機能します。

Ctrlキーはもともと押下状態かどうかがMIDPアプリケーションでは感知出来ないのでKKJConv側では対処の方法がありません。

ps. 一縷の望みを託してForum Nokiaにてバグレポートいたしました。直ると良いなぁ。