Share Extensionは、アプリをシステムの共有シートに追加するiOS拡張機能です。ユーザーはSafari、写真、ファイル、その他のアプリからコンテンツをコピーしたりウィンドウを切り替えたりすることなく、直接あなたのアプリに送信できます。Apple(2024)によると、Share Extensionを持つアプリは、共有機能のないアプリよりも35%多くのユーザーコンテンツを受け取ります。この拡張機能は、統一されたNSExtensionItemインターフェースを介してテキスト、画像、動画、URL、ファイルを処理します。
重要なポイント
Share Extensionは、任意のアプリでコンテンツを選択した際にシステムの共有シートに表示されるiOSアプリ拡張機能の一種です。ユーザーがSafariでテキストをハイライトし、共有をタップすると、利用可能なアクションのリストにあなたのアプリが表示されます。選択後、コンテンツは拡張機能に渡されて処理されます:保存、公開、送信、変換など。
Action Extensionとは異なり、Share Extensionは外部アプリからのコンテンツ受信に特化しています。Action Extensionは逆に、アプリから外部へデータを送信します。Share Extensionはユーザーコンテンツのエントリーポイントであり、ユーザー獲得の重要な要素です。ユーザーはShare Extensionを通じてアプリを完全にインストールすることなく試すことができます。App Storeは、Share Extensionを介して広告を表示することのみを目的とするアプリを禁止しています(App Store Review Guideline 4.2)。
Share Extensionは参入障壁を低くします。ユーザーはブラウザ、ギャラリー、ファイルマネージャーといった身近なコンテキストからアプリにコンテンツを送信します。Branch(2024)によると、Share Extensionを持つアプリは7日目のリテンションが28%高いことが示されています。追加の効果としてバイラル性があります。ユーザーが共有シートであなたのアプリを見るたびに、広告費をかけずに受動的なブランディングが行われます。
Share Extensionのメカニズムは、システムのNSExtensionItemコンテナを介したコンテンツ転送に基づいています。ホストアプリ(Safari、写真)は、選択したコンテンツを指定されたタイプ(public.image、public.url、public.plain-text)でNSExtensionItemにパッケージ化します。システムはこのコンテナを拡張機能に渡し、拡張機能はextensionContext.inputItemsを介してデータを抽出します。
Share Extensionは、制限された実行時間(処理に約30秒)で別のプロセスとして実行されます。拡張機能は長時間の同期操作を実行すべきではありません。大きなファイルをアップロードするには、バックグラウンド設定のNSURLSessionを使用します。SLComposeServiceViewControllerは、コンテンツプレビューと投稿ボタンを備えたShare Extensionの基本クラスです。
iOSはUniform Type Identifiers(UTI)を使用して、転送されるコンテンツのタイプを決定します。Share Extensionの主なUTI:public.image(写真、スクリーンショット)、public.url(リンク)、public.plain-text(テキスト)、public.video(動画ファイル)、public.file-url(ファイル)。拡張機能は、NSExtensionActivationRuleキーを介してInfo.plistでサポートされているUTIを登録します。
Share Extensionは、Xcodeのターゲット、SLComposeServiceViewController、Info.plist設定の3つのコンポーネントで構成されています。アーキテクチャは、処理されるコンテンツタイプ、インターフェースの表示方法、データの保存場所を決定します。
| コンポーネント | 目的 | 特徴 |
|---|---|---|
| Target | Xcodeの拡張機能ターゲット | 識別子を持つ個別のバンドル |
| ViewController | インターフェースと処理ロジック | SLComposeServiceViewControllerまたはカスタム |
| Info.plist | アクティベーションとUTIの設定 | 述語を使用したNSExtensionActivationRule |
| App Groups | アプリとの共有ストレージ | データ転送のためのUserDefaultsスイート |
Share Extension設定の重要な要素はアクティベーションルールです。これは、拡張機能が共有シートに表示される条件を決定します。ルールはInfo.plistで制約付きのディクショナリとして設定されます:最大画像数、最小テキスト長、必須URLの有無。標準ルールは、任意の1つのコンテンツタイプに対して拡張機能をアクティブにします。
// Info.plist — Share ExtensionのNSExtensionActivationRule
<key>NSExtensionActivationRule</key>
<dict>
<key>NSExtensionActivationSupportsImageWithMaxCount</key>
<integer>5</integer>
<key>NSExtensionActivationSupportsText</key>
<true/>
<key>NSExtensionActivationSupportsWebURLWithMaxCount</key>
<integer>1</integer>
</dict>
ブックマークアプリ用にSwiftでShare Extensionを作成する実践的な例を見てみましょう。拡張機能はSafariからURLを受け取り、プレビューインターフェースを表示し、リンクをApp Groupに保存します。SLComposeServiceViewControllerは、テキストフィールドと投稿ボタンを備えた既成のUIを提供します。
import Social
import MobileCoreServices
class ShareViewController: SLComposeServiceViewController {
override func isContentValid() -> Bool {
return !(contentText?.isEmpty() ?? true)
}
override func didSelectPost() {
guard let item = extensionContext?.inputItems.first as? NSExtensionItem
else { return }
for attachment in item.attachments ?? [] {
attachment.loadItem(forTypeIdentifier: kUTTypeURL as String) {
[weak self] (item, error) in
if let url = item as? URL {
BookmarkService().save(url, title: self?.contentText)
}
self?.extensionContext?.completeRequest(
returningItems: [], completionHandler: nil)
}
}
}
}
コンテンツ送信後、拡張機能はcompleteRequestを呼び出して終了します。これは必須の手順です。これがないと、システムは拡張機能プロセスを解放しません。重要:Share Extensionは、ネットワークとファイルシステムへのアクセスが制限された限定された環境で実行されます。コンテンツのアップロードにはバックグラウンドセッションを使用してください。
Share Extensionは、テキスト、画像、動画、URL、ファイルなど、さまざまなタイプの入力データを正しく処理する必要があります。各タイプは独自のUTIと抽出メソッドを使用します。ユニバーサル処理 — hasItemConformingToTypeIdentifierチェックを使用してattachment.attachmentsを反復処理します。
画像はpublic.imageとして渡され、UIImageまたはDataを介して取得できます。大きな画像の場合は、保存する前にjpegData(compressionQuality:)を使用します。Share Extensionは、ユーザーの明示的な許可なしに元の画像を変更してはいけません。オリジナルをApp Groupに保存し、インターフェースに表示するプレビューを作成することをお勧めします。
Safariや他のブラウザは、URLをpublic.urlとして、選択したテキストをpublic.plain-textとして渡します。単一のNSExtensionItemには、ページのURLとその上で選択されたテキストの両方のタイプを同時に含めることができます。Share Extensionはすべての添付ファイルをチェックし、関連するデータを抽出する必要があります。複合シナリオ:URLをブックマークとして保存し、テキストをそれに添付されたメモとして保存します。
Share Extensionとメインアプリは異なるプロセスで実行され、ファイルシステムへの共有アクセスはありません。データ交換にはApp Groupsメカニズムを使用します。group.*識別子を持つ共有コンテナです。App Groupにデータを保存した後、拡張機能はCFNotificationCenterまたはDarwin Notifyを介してアプリに通知します。
App GroupsはターゲットのCapabilitiesで有効にします。App Groupsを選択し、識別子を追加します(例:group.com.example.myapp)。メインアプリと拡張機能の両方のターゲットが同じグループにアクセスできる必要があります。UserDefaultsスイートを使用すると、最小限のオーバーヘッドで共有ストレージにデータを読み書きできます。
// Share ExtensionからApp Groupにデータを保存
let sharedDefaults = UserDefaults(suiteName: "group.com.example.myapp")
let bookmark: [String: Any] = [
"url": url.absoluteString,
"title": contentText ?? "",
"date": Date().timeIntervalSince1970
]
sharedDefaults?.set(bookmark, forKey: "bookmark_\(Date().timeIntervalSince1970)")
sharedDefaults?.synchronize()
よくある質問
Share Extensionは他のアプリからあなたのアプリにコンテンツを受け取ります。Action Extensionは逆に、ホストアプリ内でコンテンツに対してアクション(テキスト翻訳、画像修正など)を実行します。Share Extensionは受信、Action Extensionは変換です。
アプリが処理するコンテンツのタイプによって異なります。ブックマークの場合はpublic.url、写真エディタの場合はpublic.image、メモの場合はpublic.plain-textです。複数のタイプの場合は、AND/OR述語を組み合わせたNSExtensionActivationRuleを使用します。
よくある原因は、NSExtensionActivationRuleの誤りまたはUTIの不一致です。Info.plistで確認してください。アクティベーションルールがテストするコンテンツタイプと一致している必要があります。また、設定→アプリ→Siriと検索で拡張機能が有効になっていることを確認してください。Xcodeのクリーンビルドで問題が解決することがよくあります。
システムは実行に約30秒を割り当てます。その後、iOSは強制的に拡張機能プロセスを終了します。長時間の操作には、バックグラウンドのNSURLSessionを使用し、次回のアプリ起動時に結果を処理します。
はい、SLComposeServiceViewControllerの代わりに通常のUIViewControllerを使用できます。この場合、インターフェースを完全に制御できます。ただし、送信ボタンとキャンセルボタンは自分で実装する必要があります。カスタムUIは、標準的でないコンテンツ処理シナリオに推奨されます。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。