投稿日:

[iPad] Coardはまだリリースできません

アイキャッチ



ご無沙汰しております、Coard開発者です。
2020年ももうすぐ終わりを迎えますが、なにげに今年初めての記事投稿です。
今回は長らくアップデートしていないiPadアプリ、Coardについてのご説明です。
(文中に広告がいくつも入っちゃってて読みづらくてすみません)

じつは現在開発しているVersion 3.0を8月末に審査へ出しており、9月頭には審査を通過してリリースできる状態にありました。もちろんリリースするつもりで審査に出したわけです。ところがその後問題が次々と発覚し、ボタンひとつのクリックでアップデート公開しようと思えばできるがあえてしていない、というのが今いるところです。

ただし強調しておかなければならないのは、リリースしようとしているVersion 3.0は、なんら実用性を伴わない最低限の見栄えをなんとか確保しただけの"飾りアプリ"だということです。
本尊であるエディタのほとんどの機能は実装できておらず、複数の下書きを作成できないどころか、ファイルシステムすら存在しないのでテキストの保存ができません。外部への共有もできず、キーボードショートカットもありません。Coardキーボードのほうも、定型文のカスタム登録ができないし、カスタムキーボードとして他社アプリで使うこともできません。
v3をリリースしたとしても、アプリがあまりに原始的でがっかりすることと思います。

今までの経緯

これまでの経緯などについては当ブログの製品ページにすでに書いており、v3のアップデート説明文やストアの紹介文にも記述しているので同じことをあちこちに何度も書きたくなかったんですが、v3はまだしばらくリリースできないと判断したため、今回記事にすることにしました。

もともとカスタムキーボードとして出発したCoardは、2017年2月にリリースしたVersion2.0にて膨大な機能が組み込まれた「テキストエディタ」を搭載しました。ところがその直後にプログラミング言語上のトラブルが発生し、一から作り直すことになりました。
iOS開発者の方ならわかると思いますが、Swift3というメジャーアップデートが大規模な仕様変更をともなう破壊的なもので、Swift2.2から更新した結果、案の定Coardプロジェクトでは意味不明なエラーが出て、原因究明は困難を極めました。
文法上の修正は一通りやったにも関わらずエラーは消えず、しかもそのエラーの意味がまったく検討つかないという始末。これ以上の原因追求は時間のムダだと判断し、プロジェクトを作り直すことにしたのです。
本質的には自分のコーディングの問題なんですが、当時のXcode(開発ソフト)のエラー検知も未熟で、翌年の新バージョンのXcodeで確認したらエラー表示がもっと具体的になっていて愕然としました。

エディタ実装を始める前にSwift3にアップデートできたら良かったんですが、タイミングは絶妙に食い違っていました。
Swift3がリリースされたのは2016年9月。一方、大規模な機能追加を行うエディタ開発に取りかかり始めたのは、その2ヶ月前の7月。実装できるかもわからない未知の機能群に挑戦する日々だったので、当然ながらSwiftの億劫なメジャーアップデートなんて後回しにします。特にこの時は経済的にもギリギリだったので1日でも早くリリースしたいと毎日必死に取りかかり、急いでいました。
エディタ搭載版をリリースした2017年2月当時、Xcode8の主流はSwift3.x。同年秋にリリースされたXcode9でSwiftはもう4.0。Swift3とCoardエディタの衝突を避けることはできませんでした。

それから3、4年の月日が経ち、開発はずっと継続してきたものの、2020年末現在、アプリはまだ原始的な状態にとどまっています。正直こんなに時間がかかるとは夢にも思っていませんでした。
作り直すといっても元データは存在するわけで、決断をした当時は一つ一つコピペしていけばそう時間はかからないだろうと高をくくっていました。

ところが実際に一から見直していくと、昔の自分が書いたコードの問題がどんどんどんどんわかってしまう。それを知ってしまうと直さないわけにはいかない。だから丁寧に書き直す。元データのコードは複雑に入り組んでいるのでコピペする余地がほとんどなく、一つずつ書き直していくので時間はどんどんかかっていく。この3年間それを延々と繰り返してきた、というのが実際のところです。

