[Swift] iOS の共有メニューに追加できるアプリを作る(その 2:HostAppからデータを受け取るまで)

共有メニューに自アプリのExtensionが表示されるようになったので、自アプリExtensionが選択された時にデータを受け取る方法を説明します。
[Swift] iOS の共有メニューに追加できるアプリを作る(その1:共有メニューにアプリが表示されるまで)

何を受け取り可能とするか?:Info.plistの設定

Info.plistで、どのようなデータを受け付け可能とするかを設定します。

Xcodeのテンプレートでは、全てを受け付けるようになっています。


	<key>NSExtension</key>
	<dict>
		<key>NSExtensionAttributes</key>
		<dict>
			<key>IntentsSupported</key>
			<array></array>
			<key>NSExtensionActivationRule</key>
			<string>TRUEPREDICATE</string>        <- 受け付け可能設定
		</dict>
		<key>NSExtensionMainStoryboard</key>
		<string>MainInterface</string>
		<key>NSExtensionPointIdentifier</key>
		<string>com.apple.share-services</string>
	</dict>

Appleのドキュメントの”NSExtensionActivationRule”のセクションを参考に、受け付けたいタイプを設定していきます。

今回は、イメージとWebPageを受け取りたいので、以下を設定します。

  • NSExtensionActivationSupportsImageWithMaxCount
  • NSExtensionActivationSupportsWebPageWithMaxCount
注意
指定するのは、最大受付数なので、TRUE/FALSEを設定するものではありません。

以下のようになります。


		<key>NSExtensionAttributes</key>
		<dict>
			<key>IntentsSupported</key>
			<array></array>
			<key>NSExtensionActivationRule</key>
			<dict>
				<key>NSExtensionActivationSupportsImageWithMaxCount</key>
				<integer>1</integer>
				<key>NSExtensionActivationSupportsWebPageWithMaxCount</key>
				<integer>1</integer>
			</dict>
		</dict>




HostAppからデータを受け取る

Xcodeのテンプレートとして作成されたShareViewControllerで、プロパティ extensionContext 経由でデータを受け取ることができます。

以下は、ShareViewController#didSelectPostに記述したコードです。

コード

    override func didSelectPost() {
        // This is called after the user selects Post. Do the upload of contentText and/or NSExtensionContext attachments.
        let checkItems = self.extensionContext?.inputItems  // ⬅︎ 
    
        // Inform the host that we're done, so it un-blocks its UI. Note: Alternatively you could call super's -didSelectPost, which will similarly complete the extension context.
        self.extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
    }

extensionContent.inputItems は、NSExtensionItem の配列で、このデータが、HostAppから渡されたデータです。

Item の attachements が、NSItemProvider の配列となっています。実データは、この NSItemProvider 経由で受け取ることとなります。

最初に設定した受け付けるタイプの種類と数がこの NSItemProvider とその attachments に反映されます。

異なるタイプの情報を受け取れるようにすると(かつHostApp側から渡そうとすると)複数の NSItemProvider が渡されます。

同一タイプの複数の要素を受け取れるようにすると(例:複数枚の画像)、NSItemProvider の attachments が複数セットされてきます。

また、NSItemProvider#hasItemConformingToTypeIdentifier にて、欲しいタイプの情報を含んでいるか確認することができます。

例えば、画像データを入手したい時には、以下のようにすることで、HostApp側からの情報を取得できます。

コード

    override func didSelectPost() {
        // This is called after the user selects Post. Do the upload of contentText and/or NSExtensionContext attachments.
        guard let checkItems = self.extensionContext?.inputItems else { return }
    
        guard let extensionItem = checkItems[0] as? NSExtensionItem else { return }
        guard let firstItem = extensionItem.attachments?.first! else { return }
        if firstItem.hasItemConformingToTypeIdentifier(String(kUTTypeJPEG)) {
            firstItem.loadItem(forTypeIdentifier: String(kUTTypeJPEG), options: nil) { (item, error) in
                // process item as it is a path to jpeg file
                print("\(item)")
            }
            // Inform the host that we're done, so it un-blocks its UI. Note: Alternatively you could call super's -didSelectPost, which will similarly complete the extension context.
            self.extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
        }
    }

説明は以上です。




HostAppからデータを取得できるようになりましたが、以下の項目の検討も必要です。

  • 自分のアプリとApp Extension でのコード共有
  • App Extension で使えるAPIの確認
[Swift] iOS の共有メニューに追加できるアプリを作る(その3:ContainingApp と App Extensionのデータ共有)




1 COMMENT

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です