2017年10月2日月曜日

UIActivityViewControllerには罠がある

UIActivityViewController は画像やテキスト、URLなどを他アプリへ渡す仕組み。
Twitter, FacebookなどのSNSにシェアしてもらうときに使える。

実装はとても簡単。シェアしたいものを配列にして渡す。

let image:UIImage = ...
let shareItems:[Any] = [image,  "Hi!"]
let controller = UIActivityViewController(activityItems: shareItems, applicationActivities: nil)
present(controller, animated: true, completion: nil)

これで、以下のようなシートが表示される。


手軽なのでよく使っているのだが、罠がある。

1. 画像をシェアするときには、Usage Descriptionが必要


「Save Image」ボタンで、写真appに画像を保存できるのだが、その際にPhoto LibraryのUsage Descriptionが無いとクラッシュします。
写真appにアクセスしていないアプリだと見落としがちなので注意。

iOS10までは、Privacy - Photo Library Usage Description で読み込み/保存の両方ができましたが、iOS11からは書き込み時にはPrivacy - Photo Library Additions Usage Descriptionが必要です

Usage Descriptionは、Extension側で管理してよ と強く思います...!
「Save Image」はデフォルトで入っているものですが、3rd party appでもそうなのかどうかは試してないので不明。
どんなExtensionが使われるかはユーザ依存なので、アプリ本体側としては全部テストはできないから妥協が必要だが、ユーザー目線からみるとアプリのバグと見えるのでツライところ。

2. シェアアイテムが全て使われるとはかぎらない

アプリ本体側は、Image, Text, URLなど、シェアしたいアイテム を渡すが、それをどう使われるかはExtension次第。

たとえば、Facebookの場合、ImageとTextの両方を渡すと、Imageのみになる。
(現在の v143.0ではそうなるが、少し前のバージョンだとImageも認識されなかった)

FacebookはそもそもアプリからデフォルトのTextを入れてはダメというポリシーがあるようなので、Textは渡せない(渡さない)と考えたほうが吉。
ちなみに、Hashtag (ex. #Standland) はいけるようだ。

3. Extensionのアプリバージョンによって挙動がかわる

まぁ当たり前ではあるのですが、そういうものです。
言い換えると、実装したタイミングでは動いていたのに、今みたら動いていない...ということがあるということ。

iOS11のリリース直後はTwitterで画像のシェアができなくなった。
すぐTwitterのアプリをアップデートしてくれたので今はiOS11でできるようになったが、iOS10だと画像シェアできないようだ。 (Twitter v7.8)


4. iOS10のTwitter, Facebookはアプリ有無によって挙動がかわる

iOS10以前には、iPhone本体でTwitter, Facebookのアカウント管理機能があった(SocialFramework)。
そのため、アプリをインストールしていなくてもActivityViewControllerには表示され、シェアが可能。(これはiOS11で消滅)
つまり、iOS10で動作確認する際は、アプリインストール有無で挙動が変わるということを知っておくのが大事。



いろいろ気をつける注意するべき点はあるものの、UIActivityViewController + Extensionの仕組みはとてもいいものだと思う。

これがなければ、アプリに「他アプリへの連携機能」を付けてもらうしか無い。
マイナーアプリの場合は、連携機能を期待するのも難しいであろうし。

その代わり、使う方(本体アプリ)も、使われる方(Extension)も、正しい理解と実装をして、新しいOSにも対応し続けていかないといけない。

もし私が受託開発を請け負っている身だったら、あまり理解してもらえないようなお客さんの場合は、使うのはためらうかも...。



• • •