ソフトウェア開発というのは普通、少しずつ改良を積み重ねていくべきであって、一から作り直すというのはあまり良いアプローチではありません。もしそうするとしても、リリース版も並行アップデートしていくのが望ましいと思います。
ところが自分の場合、Swift2.x版との並行開発というアプローチは選びませんでした。全体を手っ取り早くコピペしてリリース版をつくり、さらにそれとは別に「一から再構築版」もつくるという二重生成・並行開発が、二度手間な感じで正直気持ち悪かったというのはあります。
再スタート当初はまさかここまでコピペしていられないとは予想できず、なんとかなるだろうと思っていました。そして前述のようになり、マイナーアップデートさえ提供できず、iOS10、9.7インチ対応までで時間は止まり、2020年4月、App Storeから強制的に除外されることになりました。

方針の転換

実は行き当たりばったりで見直しに直面していったのではなく、再スタートを切ったときに開発方針を変えています。つまり「スピード/機能追加重視」から「品質/安定性/保守性重視」への転換です。
それまでの開発姿勢は、とにかく機能的な魅力をどんどん高めていくこと、それをできる限りスピーディに世に出していくことでした。といってもこれは開発哲学というより、単に我欲からくる勢いのようなものです。

開発期間7ヶ月のエディタは「絶対的安定性は死守する」という意気込みで取りかかり、実際クラッシュする箇所といえば1万字のファイル(読み込みに時間がかかる)を含んだ下書きタブを高速で切り替えたときくらいで、膨大な機能追加アップデートにしては安定していたと思います。
(iOS12の環境下でもそれは変わらず、2度のメジャーアップデートによく耐えたなと我ながら感心していました。他社アプリで使えるカスタムキーボードに至ってはiPadOSでも実用レベルでした。)
それでも一日でも早く出さなくてはと焦っていて、今の自分が見ると本当に汚いコードを書いていました(当時の自分はじゅうぶん整えているつもりだった)。
そしてSwift3の門前で、その複雑で見苦しいコーディングのツケを払うことになります。

この反省を踏まえ、Coard開発では短期的なメリットよりも長期的な繁栄を重視する方針でいくと決意しました。エディタ開発当時の自分は「絶対的安定性」は重視していたものの「可読性/保守性/柔軟性の高いCoding」までは、こだわりがまだ十分に行き届いていませんでした。
僕はソフトウェアのことを「複雑巨大な超構造体」と呼んでいますが、ソフトウェアというのは構造上、物理的な物体よりもはるかに複雑で、徹底した管理が不可欠です。それを本気で丁寧にやるとなるとどうしても時間がかかります。ソフトウェア開発と締め切りは折り合いが悪いとつくづく実感します。

YoutubeでSurface Duoのレビューを見るとわかりますが、DuoのOSは、キーボードが表示されない、スワイプアップが反応しない、画面表示がおかしくなる、裏表のスクリーン切替が反応しないなど、低レベルなbuggyさが目立ちます。ソフトウェアを開発する者として、こういう粗雑なモノづくりはしたくないと思っています。
今年9月にCoard購入者から問い合わせをいただき、ずっと待ってんだよ返金するぞコノヤロー!というお叱りをいただいたばかりですが、残念ながらユーザーさんにどんなに急かされても急いで出すことはできません。
v2で急いだからこそ、このような状況を招いた部分もあるからです。ソフトウェア開発は「急いだら負け」だと思っております。

Coardの設計仕様の影響

しかし丁寧にコーディングするとしても、なんら実用性を伴わない最低限の見栄えを確保するまでに「数年」はかかりすぎですね。
なぜここまで時間がかかるのか。一番の要因は、Coardのその独自UIにあります。

一般的なiOSアプリではUIデザインのベースはすごく似ていて、
・左サイドにテーブルビュー/リストビュー、
・その右隣にメイン画面、
・そしてナビゲーションバー(画面上部)やショートカットバー(キーボード上部)にボタンを羅列する

というパターンが定石です。

ATOK、iA Writer、LiquidLogic、Ulyssesのスクショ (ATOK、iA Writer、LiquidLogic、Ulysses)

多くのアプリはこの枠組みを前提として独自の機能を当てはめていくわけですが、これならベースUIそのものに時間や手間はほとんどかかりません。
ボタンは「上下左右に定められた境界線」に沿って羅列すればよく、コンテンツは「上下左右にスクロールできるビュー」に羅列すればいいだけだからです。その境界線やスクロールビューが、物理的な画面サイズや比率に自動で適応してくれます。
これはmacOSやWindowsで昔から採用されているUIシステムで、Split Viewや多様な画面サイズへの対応はすぐに完了します。
一方のCoardはそうはいきません。

