Xcod11&iOS13のUIActivityViewControllerのプレビュー画面の挙動が実装方法によって異なる
ざっくりまとめ。
iOS 13から UIActivityViewController
が少し変わって、プレビュー画面ができていい感じになったと。
確認してみると意外なところで挙動に差異が生じるのを発見しました(笑)
どうやら UIActivityViewController
に String
などを直接渡していると場合と、
UIActivityItemSource
プロトコルに準拠した物を渡している場合で挙動がかわります。
iOS 13 からは LPLinkMetadata
をつかってプレビュー画面のカスタマイズができるようになるので、後者の方法で実装しておくといいかもしれません。
環境
- Xcode v11.2.1
問題
iOS 13 から UIActivityViewController
をつかって何かしらシェアする時のプレビュー画面がいい感じになった(リッチになった?)という話をきいて
いくつかアプリを確認してみるとなにか挙動が違うアプリがあったのです。
テキストとURLで同じようなセットで利用しているにも関わらず、
とあるプリはテキストとテキストアイコンのようなもの表示している
また別のものでは、URLのOGPからの情報を表示している
という感じで同じ情報を渡しているにもかかわらず挙動に違いがあると。。。
テキストアイコンとテキストが表示される場合
OGPが表示されてる場合
どっちも渡しているとのはStringとURLなのだけれど。
対応
どちらもStringとURLを設定しているにもかかわらずなぜ挙動が違うのだろう?🤔
見比べたら違いは一目瞭然でした(笑)
どうやら、UIActiivtyItemSource
に準拠したものをアイテムとして渡している場合と String
などを直接渡している場合で挙動が変わってくるようでした。
class ViewController {
func share() {
let shareText = "シェアてきすとだよー"
let shareUrl = URL(string: "https://blog.anzfactory.xyz")!
let activityVC = UIActivityViewController(activityItems: [shareText, shareUrl], applicationActivities: nil)
present(activityVC, animated: true, completion: nil)
}
}
こういう感じで String
なんかを直接渡しているとテキストアイコンとテキストが表示されるパターンになります。
そして下記のように UIActiivtyItemSource
に準拠したものを渡すとOGPからの情報が表示されるパターンになります。
class ViewController {
func share() {
let shareText = ShareItem("シェアてきすとだよー")
let shareUrl = ShareItem(URL(string: "https://blog.anzfactory.xyz")!)
let activityVC = UIActivityViewController(activityItems: [shareText, shareUrl], applicationActivities: nil)
present(activityVC, animated: true, completion: nil)
}
}
class ShareItem<T>: NSObject, UIActivityItemSource {
private let item: T
init(_ item: T) {
self.item = item
}
func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any {
return item
}
func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivity.ActivityType?) -> Any? {
return activityViewControllerPlaceholderItem(activityViewController)
}
}
補足
この挙動に気づいたことは実は別にやりたいことがあったからで、
iOS 13からプレビュー画面ができてそれが編集可能だというのをしってそれで遊んでみようとごにょごにょしていたところ気づいたというわけです。
上記の例だとOGPの情報を良い感じに表示していますが、これらを変更できるというわけです。
class ShareItem<T>: NSObject, UIActivityItemSource {
private let item: T
init(_ item: T) {
self.item = item
}
func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any {
return item
}
func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivity.ActivityType?) -> Any? {
return activityViewControllerPlaceholderItem(activityViewController)
}
@available(iOS 13.0, *)
func activityViewControllerLinkMetadata(_ activityViewController: UIActivityViewController) -> LPLinkMetadata? {
let metadata = LPLinkMetadata()
metadata.title = "シェアする!"
return metadata
}
}
こう書いておくと...こうなります。
ちなみに表示されている画像はアプリアイコンです(こちらも指定可能です)
LPLinkMetadata
は結構癖が強い気がします。
OGP が展開された時のようにサブタイトルのとこに何か指定したいのだけれどできない(originalURL に設定したら表示はされるけど URL に限定されてしまう)とか
Item に紐づくので今回のように複数アイテム渡す場合、もしアイテムごとにことなる情報を持つ metadata を返した時の挙動は確証がもてないとか