anz blog

NSExtensionActivationRuleを勘違いしていた

2018-12-27 #Swift

ざっくりまとめ。

  • Share Extension の NSExtensionActivationRule を勘違いしていた
    • NSExtensionActivationSupportsText を false にしたときにサポートしないだけでアプリ自体は表示されると思っていた
  • 仕様上いらないものでも受け入れられるように設定しておくほうが良いかもしれない

です。

ある日問い合わせが来た

僕が出しているアプリでツイートスクラップというものがあるのだけれど、
そこにお問い合わせがきました。
ざっくりまとめると

Tweetbot をつかっていると共有メニューにツイクラでてこないです...

という感じ。
初めに受け取ったときは、あー「…」からツイクラを登録してくれないと出ないのでソレかな?とかおもったのだけれど、どもそうではない
(「…」タップで展開されるアプリリストにもいない)

調査する

plist

自分の場合、Share Extension でこの様に設定していたのだけれど、
これで問題になってくるのが
NSExtensionActivationSupportsText を false にしているところです。
どうやら Tweetbot は UIActivityController を呼び出す時に、
URL と Text を設定しているのだと思いますが。。。
僕は Text をサポートしていないと設定しているので、リストにアプリすら出てこなかったみたいです。

この設定の挙動を完全に勘違いしていて、
false に設定したら、Text は要らないというだけで、呼び出すときに Text を渡されても無視して URL だけ受け付けて呼び出されるのだろう...
とか思っていたのですが、全然そうではなかったということでした。

実際に検証してみました

let text = "Share!!!!!"
let url = URL(string: "https://blog.anzfactory.xyz")!
let items = [url]  // ①
// let items = [text, url] // ②
let vc = UIActivityViewController(activityItems: [url], applicationActivities: nil)
present(vc, animated: true, completion: nil)

NSExtensionActivationSupportsText を false にしていると
①の場合はちゃんとアプリリストに表示されるのですが、
②のようにサポートしていないものが渡されるとアプリリストに表示されなくなるのです。
ここを僕は、アプリリストには表示されるけど実際に呼び出した時に、Text は渡されずに、URL だけ渡されて共有画面が起動されるものかと...

そんなよしなにはやってくれないということですね(笑)

対応

ということで、対応は簡単で
NSExtensionActivationSupportsText を true にしてあげるとちゃんと表示されるようになります。

ただ僕のアプリとしては都合が悪い

使ってみた事があったり、ちょっと見てもらえるとわかりますが、
僕のアプリだと、共有画面が、登録するときの自分なりのメモだったり、タグというものを自分で入力するところなので、
ツイートのテキストが渡ってきてそれがデフォルトで表示されていると、割と都合がわるいのです。
けれど、NSExtensionActivationSupportsText を false にするとアプリ自体が表示されなくなってしまう。。
ということで、無理やり Text をクリアするようにしてお茶を濁しました

class ShareViewController: SLComposeServiceViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Text が渡ってきても表示はしないようにクリアする
        textView.text = ""
    }
}

なんだかイケてない感がありますが...これで Text を渡された状態で呼び出されても、実際の共有画面には何も表示されない状態で始めることが出来ました

蛇足

isContentValid() -> Bool をオーバーライドして、投稿が出来るか出来ないかっていう状態変化をやっていくことができますが、
ここで false を返すとたしかに投稿はできなくなるのですが、
TextView 自体にはフォーカスがあたってしまうのです。
これが、気持ち悪くて、textView.isEditable = false とか設定すると、
シミュでは何事もなかったのですが、実機だと共有画面が開かれずに、呼び元のアプリ側で何も操作できなくなってしまいました。
(見えない透明な View が Screen を覆っている様な感じになる)