iOS 9 (XCode7) でできること、できないことまとめ

iOS9が正式リリースされるまであと少しとなったので、影響を受けそうなとこをろまとめてみた。なお、この記事は以下の前提で記載しています。

```
iOS9の各機能は、現時点(2015/09/07, iOS 9 beta 5)での情報を元に記載していますので、正式リリース時に変わることがあります。また、この記事でのiOS9アプリというのはXCode7でビルドしたアプリをiOS9上で動かしたもののことを指します。
```

# アプリ内で非SSL/TLS通信ができない
XCode7でビルドされたアプリはデフォルトでは、非SSL/TLS通信ができない。WebViewだけでなく通信ライブラリにも適用される。これによって、非SSL/TLSのWebコンテンツが表示できない、非SSL/TLSのAPIからデータが取得できなくなる。

### 対処するには...
各アプリごとに`ATS(App Transport Security)`を設定することで、非SSL/TLSのコンテンツを取得することができるようになる。`すべてのドメインに対して例外を指定`、`特定のドメインに対して例外を指定`、`セキュアでないHTTPS接続を可能にする`などを記述できるので、ひとまずこれらを指定しておけば今まで通りには動かせる。

くわしい設定の仕方はこちら: [[iOS 9] iOS 9 で追加された App Transport Security の概要](http://dev.classmethod.jp/smartphone/iphone/ios-9-intro-ats/)

もしくは、後述の`SFSafariViewController`を使うことでも解決できる。


### ただし、全アプリが設定しているとは限らない...
ただし、これらの設定を全アプリがしているとは限らないため、他のアプリ内で表示されるであろうWebコンテンツ(ニュースサイト、ブログ、キュレーションメディアなど)はSSL/TLS化をしておいた方がよさそう。


# WebViewでSafariとCookieが共有ができる
`SFSafariViewController`を使うことで、SafariとCookieを共有することができるようになった。これによって、Safariでログインしていれば、アプリ内でも同じユーザーとして利用できたり、Cookieを使った計測のためにSafariを起動しなくてよくなった。

### ただし、カスタマイズができない
ただし、`SFSafariViewController`はカスタマイズがほとんどできないため、URLをフックして表示を変えたり、ボタンを配置したりなど、アプリ内で処理を加えることができない。


iOSで提供されているWebViewたち。

|  | UIWebView | WKWebView | SFSafariView |
|:---:|:---:|:---:|:---:|
| 非SSL/TLS通信 | ✕ | ✕ | ◯ |
| SafariとCookie共有 | ✕ | ✕ | ◯ |
| カスタマイズ | ◯ | ◯ | ✕ |

# Safariに適用できる広告ブロックExtension
提供されるのは、コンテンツブロック機能なので広告とは限らないが、実際には広告ブロック機能をつけたExtensionが作られることが予想できる。

例えば、`サイトから広告を消すこと`や、`そもそも広告を読み込むJavaScript・Cookieを設定するリソースを読み込まないようにすること`、`YouTubeの広告動画を見ることなく本編が見られるようにする`などができる。
イメージ動画: https://www.youtube.com/watch?v=fEpEv_wOgJo

Extensionでは以下のように指定でき、特定のリソースを読み込まないようにしたり、特定の要素を非表示にしたりできる。

```json
[
    {
        "action": {
            "type": "block"
        },
        "trigger": {
            "url-filter": "example.com/track.js"
        }
    },
    {
        "action": {
            "selector": "a[href^=\"https://example.com/redirect\"]",
            "type": "css-display-none"
        },
        "trigger": {
            "url-filter": ".*"
        }
    }
]
```

ただし、適用するには、

- Extensionをインストール
- Safariの設定でONにする

というフローが必要なので、どれくらいのユーザーが利用するかは未知数。

# 戻るボタンが出てくる
アプリ間で遷移した時に、左上に「戻る」ボタンが表示される。これによってアプリ遷移後もどってきやすくなる。ただし、表示がかなり小さいのでユーザーが気付くかやや不安。



# リーダーモードで背景色・フォント指定できる
個人的によく使うSafariの`Reader Mode`のデザインを細かく設定できるようになった。設定できるのは、フォントと背景色。Kindleアプリみたいな感じ。`SFSafariViewController`でも同様に設定可能。


# Spotlight, Safari検索結果に表示する
Spotlight, Safari検索結果に表示される内容が拡張され、Webサイトやアプリから指定もできるようになった。

Webサイトでは`App Links`, `Twitter Card`, `Scheme.orgマークアップ(JSON-LD)`を入れておく。
詳しくはこちら: http://qiita.com/herablog/items/ce9ceaccb13c304855f4

アプリでは`Search API`でインデックスしたい内容を送信できる。また、`deeplink(Custom URI Scheme)`でアプリの特定の画面に直接遷移できるようにしておくとよさそう。
詳しくはこちら: http://qiita.com/herablog/items/ce9ceaccb13c304855f4#ios-search-spotlight-safari-search

ただし、何をいつどのように表示するかはAppleが決めるので、対応したところで必ずしも表示されるとは限らない。


# アプリがあったらいきなりアプリ起動 (Universal Links)
iOS9から追加される`Universal Links`を使うことで、特定のURLをタップした時に、アプリがあったらアプリを開く、なければSafariで表示するということができるようになった。

これは、Safariでページを表示する前にアプリに遷移するので、アプリ間遷移にも使え、上述の戻るボタンで元のアプリに戻ることもできる。また、アプリを開く際に、`Custom URI Scheme (e.g. twitter://)`を使わなくてよくなり、URLがひとつに統一されるというメリットもある。

ただし、以下すべての設定を満たさなければならないのでなかなか大変。

**Web**: `SSL/TLS`にする、ドメインルートに該当ドメインのSSL証明書で署名された`apple-app-site-association`というファイルを置く
**App**: XCodeで対応するドメインを設定する、アプリの特定のページを開けるようにしておく(deeplink)

詳しい設定の仕方: [URLスキーム・独自ディープリンク実装に代わる、Universal Links(iOS 9で導入)でより良いUXを実現](http://qiita.com/mono0926/items/2bf651246714f20df626)

また、上記設定されたアプリからは、`インストール時`, `アップデート時`にサーバールートの`apple-app-site-association`にアクセスされるため、結構負荷がかかる(？)と言われているので、ドキドキしながら取り入れなくてはならない(未確認)。

> アップルのテクニカルサポートへこの件について問い合わせしたところ次のような返答がありました。
返答を要訳すると、アプリのインストール、再インストール、アップデート時に/apple-app-site-associationにアクセスします。自動アップデートの時間は決まってないけど、グラフを見ればリクエスト数予想できますね？アプリをアップデートするスケジュールに応じて、サーバーにどれくらいの負荷がかかるか予測して下さい。という旨のキビシい返答でした...

詳しい情報: http://techlife.cookpad.com/entry/2014/12/11/093000

# Custom Schemeでのアプリ起動 (50個まで)
アプリ起動に使う`Custom URI Scheme`を`Info.plist`内で明示的に宣言する必要があり、その限度は`50`までと言われている。通常のアプリでは困ることはなさそうな数だが、アプリ起動をたくさんするプラットフォーム的なアプリは作りにくくなった。

詳しい記事: [Security and Privacy Changes in iOS 9](https://nabla-c0d3.github.io/blog/2015/06/16/ios9-security-privacy/)

# IPv4 Only時の25msタイマー
iOS9では、IPv4よりIPv6が優先されるようになるので結果的に、IPv4 Onlyの環境では、`25ms`遅くなる。以下がその実装フロー。

> The updated implementation performs the following:
- Query the DNS resolver for A and AAAA.
   If the DNS records are not in the cache, the requests are sent back to back on the wire, AAAA first.
- If the first reply we get is AAAA, we send out the v6 SYN immediately
- If the first reply we get is A and we're expecting a AAAA, we start a `25ms` timer
   - If the timer fires, we send out the v4 SYN
   - If we get the AAAA during that `25ms` window, we move on to address selection

(Apple and IPv6 https://www.ietf.org/mail-archive/web/v6ops/current/msg22455.html)