iOS 12 のショートカットアプリ入門あるいは「はてブを開く」を作った話

# 「はてブを開く」ショートカット

iOS 12 から新しく使えるようになったショートカットアプリで「はてブを開く」というショートカットを作りました。これは、iOS 内の様々なアプリで URL をシェアする際に、そこから直接はてブを開けるというショートカットです。ショートカットアプリの使い方は分かってる、細かいことはいいからとりあえず使ってみたい！という人は下記リンクからインストールしてみて下さい。

[「はてブを開く」ショートカット](https://www.icloud.com/shortcuts/c058d40af2d64ca6bb1ebca6c66e7802)

以降では、ショートカットの使い方と作り方、「はてブを開く」ショートカットがどのように動作しているかなどを紹介していきたいと思います。

# なぜこれを作ったのか

多くの iOS アプリが URL をシェアする機能を持っており、大抵はこんなアイコンが用意されていたりします。
<img width="320" alt="app-share-icon.png" src="https://qiita-image-store.s3.amazonaws.com/0/24898/0e4518e9-2206-ec6e-4345-bde99d2b6ccc.png">
そして URL をシェアしようとする時に、はてなブックマークのアプリがインストールされていると、シェアする対象のアプリに表示されます。
<img width="320" alt="app-share-hatebu.png" src="https://qiita-image-store.s3.amazonaws.com/0/24898/cc0e3f9e-fc32-018d-65e8-0ee7d5c3b70f.png">
ところがこのアイコン、はてなブックマークを投稿するための機能であって、はてなブックマークのページを開くことが出来ません。
<img width="320" alt="hatebu-app.png" src="https://qiita-image-store.s3.amazonaws.com/0/24898/f14e2420-0627-25c5-c5df-4f3d8b1fc259.png">
単に他の人のコメントだけ参照したい、とか、ブックマークする前に他の人のコメントを確認して恥ずかしいことを書いてしまうのを避けたい、とか、そういう時ってありませんか？ありますよね？ね？でもこのデフォルトの機能だと出来ないんです。

> 詳しくは知りませんが、URL をシェアする時に別のブラウザ (もしくはそれ相当のアプリ) で直接開くことを Apple が規約で禁じているのだと思っています。URL を別アプリで開くのを Safari に限定させるためですね。だって、Google が「Chrome で開く」を実装しないのあまりに不自然じゃないですか？なので、はてなを責めないであげて下さい。

ですので、ずっと長いこと、わざわざクリップボードを経由して開くっていう手順を踏んでいました。ですが、iOS 12 で利用できるようになったショートカットアプリだったら、やりたい事が実現できるんじゃないかと思って、会社の昼休みに試してみたところ、首尾良く出来たのでここでやり方を共有します。

# ショートカットの使い方

さて、この記事の後半ではどのように「はてブを開く」ショートカットが動作しているか、という解説をしますが、それより先に、まだあまり良く知られていないと思われるショートカットの使い方から説明します。
まずは App Store で[ショートカット](https://itunes.apple.com/jp/app/%E3%82%B7%E3%83%A7%E3%83%BC%E3%83%88%E3%82%AB%E3%83%83%E3%83%88/id915249334?mt=8)アプリをインストールして下さい。全てはそれからです。

ショートカットアプリには、ギャラリーというタブがあって、そこからあらかじめ定義された様々なショートカットをインストールすることが出来ます。自分で作ったショートカットもそこで公開出来るかと思ったのですが、どうやらそういう UI が見つからないので、まだ外部の開発者には開放されていないのかも知れません。

ですが、後述のショートカットを公開する機能を使うと、ショートカットごとにユニークな URL が生成されるので、それを公開することで自分の作ったショートカットをインストールしてもらう事が出来ます。今回作ったショートカットはこちらです。

[「はてブを開く」ショートカット](https://www.icloud.com/shortcuts/c058d40af2d64ca6bb1ebca6c66e7802)

ここで「はてブを開く」ショートカットをインストールしたら、以下の手順で初期設定すると、それを別のアプリから呼び出せるようになります。

まずは任意のアプリで URL をシェアしようとして下さい。二段目のアイコンの一番右端に、その他、という項目があるはずです。
<img width="320" alt="app-share-others.png" src="https://qiita-image-store.s3.amazonaws.com/0/24898/0454aadd-d74d-2142-e8af-d3701df38d21.png">
ここで「ショートカット」を有効にし、必要に応じて並び順も変更して下さい。
<img width="320" alt="app-share-config.png" src="https://qiita-image-store.s3.amazonaws.com/0/24898/056bb06e-3720-7585-1c30-3e0a22506e5f.png">
すると、URL をシェアしようとする時の候補に「ショートカット」が現れます。
<img width="320" alt="app-share-shortcut.png" src="https://qiita-image-store.s3.amazonaws.com/0/24898/ac24778d-1874-32ea-826b-1a9513704c79.png">
ここで「ショートカット」を選択すると、インストール済みのショートカットの中から利用するショートカットが選べるようになります。
やろうとしていることは、単にはてなブックマークのページを開くことですが、はてなブックマークのアプリをインストールしているとそれが URL スキーマとして動作し、はてなブックマークアプリが直接起動します。
<img width="320" alt="animation.gif" src="https://qiita-image-store.s3.amazonaws.com/0/24898/7700b670-254d-ad34-4989-82b0904bc2db.gif">

# 「はてブを開く」の動作

さて、ショートカットの使い方が分かった所で、この「はてブを開く」ショートカットがどのように動作しているかを解説していきます。

それにはまず、はてなブックマークのページの URL がどういう構成になっているかを理解する必要があります。二つ三つの例を見てもらえれば一目瞭然かと思うのですが、はてなブックマークのページの URL は、ブックマークされたページが `http` の場合は `http://b.hatena.ne.jp/entry/`、`https` の場合はそれに `s/` を追加した `http://b.hatena.ne.jp/entry/s/`で始まります。そしてその後に、ブックマークされたページの URL から `http(s)://` をのぞいた部分を URL エンコードしたものを続けます。

つまり、「はてブを開く」ショートカットを作るにあたっては、上に書いたような事を自動化すれば良いことになります。

ではここで、「はてブを開く」ショートカットの全容を公開しましょう。
<img width="320" alt="editor-full.png" src="https://qiita-image-store.s3.amazonaws.com/0/24898/8f16c2b8-cd08-0511-72db-b8d9c6649e95.png">
思ったより長かったですか？短かったですか？全く同じ事をするブックマークレットも使っているのですが、それが JavaScript で高々 114 文字なので、真っ当なプログラミング言語と比べたら圧倒的に長いことは否めません。とはいえ、ビジュアル言語ってそんなものですし、iOS が公式でここまでカスタマイズできるようになった事を喜びましょう。

上部にあるこのアイコンからは、ショートカット自体の設定が行えます。
<img width="320" alt="editor-top-config-icon.png" src="https://qiita-image-store.s3.amazonaws.com/0/24898/03e1dbed-8dca-21e9-843d-707497f9b35b.png">
ここでショートカットの名前やアイコンなどの設定が出来るのですが、重要なのは「共有シートに表示」を有効にすることと、「受け入れの種類」に「URL」を指定する事です。こうすることで、他のアプリで URL をシェアしようとした時に、このショートカットを選ぶことが出来るようになります。
<img width="320" alt="config.png" src="https://qiita-image-store.s3.amazonaws.com/0/24898/2fe121d4-d466-deb8-aaa0-fc16473b7375.png">

続いて、ショートカットに設定した各項目について順に説明していきます。

## 入力から URL を取得
入力されているのが URL という前提なのに、なぜこんなものが必要か疑問に思うでしょうか？それは URL をシェアしようとした時にショートカットに渡ってくる情報が、URL だけではないからです。実際にはそのページのタイトルと URL の両方が渡されてくるので、ここで URL のみを取得します。

これ以降の全てで基本的には同様ですが、ここで処理した結果が次の項目に渡されていくことになります。Unix のコマンドラインのパイプをイメージすると近いですね。

## ~~URL を展開~~
~~前の項目から URL のみを受け取ったあとでそれを展開します。これは、`bit.ly` などの短縮 URL を元の URL に戻してくれるもので、今回の用途では必須でありません。将来的にそういった URL をクリップボードから読み込みたい場合もあるかと思って念のため追加しています。~~
これがあるとパフォーマンスにかなり影響がある事が分かったので (考えてみれば当たり前) 最新版のショートカットからは削除しました。

## URL エンコード
受け取った文字列を URL エンコードします。シンプルですね。これが後々、はてなブックマークのページの URL の一部として使われることになります。

## テキストを分割
はてなブックマークのページの URL で使われているのは、元の URL 全体では無く、プロトコル部分を省いたものだというのを覚えているでしょうか。ここでは受け取った文字列を `://` で分割することによって、プロトコル部分とそれ以外に分割しています。

ここでちょっと面白いのは、この「テキストを分割」した結果は、次の項目にリストとして渡されていくという事です。シンプルに標準出力と入力を繋ぐだけのパイプよりも賢いですね。

## 次の場合
さあ来ました！いわゆる `if` 文です。一つ前の項目から渡されたリストの中に `https` が含まれるかどうかで分岐しています。分岐自体はその出力に影響を与えないので、「テキストを分割」した結果のリストがそのまま次の項目に渡されていきます。

## リストから項目を取得
リストに対して「最後の項目」を取得するように指示します。これによって、元の URL から `://` より後の文字列が取り出せたことになります。

## URL
新たに URL を生成することが出来ます。ここでは `http://b.hatena.ne.jp/entry/s/` の後ろに一つ前の結果をつなげることで、最終的に `https` 向けの URL を生成しています。

## その他の場合
まあ `else` 句ですね。`https` の代わりに `http` 向けの URL にする以外は `if` 句と同じです。

## 次の場合に終了
誤訳だと思います。「"次の場合"**を**終了」とすべきではないでしょうか。これは `if-else` 文の終了を表します。

## URL を開く
一つ前までで、`https` と `http` の両方にあわせた、はてなブックマークのページの URL が生成されているので、それを開くように命令して終わりです。
ここでその URL が特に何の URL スキーマにも引っかからなかったら、シンプルに Safari が立ち上がるのだと思いますが、前述のように、はてなブックマークのアプリがインストールされた環境では、そちらが立ち上がります。

# ショートカットを公開する
最後の項目は、作成したショートカットを公開する手順です。ショートカットアプリのギャラリータブで公開出来るのがもちろんベストなのですが、現状では難しいようです。ですので、下記の手順で公開用 URL を取得して、それをシェアしてみましょう。

とはいえ、めっちゃシンプルです。設定用のアイコンの隣にシェア用のアイコンがあるのでそれを選択します。
<img width="320" alt="editor-top-share-icon.png" src="https://qiita-image-store.s3.amazonaws.com/0/24898/bd2753e5-50a7-27f8-5b3e-254acccd09fd.png">
そこに「iCloud リンクをコピー」というのが見つかるはずなのでそれを選択すれば、ユニークな URL が取得出来ます。シンプル…ですが、この説明で分かるか！とは思います。
<img width="320" alt="app-icloud-link.png" src="https://qiita-image-store.s3.amazonaws.com/0/24898/c65ce759-730f-da84-8b98-f8b34ba6adef.png">
一点、注意点としては、このユニークな URL はバージョンも自動的に管理されていて、ショートカットの内容を変更すると URL も変更になる点です。ですので、酷いバグのあるバージョンを公開して例えば Twitter などで拡散してしまったら、そのバグを後で直したとしても公開済みの URL では修正が反映されません。気をつけましょう。

# まとめ
まあ正直に言って普通にプログラムする方がずっと楽です。このくらいシンプルな処理だったらそのままショートカットのロジックに落とし込んでも大したことないですが、より複雑なことをしようと思ったら、どっかのサーバでほぼ全部動かして、ショートカットは API 呼ぶだけ、みたいにしたくなりそうです。
それはそれでネットワークのレイテンシの分、動作が絶対的に遅くなるのでトレードオフではあるのですが…。

なので、この記事を読んでやる気を出した人達が、有用なショートカットをいっぱい公開してくれるようになったら嬉しいな、と思っています。