はじめに
初の個人アプリを App Store に審査出したら 30 分足らずでリリースされてビビったからその全てをお伝えしますの記事を見てShare Extensionいいなぁと思い自分のアプリにもつけてみよう!と思ったのですが色々ハマりました...
対象
- iOS13.0以上
- macOS Catalina
Share Extensionの実装
ここを参考に実装をしました。
Share Extension の追加自体は簡単でした。
ShareViewController
の POST 機能とかいらなかったので参考記事に書いてあったように下記のように修正して画面を作成しました。
- class ShareViewController: SLComposeServiceViewController {
+ class ShareViewController: UIViewController {
画面は下記のようなものでテキストのみ共有するようにしました。(上下に TextView
を置いています。上が共有文字列で下はまだ実装中)

共有メニューに表示されない
なぜか共有メニューにアプリが表示されない時がありました
<key>NSExtensionAttributes</key>
<dict>
<key>NSExtensionActivationRule</key>
<dict>
<key>NSExtensionActivationSupportsText</key>
<true/>
</dict>
</dict>
上記のようにしてると共有メニューに表示されず参考記事のように SUBQUERY にすると表示されるようになりました
<key>NSExtensionActivationRule</key>
<string>SUBQUERY (extensionItems,$extensionItem,
SUBQUERY ($extensionItem.attachments,$attachment,
(ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "public.text"
|| ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "public.plain-text")
).@count == $extensionItem.attachments.@count).@count == 1
</string>
画面が閉じれない
iOS | Mac |
---|---|
![]() |
![]() |
上記のように iOS 版は半モーダルなので下にスワイプすれば閉じれますが Mac 版の場合は閉じることができません
こちらも参考記事に閉じる方法が書いてありました
閉じるボタンを用意して下記のようにすれば閉じることができました
@IBAction private func cancel(_ sender: Any) {
extensionContext!.completeRequest(returningItems: nil, completionHandler: nil)
}
共有メニューのローカライズ
iOS | Mac |
---|---|
![]() |
![]() |
上記のように iOS 版は共有メニューにもアプリのターゲットで設定した Display Name が表示されます(ローカライズも対応)が Mac 版は Share Extension のターゲットで設定した Display Name が表示されています
Share Extension のターゲットに InfoPlist.strings を下記のように追加しました。
CFBundleDisplayName = "DNA Converter"; // (Japaneseの方は "DNA変換" と設定)
これで Mac版 でもアプリ同様共有メニューにも日本語表示なら「DNA変換」英語表記なら「DNA Converter」と表示されるようになりました(どっかに変数を設定してアプリのターゲットと共通化すべきなのかも?)
共有した値が取得できない
致命的なのですが Mac 版で共有した値が取得できませんでした
共有したテキストの取得処理は下記のように実装しました。
let extensionItem: NSExtensionItem = extensionContext?.inputItems.first as! NSExtensionItem
guard let itemProvider = extensionItem.attachments?.first else {
// ここでなんかエラー処理
return
}
let publicText = String(kUTTypeText) // "public.text"
if itemProvider.hasItemConformingToTypeIdentifier(publicText) {
itemProvider.loadItem(forTypeIdentifier: publicText, options: nil, completionHandler: { (data, error) in
guard let text = data as? String else {
// ここでなんかエラー処理
return
}
// ここでなんか処理
})
return
}
let publicPlainText = String(kUTTypePlainText) // "public.plain-text"
if itemProvider.hasItemConformingToTypeIdentifier(publicPlainText) {
itemProvider.loadItem(forTypeIdentifier: publicPlainText, options: nil, completionHandler: { (data, error) in
guard let text = data as? String else {
// ここでなんかエラー処理
return
}
// ここでなんか処理
})
return
}
// ここでなんかエラー処理
iOS では下記のように extensionContext?.inputItems.first
の NSExtensionItemAttachmentsKey
に値が入っているのですが
po extensionContext?.inputItems
▿ Optional<Array<Any>>
▿ some : 1 element
- 0 : <NSExtensionItem: 0x6000007e4260> - userInfo: {
NSExtensionItemAttachmentsKey = (
"<NSItemProvider: 0x600002edc690> {types = (\n \"public.plain-text\"\n)}"
);
NSExtensionItemAttributedContentTextKey = {length = 317, bytes = 0x7b5c7274 66315c61 6e73695c 616e7369 ... 20417070 6c65207d };
"com.apple.UIKit.NSExtensionItemUserInfoIsContentManagedKey" = 0;
}
Mac では下記のように値が入っていません...
po extensionContext?.inputItems
▿ Optional<Array<Any>>
▿ some : 1 element
- 0 : <NSExtensionItem: 0x6000018d45c0> - userInfo: {
NSExtensionItemAttachmentsKey = (
);
NSExtensionItemAttributedContentTextKey = {length = 315, bytes = 0x7b5c7274 66315c61 6e73695c 616e7369 ... 30204170 706c657d };
}
色々試してみましたが Mac 版では値が取得できませんでした。extensionContext?.inputItems.first
の NSExtensionItemAttributedContentTextKey
からがんばれば取得できそうですがなんか違うと思いあきらめました。
ここにきて思ったのが Mac 版だけ動作がおかしいのでそもそも Share Extension が Mac に対応してないんじゃね?という疑惑です。(なんか知ってる人いたら教えて下さい)
ということで私は Mac 版の Share Extension はあきらめました
Mac版で取得できた値(20200211追記)
コメントでURLは取れると聞いたので他の値が取れるかみてみました。
info.plist を下記に設定して extensionContext?.inputItems
をログで出してみました。
<key>NSExtensionAttributes</key>
<dict>
<key>NSExtensionActivationRule</key>
<string>TRUEPREDICATE</string>
</dict>
URL
▿ Optional<Array<Any>>
▿ some : 1 element
- 0 : <NSExtensionItem: 0x6000013e8660> - userInfo: {
NSExtensionItemAttachmentsKey = (
"<NSItemProvider: 0x600003aeddc0> {types = (\n \"public.url\"\n)}",
"<NSItemProvider: 0x600003aedea0> {types = (\n \"public.image\"\n)}"
);
}
Image
▿ Optional<Array<Any>>
▿ some : 1 element
- 0 : <NSExtensionItem: 0x600002034630> - userInfo: {
NSExtensionItemAttachmentsKey = (
"<NSItemProvider: 0x60000092f3a0> {types = (\n \"public.image\"\n)}"
);
}
Movie
▿ Optional<Array<Any>>
▿ some : 1 element
- 0 : <NSExtensionItem: 0x6000013d1ef0> - userInfo: {
NSExtensionItemAttachmentsKey = (
"<NSItemProvider: 0x600003ae0230> {types = (\n \"com.apple.quicktime-movie\",\n \"public.file-url\",\n \"public.url\"\n)}"
);
}
▿ Optional<Array<Any>>
▿ some : 1 element
- 0 : <NSExtensionItem: 0x6000013c54f0> - userInfo: {
NSExtensionItemAttachmentsKey = (
"<NSItemProvider: 0x600003ae43f0> {types = (\n \"public.url\"\n)}",
"<NSItemProvider: 0x600003ae5ff0> {types = (\n \"com.adobe.pdf\"\n)}"
);
}
まとめ
Type | 結果 |
---|---|
text | ![]() |
url | ![]() |
image | ![]() |
movie | ![]() |
![]() |
テキストだけ取れない
さいごに
Mac 版はなにか特殊な設定がいるんでしょうか?調べた限り有力な情報は得られませんでした...
情報求ム!!