Coardでは設定のOn/Offスイッチを除く、大部分のUIが独自レイアウトか、細部まで独自のカスタマイズが施されています。
例えばアプリ全体で、画面上部にボタンを設置しない「ナビゲーションバー排除」の姿勢を貫いており、5つのページが同時に横に並び、スクロールで手軽に移動できます。

CoardのBaseUI

下部には対応する5つのタブボタンがありますが、これも横へスクロールし、上のページとリアルタイムで連動し位置が変わる、という入り組んだ機構になっています。
もちろんこれはAppleが提供するテンプレートなどではなく、完全な自作です。
したがってこのベースUIである時点で、Split Viewや画面サイズどころか、縦向き対応さえ困難となります。11インチのような縦横比率が異なるのも、微妙な調節が必要です。

それに加え、エディタではシステム標準のスクリーンキーボードの代わりに、独自に構築した「Coardキーボード」が常時表示されるようになっています(こんな仕様のアプリは他に知りません)。

エディタ画面

キーボード上部にボタン乗っけるだけの"ショートカットバー"より難易度が高いだけでなく、この「独自管理キーボード×ページのスクロール遷移」の組み合わせ、これがまた事を複雑にする部分で、無数のバグを誘発します。

ページが移動するたび、またはアプリのバックグラウンド状態が変わるたびにキーボードの解放・再生成が発生し、ちょっとした例外イベントでもキーボードが表示されなかったり、クラッシュしたり、各キーがうまく生成されなかったりといった問題に悩まされます。
(例えば他のアプリを起動中、Dockからのドラッグ&ドロップでCoardを起動させるパターンだと独特のバグが発生する、など。)

CoardKeyboard表示非表示のGIF

OS、アプリ、キーボードのライフサイクル特性を深く把握しなければならず、一から作り直してもかなり四苦八苦してきました。
もちろんそのキーボード自身も、他社アプリで使えるカスタムキーボードとしての調整が別途必要で(v3では利用不可)、画面サイズによって「キー数」も調節しなくてはいけません(ここもまだ手が行き届いてない)。
近年のAppleのiPad新サイズ連発祭りは、僕にとっては単なる悪夢です。

さらに、そのベースの上に乗っている機能群も実装が難しいものばかりです。
円運動UIであるカーソルホイール、それと物理キーボードの連動、command/option/controlキー単発による言語切替、space keyをトリガーとする独自のキーコマンド、space + tabだけで切替/削除/新規作成ができ6つの下書きを高速切替できるDraftTabUIなどなど、これらはその存在自体に高度な技術力を要求されます。

例えばOSの仕様上、iOSではmacOSのようなキーリマップは本来、開発者が行うことはできませんが、僕は泥臭いことをしてspace keyを「Shortcut Trigger Key」として使えるようにしました。企業であってもここまでやろうとは思わないでしょう。

最後の苦労話に、エディタ両サイドにある「ボタンの位置調節」があります。
スクリーンキーボードが表示されることによってサイドボタンがキーボードの下に隠れてはいけないので、キーボード高さに合わせて動かしてあげないといけない。

サイドボタンのGIF

彼らは何が何でもキーボードをひらりとかわさなければならないのです。

じつはここも非常に難しいところで、キーボードの高さの"最終決定値"を結論づける処理の実装だけでも、毎日とりくんで2ヶ月はかかっています(その後のiPadOSで仕様が変わって唖然)。
システムが"高さ値"を吐き出してくれても、それが変形途中のものなのか最終値なのかは教えてくれませんし、別言語のキーボードへ切り替えても高さ値を吐き出してくれなかったり、はたまた何度も吐き出されたりするからです。つまり意味不明なんです。

そこで僕はiOSのシステムキーボード"全言語全種"の高さを片っぱしから調べ、表示・切替・分割・統合それぞれの挙動も調べ尽くし、いくつかの挙動パターンがあることを導き出してアルゴリズムに落とし込みました。
(一般的なアプリなら、ナビゲーションバーかショートカットバーにボタン乗せて終わり。)
リリースしていたVersion2.0のサイドボタン挙動は上記GIFほど洗練されておらず、それでいてコードも煩雑に入り組んでいました。
新アルゴリズムは最終決定値をポンと出すだけのシンプルさです。


時間がかかることほど効果は強力

一人で取りかかる量ではないですね。だからといって一般的なUIをベースとしたらCoardとして存在する意味がなくなります。独自のUIそのものが、独自の機能性を発揮しているからです。そして他のアプリやOSでは体験できないような使い心地を提供します。

