DraftPad 開発者への 16,820 文字インタビュー
■今日は DraftPad の作者である上野さんに起こしいただき、DraftPad に込められた思想や開発時の苦労話などを伺っていきたいと思います。それでは上野さん、どうぞ。
□あ、どうも、上野です。よろしくお願いします。
■はい、それでは早速お話をお伺いしますが、まず、DraftPad のことをまだ知らない人のために、簡単に紹介をしていただけますか。
□はい。DraftPad は、iPhone、iPod Touch、iPad 用のノートパッドアプリです。特徴はとにかくシンプルなことです。標準のメモアプリもシンプルで洗練されたアプリだと思いますが、DraftPad はこれをさらに単純化して、メモを管理するという機能を排除して、とにかくただ書くだけに特化させています。だから起動するといきなり UITextView が FirstResponder 状態で表示されます。見た目にも余計な罫線とか背景色などは排除して、プレーンな一枚の紙のような感じになっています。
■なるほど。でも UINavigationBar はありますよね。プレーンにということであればこれも取り去ってよかったのではないですか?
□もちろんそれも最初考えました。ただ何かしらのアクションボタンは必要だと思っていたので、それを置く場所が必要でした。iPhone ではスクリーン下部はキーボードが占有してしまいますから、置き場所は上しかない。どうせ上に置くなら Cocoa Touch の標準的な部品である UINavigationBar を使うのが美的安定性を確保するために最適であろうと判断しました。時々勝手にデザインしたUI部品で画面を埋め尽くしているアプリがありますが、ほぼ確実にダサいですからね。
■UINavigationBar といえば、DraftPad では単語数などを UINavigationBar に表示する機能がありますね。これも特徴のひとつだと思いますが。
□そのとおりです。Twitter クライアントでは文字数カウントを表示するものがほとんどだと思いますが、単語数や行数なども表示するアプリは珍しいと思います。
■なぜそのような機能を?
□その理由は、そもそも DraftPad を作った経緯に遡ります。以前私は「Modeless and Modal」という題名のブログを書いていたのですが、これはすべて iPhone で書いて更新していました。その時使っていた WordPress というアプリが、iPhone 3G でメモリーが少なかったということもあって、今ひとつ不安定だったんです。ある日そのアプリで3000文字ぐらい書いたところで iPhone に電話がかかってきて、その拍子にアプリがクラッシュして、書いたものが全部消えてしまったんです。それでものすごく頭にきて、何か文章の下書きのための、とにかくシンプルで安定した、たとえクラッシュしてもデータが消えないようなアプリを自分で作ってやろうと思ったんです。文章の下書き用だからファイリングやスタイリングの機能は一切不要。むしろそういうものを排除することでプログラムを単純化して安定性やレスポンスを高めようと考えました。
■なるほど、それで DraftPad という名前なんですね。
□今頃気付いたんですか。で、下書きという作業では、欧文なら単語数、日本語なら文字数を把握できることが重要ですし、行数も知りたい場合があります。これらはタイピングの際にリアルタイムに見えている必要があるので、UIViewController の Title として表示させるようにしました。
■データを失わないようにということでしたが、iPhone の標準のメモアプリをはじめ、テキストエディターを備えたアプリのほとんどはデータを自動保存してくれますよね。特別に保存コマンドを実行しなくても閉じれば勝手に保存してくれるのが普通だと思いますが、DraftPad はそれらと何か違うのですか?
□標準のメモアプリなどは、一覧表示に切り替えたりアプリを終了するタイミングでデータを内部ファイルもしくはDBに書き込みます。通常はそれで問題ないのですが、文章の編集中に何らかの理由でアプリがクラッシュした場合、その保存処理が実行されずに、データロスすることになります。DraftPad も基本的には同じなのですが、できるだけデータを失わないように、背後で1分おきに自動保存をかけています。ですからもしクラッシュしたとしても、失うのは最大でも1分間分の作業だけですみます。
■ほう。それはいいですね。でも1分間分の作業は失われる可能性があるんですよね。例えば自動保存を1秒おきぐらいに実行するようにすればもっと安心になるのではないですか?
□確かにもっと頻繁に自動保存を行えば、例えば1文字打つたびに保存すれば、データロスをほとんど無くすことができます。けれど保存処理にはそれなりに CPU パワーや一時的なメモリー負荷がかかりますから、あまりに頻繁に実行するとレスポンスの問題やバッテリー消費の問題、そして安定性の問題が生じるので、本末転倒なのです。
■では、ユーザーが自動保存のタイミングを任意に設定できるようにしたらどうでしょうか。
□それは素人の考えです。そういった実装モデルに依存したパラメーターの設定をユーザーに行わせるのは悪いデザインです。ユーザーにはその設定の意味や影響範囲が分からないですし、そのためにUI要素が増えてアプリ全体のシンプルさが損なわれてしまいます。そういうユーザーに見えない部分の調整は開発者がガッツをもって決め打ちしてやるべきなんです。
■なるほど、勉強になります。それで、ご自身のブログ執筆のためにまず開発されたというわけですね。
□そうです。最初のバージョン、というか自分用のプロトタイプは、3時間ぐらいで作りました。その段階では文字数カウンターやクリア機能などは無く、ただ UITextView と自動保存機能があるだけの状態でした。それを使ってブログを書いて、我ながらこれは役立つと思いました。何か便利な機能があるというのではなく、余計なものが何も無いということが重要でした。で、しばらく使っていたのですが、ブログの方が完結してしまい、DraftPad のプロトタイプは役目を終えてしまいました。でもせっかく作ったのだから、もう少しブラッシュアップさせて、App Store で公開したらどうだろうと思いました。自分と同じように、iPhone における文字入力作業にストレスを感じている人が他にもきっといるに違いないと思ったわけです。iPhone では、そもそもタッチパネルのソフトウェアキーボードであることとスクリーン自体が小さいことに加え、アプリによって不安定だったり重かったり、あるいは入力欄がとても小さかったりしますからね。だから DraftPad のようなミニマルで単機能のアプリを併用することでかえってひとつの作業、例えばブログを書いて更新するといったことがスムーズになるのではないかと思ったのです。
■なるほど。それで多少の機能追加などをして公開したわけですね。
□ええ、そうなんですけど、公開するためにはそれなりに細かい部分をきちんと作り込まないといけませんから、思った以上に大変な作業になりました。アプリアイコンなんかも作らなければいけないですし。
■プロトタイプの段階ではアプリアイコンも無かったんですね。
□ええ、最初はただの真っ白な四角でした。
■具体的には、どのような点が難しかったのでしょうか。
□はい。まず、アプリにどのような機能を盛り込むのかを検討しなおすところからはじめました。アプリのコンセプトは「下書のための一枚の紙」と決めていましたが、いざ機能を考え出すと、色々なアイデアがでてきてしまいます。例えば、Twitter に直接投稿できたら便利なんじゃないかとか、タイムスタンプが自動的に挿入されたら嬉しいんじゃないかとか、そういうことです。ただ私のインタラクションデザインの哲学として、アプリケーションはミニマルな機能セットを提供するだけで、ユーザーのタスクを限定するべきではないという考えがありますから、特に DraftPad のようなシンプルなアプリでは、すべてのUI要素や機能性がバランスよく意味を持っているべきだと思い直しました。無駄なものがひとつも無く、足りない部分は自分なりの工夫で補えるような状態を目指すべきだと。そこで基本のコンセプトに立ち返り、下書き作業をする上で最低限必要な機能は何かということを考えました。
■ほう。
□下書き作業に必要なのは、まずできるだけプレーンな UITextView です。それから、書いたテキストを他のアプリに移動する手段です。移動できなければ下書きの意味が無いですからね。
■それはそうです。
□幸い、ターゲットとした iPhone OS3 にはすでにコピーペースト機能がありましたから、ユーザーはこれでテキストを他のアプリに移動させることができます。ただ書いた文章全体を選択してコピーする操作は結構面倒ですから、「Copy All」という機能を付けました。また DraftPad は一枚の紙でありファイリングはできないので、書かれたものをすべて消すための「Clear」機能を付けました。このクリア機能については、間違ってクリアしてしまうリスクがありますから、アンドゥできるように undoManager へ登録する処理を自前で実装しました。それから、ネットワーク経由でデータを渡せるように、最も基本的かつ様々な用途に使えるメール作成機能を付けました。
■DraftPad(v1.1まで)のアクションメニューにはもうひとつ「Google」という機能がありますが?
□はい。「Google」機能についてはやや恣意的な、タスクを限定したものに感じられるかもしれません。でもこの機能は、単にインターネット検索を楽にするということ以上の意味がありました。というのは、ご存知のとおり、コンピュータの世界ではテキストデータというのは特別な存在です。それは自然言語で情報を記録するというだけでなく、情報処理の基本的なプロトコルになっているわけです。例えば、プログラミングをするのにもテキストを使いますし、ファイル名や URL といった識別子にも使います。Google というのはユーザーが入力したテキストを解釈して何か別の有意義な情報に変換してくれるというエージェントあるいはコンシェルジュとしての象徴ですから、DraftPad で入力したテキストをそこに簡単に渡すことができれば、使い方次第で用途が無限に広がるだろうと思ったのです。簡単な例で言えば、DraftPad で「1+1」とタイプしてアクションメニューから「Google」を実行すれば、Google は「1+1=2」という情報を返してくれます。このように、私はデジタルデバイスにおける「下書き」というものを、単なる文章の下書きとしてだけではなく、情報処理のトリガーとして捉えたかったのです。DraftPad には本当に厳選した最小限の機能しか持たせたくありませんでしたが、同時に、そのポテンシャルには無限の広がりを持たせたかったのです。
■うーむ、そうだったのですね。では、他に苦労された点はどんなところでしょう。例えばプログラムの実装で難しかったことなど。
□私はプログラマーではないですから、苦労はいろいろあります。ただバージョン1.0を作った段階で難しかったのは、単語数のカウンターぐらいでしょうか。UITextView クラスには、文字数を返してくれるメソッドはあるのですが、単語数を返してくれるものはありませんから、自前で数えなければいけません。そこで、どうすれば欧文の単語数をカウントできるか考えました。例えば、単語の区切りであるスペースや改行文字を検索してその数を数えるだけでは、連続したスペースや改行があった場合に正しくカウントできません。またピリオドやカンマといった文字が単語の区切りになる場合もあります。正規表現を用いればこれらを一括で特定のデリミターに置換することができるかもしれませんが、そのためには別途特別なフレームワークを読み込まなければなりませんでした。プログラムを軽くするためにそれは避けたかったので、結局、文字列を一定の条件で配列化するメソッドを使って、その要素数を数えることで、できるだけ正確に単語数をカウントできるようにしました。
■なるほど、色々と難しいのですね。
□そうですね、でもこの話には続きがあります。バージョン1.1では、1.0で実現できなかった細かな部分の実装を行おうとしました。そのうちのひとつが、単語数カウンターのレスポンス改善でした。文字数や単語数のカウント処理は、ユーザーがテキストに何らかの変更を加える度に実行します。例えば1文字打つ毎に文字や単語を数え直すのです。そうしないとリアルタイムに表示できませんから。しかしこの処理は毎回テキスト全体を変数にコピーして舐めるので、テキストの文字数が多くなると処理に時間がかかります。特に単語数や1.1で追加した行数のカウントは処理が複雑なので、高速でタイプされると処理が追いつかず、文字入力のレスポンスが悪くなってしまいます。この問題を解決するために、テキストが変更される度に、つまり1文字打つ毎にスレッドを生成して並列処理させることにしました。そうすればユーザーの入力操作とは非同期でカウント処理できますので。ところが、スレッドの生成はうまくいったのですが、カウントした結果を UINavigationBar に表示するところで問題が起きました。並列処理で計算された単語数などの文字列、例えば「Words: 10,872」といった文字列表示の命令が短時間に集中すると、表示処理が追いつかず、文字がうまく表示されないという不具合が起きたのです。UIViewController の Title は、よく見ると分かりますが、白い文字の下に黒い文字が1ピクセルずれて敷かれています。これによって文字にエンボスがかかって見えるわけですが、この表示処理がうまくいかず、ただの黒い文字になってしまったりするのです。この問題を解決するのにかなり時間がかかりました。結局、スレッドで算出した結果をもう一度メインスレッド上の変数に戻し、その状態をオブザーブすることで同期処理として Title の文字列更新を行うという方法を取りました。同期処理が入ることで、文字入力のレスポンスに多少の影響を与えてしまいますが、処理が重なったスレッドはキャンセルされるようにしてあるので、更新の回数自体が減り、バージョン1.0に比べれば軽くなりました。そのかわりメモリーは沢山使うようになりましたが。
■ええと、何だかよく分からなくなってきましたが、単語数表示のために大変苦労をされたということですね。
□そうです。しかしバージョン1.1でのチャレンジはそれだけではありません。もうひとつ難しかったのが、カーソル位置の復帰です。
■といいますと?
□バージョン1.0の時は、ユーザーがテキストを編集中に、つまりキーボードが表示されている時にアプリを終了すると、次に起動した時には、キーボードが引っ込んだ状態になっていました。標準のメモアプリもそうなのですが、それだとすぐに書きはじめられませんし、スクロール位置が毎回先頭に戻ってしまうので、最後尾に追加入力をしたい場合にはいちいち一番下までスクロールしなければいけません。理想は、前回終了した時のカーソル位置やスクロール位置を自動的に再現して、すぐに前回の続きを入力できるようにすることです。
■ということは、終了時にそれらのポジションを記録しておくということですね。
□そのとおりです。でもそれだけなら簡単なことです。問題は、アプリの起動時にそれらを再現する方法です。
■UITextView のプロパティにそれらをセットすればよいのではないのですか?
□実はそれだけだとうまくいかないんです。確かに UITextView クラスにはスクロールポジションやカーソル位置を指定できるプロパティがあります。けれど例えばアプリの起動直後に UITextView のインスタンスに becomeFirstResponder メッセージを投げて、それから selectedRange プロパティを更新しても、その直後にフレームワーク側で値が上書きされてしまい、カーソル位置は強制的にテキストの最後尾にいってしまうのです。ですからその強制的な処理を検知してその後で selectedRange を書き換えてやらないといけません。で、そのような UITextView の勝手な振る舞いのタイミングが OS のバージョンやデバイスによって違っているのです。具体的には iPad なんですけど。
■そういえばバージョン1.1で iPad にも対応したんですよね。
□はい。iPad に対応させるためにユニバーサルアプリとしてコンパイルされるようにしたわけです。ですからひとつのソースで iPhone の OS3.1 と iPad の OS3.2 に対応させなければいけなせん。API の違いはあまり無かったのですが、UIコンポーネントの細かな振る舞い、つまりドキュメント化されていない部分で結構な違いがあるのです。各ビューのデリゲートメソッドは非同期で実行されますから、フレームワーク側が勝手にやっている処理を擬似的にオーバーライドするためにどこのデリゲートに引っ掛ければ良いのかを探るのが大変でした。
■iPad への対応で他に苦労した点はありますか?
□そうですねえ、見た目を iPad 風にするのはフレームワークが自動的にやってくれますので、特に大変なところはありません。けれど iPad 独特の機能やUIガイドラインに対応するためにいくつかやらなければならないことがありました。
■iPad 独特の機能とは例えば何でしょう。
□DraftPad に一番関係するところで言えば、外部キーボードのサポートですね。外部キーボードを使えるようにするということ自体はOSが勝手にやってくれるのですが、UIとして、入力可能状態であるのにソフトキーボードが非表示になっているという、iPhone では存在しない状況が生まれます。それまで、編集状態と閲覧状態の切り替えはそのままキーボードの表示非表示の切り替えと同義でしたが、これが別々に起こることになったので、例えば UITextView の高さの変更といった処理を少し書き直さなければなりませんでした。
■言われてみればそうですね。
□それから、iPad では新たに UIPopover という部品があり、これは iPad 独特のものです。アクションボタンを押した時に、iPhone ではスクリーン下部から UIActionSheet でメニューが出てきますが、これを iPad では UIPopover で表示するようにしました。iPad の UIガイドラインでは、UIPopover にはキャンセルボタンを置かずに外をタップすれば閉じるようにしろとありましたので、メニューの中身も iPhone と iPad で条件分岐させる必要がありました。ただその条件分岐の方法として、UIPopover クラスの有無を見るようにしたことで、後で問題が出る原因になってしまいました。その問題についてはまた後でお話するということで。
■はい。では他に iPad のUIガイドラインとして新しい事項はありましたか?
□iPad のガイドラインでは、iPhone と違い、すべてのアプリがポートレートモードとランドスケープモードの両方をサポートしなければならないとされています。DraftPad はもともと両者をサポートしていましたが、iPhone では仕組みとして起動時のローテーションをどちらかひとつに決めるようになっているのに対し、iPad では両方可能になっているので、それに対応しなければなりませんでした。
■よく分かりません。
□例えば iPhone では、横向きに持って DraftPad を起動すると、まずポートレートモードで表示されてからランドスケープにローテートします。一方 iPad では、横向きに持って起動したらはじめからランドスケープモードで表示されます。実際には、内部的にはポートレートで起動してビューが表示される前にこっそりローテートが起こっているのですが、ユーザーにはそれは意識されません。それで、ただランドスケープで表示させるだけなら特別な処理は必要ないのですが、バージョン1.1では、先ほどお話したとおり、編集状態での起動時にカーソルを前回位置に復帰させるためのハックがあり、これが内部的なこっそりローテーションで再度無効にされてしまうことが分かりました。ですからそのこっそりローテーションを検知してもう一回ハックしてやる必要がありました。もうイタチごっこですよ。
■へえー、見えないところで壮絶なせめぎ合いが起きているのですね。
□はい。実はこの起動時のカーソル位置復帰と同様にもうひとつ、起動時のスクロールポジション復帰という課題がありました。
■カーソル位置とスクロール位置は違うのですか?
□編集状態の時には両者はほぼ同義で、UITextView はカーソル位置を指定すると自動的にそこまでスクロールします。けれど閲覧状態の時には純粋にスクロールポジションを指定してやる必要があります。その時、単に記録してある前回終了時のポジションを指定するのはすぐできますが、問題は、iPad において、前回終了時のローテート状態と次に起動した時のローテート状態が異なる場合です。
■例えばポートレートモードで終了して、次にランドスケープモードで起動したような場合ですか?
□そうです。その場合、単にスクロールのY座標を記録して再現するだけだと、ローテートの違いによってスクロール位置がずれてしまうのです。ポートレートよりもランドスケープの方がスクリーンの幅が広いですよね。UITextView は常にスクリーンの幅いっぱいに広がっています。多量のテキストがある状態で、例えばポートレートモードで見ている時に、ちょうど1000文字目がスクリーンの中央に見えていたとします。そしてその時のスクロールY座標が500ptだったとします。その状態でランドスケープにローテートさせて、スクロールY座標を500ptのままにすると、幅が広がる分、1000文字目はもっと上の方に見えているはずです。このギャップは、テキストの末尾に行くほど大きくなります。前回のスクロールポジションを復帰させることの目的は、前回見ていた箇所のテキストが次回起動時にも見えているようにすることですから、単にスクロールY座標を復元するだけではこの目的が叶いません。これは起動時に前回終了時とローテートが異なる場合だけでなく、閲覧状態での通常のローテーションにも起こる問題です。例えば標準のメモアプリで試していただければ分かります。長文を閲覧状態で見ている時にローテートさせると、直前に見ていた箇所がスクリーンから大きくはずれてしまうはずです。
■本当ですね。
□ですからバージョン1.1では、これに対する補正処理を加え、できるだけローテート前に見ていた箇所がローテート後にも見えているようにしました。ただ精度がそれほど高くないので、まだチューニングの余地はありそうですが。で、この処理に若干不備があったことで、バージョン1.1.1という修正版をすぐに出したのです。
■そうだったのですか。いやあなんといいますか、DraftPad って単純なアプリだと思っていましたが、案外細かなところで手間がかかっているのですね。
□そうですね。でも本当はこんな話はするもんじゃないんですよね。別にこれぐらいのことは誰でもやっていることでしょうから。でもつい語りたくなってしまったんです。
■いやいやこちらからお聞きしてるわけですからもっと話してください。他に、バージョン1.1もしくは1.1.1で追加したことはありますか?
□もしかしたら誰も気づいていないかもしれないのですが、カウンターの動作を、閲覧状態と編集状態で変えています。例えば編集状態の時に、文字列が選択されていると、単語数、文字数、行数のカウンターはその選択範囲に対する値になります。また行数については、これ自体バージョン1.1で追加したものですが、編集状態では現在のカーソル位置のある行番号、文字列が選択されている場合にはその選択範囲を含む行の行番号が表示されるようになっています。閲覧状態では、テキスト全体の行数表示です。このような機能は、やはり原稿の下書きをする時に必要だろうという考えで追加しました。
■確かにそれは気づいていませんでした。
□地味な機能ですが、この一連のカウンターは、Apple 純正のワープロである Pages にもない、なかなかめずらしくもあり有用な機能だと思っています。カウンターがあるから DraftPad を使っているというユーザーも結構いるようです。
■ではこのへんで、いよいよ今回新たにリリースされたバージョン1.2についてお話を伺いたいと思います。
□来ましたね。
■今回のバージョン1.2はどのようなものなのでしょうか。
□これはもう、破壊的としか言えないものですね。
■はい?
□はっきり言って、iPhone 自体のポテンシャルを大きく広げてしまうような、革命的なキラーアプリですよ。
■iPhone 自体のポテンシャルと言いますと?
□DraftPad 1.2 を使えば、iPhone がもっとパワフルなツールになるということです。DraftPad というひとつのアプリの話では最早ないのです。DraftPad は、iPhone 全体の可能性を引き上げるのです。
■何やらすごそうですが、具体的にはどのような変更があるのでしょうか。
□バージョン1.2では、大きく2つの変更があります。ひとつ目は iOS4/iPhone4 への対応。そしてふたつ目はアシスト機能の追加です。
■ではまず iOS4/iPhone4 への対応についてお聞かせください。
□まず、 iOS4/iPhone4 への対応が遅れたために、既存ユーザーにはご迷惑をおかけしました。バージョン1.1.1が、iOS4 で正しく動かなかったのです。ですから既存ユーザーで iOS4 にアップグレードした方は、それまで使っていた DraftPad 1.1.1 が使えなくなってしまいました。
■iOS4 になって、正しく動かなくなったアプリは多いようですね。原因は何でしょうか。
□アプリの実装がうまくいっていれば、OSのバージョンアップにも耐えられるはずなんです。ただ、OSの次バージョンでフレームワークにどのような追加変更があるかは、それが出る直前まで知らされませんから、未来のOSで問題が出ないように作るのはかなり難しいことです。DraftPad の場合、かなりつまらないことが原因でした。先ほどお話したことですが、バージョン 1.1 で iPad に対応させるために、アクションメニューを押した時に通常の UIActionSheet を出すか、それとも UIPopover を出すか、という条件分岐を UIPopover クラスの有無を見て判定するようにしていました。その当時は、iPhone が OS3.1.3、iPad が OS3.2 でしたが、UIPopover クラスを持つのは OS3.2 だけだったからです。ところが iOS4 が出て、そこには UIPopover クラスが追加されていましたので、iPhone に iOS4 を入れると、アクションメニューを押した時に UIPopover を表示しようとしてしまうのです。厳密に言うと、UIActionSheet をアクションボタンから UIPopover 風のUIで表示しようとするのです。この表現は iPhone では正しく実行されないため、コントロール不能なダイアログになってしまい、ほとんどフリーズしたのと同じ状態になってしまうのでした。
■iPad では有効だったコードが、未来のOSが入った iPhone では問題を起こしたということですか。
□そうです。だからこれは半分は私のフレームワークに関する理解不足の問題ですが、半分はどうしようもなかったことだと思います。何しろ、iPhone で OS3.2 がスキップされることや、次のOSが4になってそれがまず iPhone 用に限定であることなど、誰も知らなかったわけですから。
■それで、その修正が難しくて時間がかかったのですか?
□いえ、その修正は、条件分岐の方法をちょっと変えるだけですから、一瞬なのです。
■ではなぜすぐに修正バージョンをリリースしなかったのでしょう。
□今思えば、すぐにとりあえず問題を修正したバージョンを出せばよかったのですが、iOS4 がリリースされる直前の段階ではすでにバージョン1.2の開発がかなり進んでいましたので、どうせ出すなら新機能を追加した状態で出したいと考えました。App Store での審査も毎回時間がかかりますし。で、そうなると、iOS4 はもとより、iPhone 4 での実機テストをしてから出したいじゃないですか。ですから、iPhone 4 が発売されたらすぐにそれを買って、そしてそれで最終テストをしてからリリースしようと考えたのです。
■実機テストをまったくしないで出すのはかなり怖いですからね。
□はい。ところがですよ。その iPhone 4 がなかなか手に入らないのです。すぐに予約をしたのですが、発売日になっても連絡がない。当日に徹夜で並べば買えたといっても、そんな時間ないですからね。ということで、やっと手に入ったのは発売から2週間経ってからです。そこから最終テストをして、すぐに App Store にサブミットしました。恐らく、iOS4 への対応が遅れているアプリには、私と同じように実機を待っていて遅れているケースも多いのではないかと思っています。
■そうだったんですね。iOS4 および iPhone 4 への対応というのは、簡単だったのでしょうか。
□いや、思ったより大変でした。iOS4 への対応で一番大きなのはやはりマルチタスキングの処理です。iOS4 では、アプリがバックグラウンドにまわる時や、逆にフォアグラウンドに来る時に、特別なノーティフィケーションが発行されます。特に重要なのはバックグラウンドにまわる時で、アプリはデータの保存など、終了時の処理と同じようなことをそこで行わなければいけません。なぜなら、バックグラウンドにまわったアプリは、いつシステムから終了させられるか分からないからです。システムのメモリーが圧迫されると、OSはバックグラウンドのアプリを強制的にパージします。その際アプリには何の知らせもありませんから、アプリは、バックグラウンドにまわる時点で、いつ自分が死んでもいいように身辺整理をしておくわけです。そしてバックグラウンドにまわると仮死状態になって、基本的に自分自身で動くことはできなくなります。で、運がよければまたフォアグラウンドにまわってきて仮死状態から覚め、そのまま前回の続きで動き続けなければなりません。だからバックグラウンドにまわるというのは、自分が再び目覚めるかどうか分からない、このまま死んでしまうかもしれないと知りながら眠りにつくようなものです。また仮死状態の時に、つまりバックグラウンドにいる時にシステムがメモリーワーニングを出して、アプリ内で表示中のビューを破棄してしまうこともありますから、メモリー管理をきちんとしてから眠りにつかないと、猿の惑星の最初のミイラのように、せっかく仮死状態から覚めたのに起き上がれないという状態にもなりかねません。で、そういう諸々の仕様は、アプリの開発初期から分かっていればそのように作りますが、後から追加で加えるというのはなかなか難しい場合があります。UIViewController や UIView の基本構成を変更しないといけないこともあるでしょう。考え方としては単純ですが、修正作業はそれなりに広範囲になるのです。
■なるほど。他に iOS4/iPhone 4 対応で何か苦労はありましたか?
□やはりカーソル位置の復帰というところです。iOS4 になって、マルチタスキングの関係などから、カーソル位置復帰のアルゴリズムをほぼ書き直さなければいけませんでした。それで大変なのは、過去のOS、つまり OS3.1 および OS3.2 とも互換性を持つようにしなければならない点です。またデバイスとしても iPhone と iPad をサポートしなければならないので、その互換性を保ちつつコードをシンプルにするために、結構な範囲で書き直しをしました。たぶん全ソースコードの半分ぐらいを書き直したと思います。一方、iPhone 4 への対応というのは、単純に Retina Display 用に高解像度の画像リソースを加えるだけでしたから、15分ぐらいでできました。
■かなりコードを書き直したんですね。では次に、新機能についてのお話をお願いします。
□アシスト機能ですね。これはもう、すごい機能だと思っています。実はこれ、DraftPad を作り始めた時から考えていたものなのです。DraftPad で本当にやりたかったことはこれだと言ってもいいほどです。
■アシスト機能とはどういうものでしょうか。
□簡単に言うと、DraftPad 用のブックマークレットです。DraftPad で書いたテキストを他のアプリに受け渡すといった処理をブックマークにして管理&実行できるようにするものです。例えば、DraftPad 上で現在カーソルがある行を Safari に渡して Google 検索するとか、Echofon に渡してすぐにツイートできるようにするとか、そういう処理をブックマークのようにいくつも自分で作っておき、実行することができるのです。
■ほう。その処理というのはどのような仕組みで実現されているのでしょうか。
□各アシストの処理は、URLの形式で表現します。これは iOS が持っている OpenURL スキームという仕組みを利用しています。DraftPad の以前のバージョンでも、本文をメールにしたり Google 検索する機能がありましたが、これらもこの OpenURL スキームを使っていました。今回のアシスト機能は、OpenURL スキームをユーザーが自分で作成/編集できるようにしたのです。例えば自分が作ったウェブサービスと連携させて、iPhone 上からインターネット経由で様々な処理を実行させるといったことも可能でしょう。そうなると、DraftPad が一種のマルチパーパスなコンソールになるのです。先ほど、Google というものをエージェントとして捉えたかったと言いましたが、アシスト機能を活用すれば、Google だけでなく、自分の好きなエージェントをキックすることができるようになるわけです。DraftPad 活用の可能性はこれで無限大になります。DraftPad は最早、原稿の下書きツールではなく、デジタルネットワークにおける汎用的なコンソールになったのです。
■うむ。それはすごいかもしれませんね。
□ただ、OpenURL を自分で作成するにはそれなりのリテラシーが必要ですから、誰でも作れるというわけではありません。一応ヘルプ情報を用意してあるので、プログラミングやインターネット技術にある程度親しんでいる人であればすぐに活用できるはずですが、そうでない人には敷居が高いと思います。ですからそういう人のために、「Assist Library」というウェブページを用意して、そこに出来合のアシストを登録しておき、ユーザーが気に入ったものをインポートできるようにしました。このライブラリーは、継続して充実させていきたいと思っています。また Assist Library ではユーザーが自分で考えたアシストURLを投稿できるようにもなっています。
■それはいいですね。ライブラリーに登録されているアシストは、簡単に DraftPad にインポートできるのですか。
□はい、iPhone/iPad 上の Safari でこのページにアクセスし、インポートしたいアシストのリンクをタップするだけです。すると DraftPad のアシスト作成画面が開き、インポートされます。
■ということは外部から DraftPad の機能を拡張できるということですね。
□そのとおりです。その仕組みがアシスト機能の特徴のひとつだと思います。自分で作るだけでなく、誰かが作った機能をアドオンできるわけです。で、そのアドオンを実現するのにも、OpenURL スキームを活用しています。例えばウェブデベロッパーや iPhone デベロッパーは、自分のウェブサービスや iPhone アプリから DraftPad にアシストを追加できるというわけです。
■アシスト機能が OpenURL を活用して外部アプリの API を利用すると同時に、DraftPad 自体も OpenURL の API を持っているというわけですね。
□はい。DraftPad の API は、実は他にもあります。それは、DraftPad に外部からテキストを挿入する機能です。
■他のアプリやウェブページから DraftPad に任意のテキストを送ることができるということですか?
□そうです。詳しくはデベロッパー向けのページを見ていただければと思いますが、これによって DraftPad は、外部からの入力と外部への出力を自由にできるようになったわけです。DraftPad は最初のコンセプトから、自身でデータ管理の機能を持たず、文字入力だけに特化しています。ただしゼロから入力するのではなく、すでにどこかで作成されたテキストを使いたい場合もあるでしょう。そしてそれを DraftPad で編集した後、また他のサービスに渡したい場合もあるでしょう。そのように、DraftPad がテキスト情報の活用フローにおけるハブになるという発想です。
■テキスト情報活用のハブですか。
□はい。iPhone のような携帯デバイスは、複雑なコンテンツの作成や大量のデータの保存管理には向きません。それよりも、手軽に入力できることや、それを外部の様々なサービスに簡単に受け渡せることが重要です。そのような、データの Routing(受け渡し)を Assist することで、iPhone のポテンシャルを大きく広げることになるわけです。アシスト機能と聞いてピンと来た人もいるかと思いますが、この発想は、Newton のコンセプトに通じています。私は Newton がとても好きでした。iPhone に欠けているのは、Newton が重視していた、デジタルデータの Routing を Assist するという部分だと思っています。だから DraftPad でその一端を実現したかったのです。
■なるほど、Newton に通じているわけですね。そう言われれば、一枚の紙というメタファも、Newton の Notes に通じるものがありますよね。
□そうなんですよ。ただあのように図形認識などを行うプログラムは私には書けませんし、それでアプリが複雑になるのもいやですから、DraftPad で扱えるのはプレーンテキストだけに限定しています。でも Newton の頃よりもネットワーク環境が断然進んでいますから、アシスト機能の活用範囲はずっと広くなっているはずです。
■分かりました。それでは最後に、DraftPad の今後の方向性を教えてください。
□はい。実はまだいろいろなアイデアがありまして、そのうちのいくつかは実現していきたいと思っています。DraftPad 構想のうち、今回のバージョン1.2は、だいたい80パーセントぐらいのところだと思っています。ただ、アプリとして複雑さが増すのは望みませんから、よく考えていかなければいけません。
■本日はお忙しいところどうもありがとうございました。
□どうもです。
-
gulliverdj liked this
-
sion96 liked this
-
sion96 reblogged this from manabuueno
-
calmtech liked this
-
mangalcun liked this
-
lioven liked this
-
hluf reblogged this from manabuueno
-
satosnj reblogged this from manabuueno
-
huguri99 liked this
-
firedfly liked this
-
tessy3 reblogged this from manabuueno
-
domingoandtheexperience liked this
-
manamimic liked this
-
alimika reblogged this from manabuueno
-
noriyo liked this
-
abakane reblogged this from manabuueno
-
yoshimana2days reblogged this from manabuueno
-
adalas liked this
-
takahashihideki liked this
-
longspear reblogged this from manabuueno
-
satosnj reblogged this from manabuueno
-
manabuueno posted this