先に触れた一般的なUIスタイルは、iPhone向けのものを上下左右に広げたものにすぎず、そのスタイルに依存するとタブレットの潜在能力を引き出すのが難しくなるんです。だから僕は長期にわたる苦労をしてでも独自のUIデザインにこだわっています。

この独自性のおかげで、Coardにライバルは存在しません。他のText Editorは直接のライバルではないです。Coardはエディタアプリというより、エディタ機能も持つText Operating Systemで、Text Editorを超えたところを目指しています。
CoardのUIデザイン・機能アイデアの多くは僕の視点や哲学に根ざしているもので、日本企業はもとよりシリコンバレーからも出てくることはないでしょう。

じつは昔開発していたiPhone用Twitter投稿アプリ「Twitee」も似た境遇だったんですが、Twiteeが本質的に要求するレベルに自分の技術力が付いていけず、iPhone6以降の画面サイズもろくに対応できないまま終息させました。
特にTwiteeはリリース当初大ヒットしたはいいものの無料にしてしまい、ハナから採算性のないアプリでした。
リニューアル版「Twitee i」で課金システムは導入したものの開発の負担が著しく増え、便利なテキスト編集UIも短文Twitterでは宝の持ち腐れ、かといって投稿サービスを選べるような設計は根本的に向いておらず、しかもコードはObjective-Cで書かれているなどなど…開発者としては救いようのない重荷でした。

個人開発者のブログで、発案から開発、リリースまで1,2週間しかかからなかったという話をたまに見かけますが、同じ個人開発のアプリでも、Coardで直面している難題は技術的にも時間的にも次元が違うと言えます。
そんな僕から少し厳しい意見を言っておきますと、2週間や1ヶ月そこらで完成してリリース、あとは放置して別のアプリに手をつける、というような姿勢では、十分な/長期的な成果を望むほうにムリがあると考えます。少なくともツール系アプリはそうでしょう。

Coardも金銭的な成果はまだまだですが(そもそもアップデートを4年近くしていませんが)、Coard Editorリリース直後、日本だけでなくアメリカ、EU、イギリス、ロシア、韓国、中国、香港、シンガポール、ブラジルなど、洋を問わず各地でバランスよくダウンロードされ、国際的な手応えは感じました。自分のアイデアは世界に通用するなと。

このブログからの流入と英語下手な関係上、日本がほとんどですが、¥2200という高価格設定であるにも関わらず(そしてアップデートをしていないにも関わらず)、ストアから除外される今年初頭までコンスタントにダウンロードされ続けていました。
よって、ぶっ飛んだ高価格も問題ではないことを確認しました。
Coard開発は短期的には採算度外視でやっていますが、長期的には採算性を考慮しています。

製品開発のサイクル

既知の事実として、すべての製品は導入期、成長期、円熟期、衰退期の4つの段階を経過します。

4つの製品サイクル

アプリ自体は2015年末にリリースしていますが、機能的には2017年のエディタ化が本当のスタート地点だったと言えます。しばらく経ってから気づいたのは、そのエディタリリースはまだ「導入期」だったということです。
つまりロケットが膨大なエネルギーを噴射して離陸していくように、Coardもこれから開発エネルギーをふんだんに出して強化し続け、上図のような成長曲線を描いていかなければならなかった。ところが出だしでつまづいて離陸に失敗し、未だに導入期にとどまっている、というのが客観的状況と言えます。今はロケットを作り直しているところです。
Coardのライフサイクルはなかなかの長期になるかもしれません。

iOS11がリリースされた2017年の頃からすでに、アップデートを提供できないことに強い焦りと罪悪感をいだいて過ごしてきました。20代の人生における最大の悔いです。
しかし今思えばv2のリリースは、前例のないユニークなアイデアも意外と形にできる、自分のアイデアはちゃんと作れば高値でも買ってもらえる、そして世界で通用する、ということを"とりあえず"確認するステップだったように感じられます。
モノづくり的にも商売的にも、確認のフェーズでした。
すると今回のVersion 3.0は、足場を整え腹帯を締め直して本格的なスタートを切るステップだと捉えることができます。

ユーザーさんからしたらそんなん知ったこっちゃないでしょうが、まだユーザー数の少ないうちにリセットをかけといて良かったと今は思います。2015〜16年の間に蓄積してきた汚いコードを払拭することができ、アプリの基盤を整えることができたからです。

アップデートを提供してこなかったのはただひたすら罪悪感で、経緯や過程がなんであれモノづくりを通してではなく、こうして言葉による語りがひとり歩きしてしまっているのは、自分の不甲斐なさや至らなさを感じずにはいられません。しかしそれでも作り直したこと自体は良い判断と思っており、後悔はしていません。
またコーディングだけでなく、この3,4年の間にソフトウェアやコンピューティングに対する思想哲学、デザイン的/美的センスも徹底的に磨いてきました。その鍛錬の勢いは今後も増していくつもりですが、これからはその知性と感性をふんだんにCoardに落とし込んでいきたいと思っております。

というわけで、すでにCoardユーザーの方は忍耐強く、しかし何も期待することなくお待ちいただければと思います。


投稿日:

【Swift】 コンテナアプリ内で自作キーボードExtensionをインストールなしで表示させる方法

ios swift アプリ内 カスタムキーボード エクステンション 表示 インストール 方法 inputView




キーボードエクステンションの情報はネット上にそれなりに出回るようになりましたが、コンテナアプリ(以下親アプリ)内でユーザーの追加の有無に関係なく表示できるようにする情報が見当たらなかったのでここでご紹介します。


続きを読む 【Swift】 コンテナアプリ内で自作キーボードExtensionをインストールなしで表示させる方法

投稿日:

【Swift】Smart keyboardで(絵文字キーボードのように)カスタムキーボードを表示させる

swift objective c xcode smart keyboard ios custom keyboard emoji keyboard show hide not カスタムキーボード 絵文字キーボード 表示 されない





外付けキーボードも視野に入れたカスタムキーボードを作っている身として、Smart Keyboardにソフトウェアキーボード表示キーが存在しない仕様にはかなり困惑しました。

というのも僕のカスタムキーボードは外付けキーボードを接続したときに自動で画面外へ隠れる仕様にしていたためです(システムキーボードと同じ)。

これはキーボードのprimaryLanguageを”複数言語(mul)”に設定することで実現できるんですが、
こうすることで、どんな入力言語を追加していても外付けの「ソフトウェアキーボード表示キー」で柔軟にカスタムキーボードの表示・非表示ができるようになります。

しかしこの仕様のままSmart Keyboardを接続されてしまうと、さあ大変です。
カスタムキーボードは自動で隠れ、再表示させる手段はありません(接続を解除しないといけない)。

しかしその解決策がなんとか見つかったのでご紹介します。

続きを読む 【Swift】Smart keyboardで(絵文字キーボードのように)カスタムキーボードを表示させる

投稿日:

【Swift】コードでAutoLayout実装をしやすくするために工夫したこと

xcode ios autolayout コード





衝撃的な話から入りますが、なんとiOS開発歴4年目でAutoLayoutデビューを果たしました(最近の話)。

ようやく重い腰を上げたという感じですが、ぎっくり腰だったんじゃないかと思いたくなるほどで、コードを書く者としては罪深いことをしてしまったような気がしています。

さて、まず知識的な勉強から始めたわけですが、StoryboardによるGUI的なやり方はどうも手をつける気持ちになれませんでした。
なんというか「コード」と言う名の引力が僕を引っ張っている感じなんです。(?)
続きを読む 【Swift】コードでAutoLayout実装をしやすくするために工夫したこと

投稿日:

【Swift】UIKeyCommandでUIKeyModifierFlagsを複数セットする方法

swift uikeycommand uikeymodifierflags





上のアイキャッチ画像はドローンを表現してみたんですが、意外と気持ちわるくなってしまいました。

さて、外付けキーボードのキーボードショートカットを拾うためにUIKeyCommandを使いますが、
shift + command + Aのように複数の装飾キーを同時に登録したい場合もあるかと思います。

この部分でちょっとハマりましたので解決法をご紹介。


続きを読む 【Swift】UIKeyCommandでUIKeyModifierFlagsを複数セットする方法

投稿日:

【iOS】ユニークなWebページ読み込みインジケータを作ってみた

Coard for iPad UIActivityIndicator デザイン オリジナル 自作 swift おすすめ





iPadアプリで更新情報ページへアクセスするための内臓ブラウザを使っているんですが、iOSのUIActivityIndicator(下の画像)を使うことに嫌気がさしてしまいました。

続きを読む 【iOS】ユニークなWebページ読み込みインジケータを作ってみた