web-dev-qa-db-fra.com

extension de partage iOS: obtenez l'URL de la page lors du partage via le menu contextuel de Safari

Ce que je veux

J'essaie d'obtenir le flux d'utilisateur suivant:

  1. L'utilisateur navigue sur une page Web dans iOS Safari.
  2. L'utilisateur sélectionne du contenu (texte et images) et attend que le menu contextuel apparaisse.
  3. L'utilisateur sélectionne l'élément "Partager ...".
  4. L'utilisateur sélectionne mon extension d'application dans le menu de partage qui apparaît en bas.
  5. Le contenu sélectionné et l'URL de la page Web sont partagés avec un serveur distant via un appel HTT.

Ce que j'ai essayé

J'ai créé une extension de partage via Xcode. Voici la section NSExtension de mon info.plist:

<key>NSExtension</key>
<dict>
    <key>NSExtensionAttributes</key>
    <dict>
        <key>NSExtensionActivationRule</key>
        <dict>
            <key>NSExtensionActivationSupportsWebPageWithMaxCount</key>
            <integer>1</integer>
            <key>NSExtensionActivationSupportsText</key>
            <true/>
            <key>NSExtensionActivationSupportsWebURLWithMaxCount</key>
            <integer>1</integer>
        </dict>
        <key>NSExtensionJavaScriptPreprocessingFile</key>
        <string>test</string>
    </dict>
    <key>NSExtensionMainStoryboard</key>
    <string>MainInterface</string>
    <key>NSExtensionPointIdentifier</key>
    <string>com.Apple.share-services</string>
</dict>

Voici le fichier test.js:

var GetURL = function() {};
GetURL.prototype = {
run: function(arguments) {
    arguments.completionFunction({"URL": document.URL});
}
};
var ExtensionPreprocessingJS = new GetURL;

Je m'attendais au résultat suivant: dans la méthode viewDidLoad, extensionContext?.inputItems me fournirait plusieurs éléments d'entrée, grâce auxquels je pourrais obtenir le contenu sélectionné et l'adresse Web.

Qu'est-ce qui ne va pas

Dans viewDidLoad, la méthode extensionContext?.inputItems me fournit un seul élément - la représentation en texte brut du contenu sélectionné (même lorsque j'ai sélectionné des images et du texte en même temps). Je peux vivre avec du texte brut, mais j'ai besoin de l'URL de la page Web. 

Ma question

Comment obtenir l'URL de la page Web ouverte lors de l'utilisation d'une extension de partage pour partager le contenu sélectionné via le menu contextuel dans iOS Safari?

13
sbichenko

J'ai passé une bonne partie de l'après-midi embarrassante à lire la documentation à ce sujet et à essayer différentes permutations d'extensions, car je cherchais à faire exactement ce que vous essayiez de faire. 

J'ai conclu que ce flux exact ne peut pas être atteint sur iOS. Si l'utilisateur sélectionne du texte et utilise le menu contextuel (c'est-à-dire "Copier", "Rechercher", "Partager" ...), la seule chose que votre extension recevra jamais est un NSItemProvider avec le texte qu'il a sélectionné. , c’est-à-dire qu’il ne s’agit pas d’un plist avec les résultats du prétraitement javascript. Lorsqu'ils sélectionnent Partager dans ce menu, l'extension s'affiche si et seulement si vous avez défini NSExtensionActivationSupportsText sur YES dans le fichier Info.plist de l'extension. 

Pour exécuter le prétraitement javascript, une extension doit avoir NSExtensionActivationSupportsWebPageWithMaxCount défini sur une valeur supérieure à 0, selon le docs _. Si une extension est appelée via le menu contextuel sélectionné, ce fichier javascript ne s'exécute jamais. 

Cependant, il est possible d'être assez proche du flux souhaité. Si l'utilisateur est dans Safari et qu'il sélectionne du texte, puis au lieu de cliquer sur "Partager" dans le menu contextuel, cliquez sur l'icône Partager en bas de l'interface utilisateur de Safari. La NSItemProvider revient alors sous forme de liste de contrôle et la NSExtensionJavaScriptPreprocessingFile est exécutée. Mon fichier javascript ressemble à ceci:

var Share = function() {};

Share.prototype = {
  run: function(arguments) {
    arguments.completionFunction({"URL": document.URL, "selectedText": document.getSelection().toString()});
  },
  finalize: function(arguments) {
    // alert shared!
  }
};

var ExtensionPreprocessingJS = new Share

ce qui signifie que l'objet plist retourné à l'extension a à la fois l'URL de la page et le selectedText.

Si le seul but d'une extension est les URL de partage, et que le texte brut sans URL n'est pas un cas d'utilisation sensé, vous ne devriez probablement pas avoir NSExtensionActivationSupportsText défini sur YES. Par exemple, une application telle que Pocket l’a activée, mais si un utilisateur sélectionne du texte dans Safari puis essaie de le partager via le menu contextuel, Pocket ne peut rien faire de significatif avec uniquement le texte en clair et aucune URL de page; un message d'erreur assez cryptique.

J'ai _ { publié le code de mon extension } _ ainsi si vous voulez jeter un coup d'œil.

1
apb

Swift 3

Essayez quelque chose comme:

override func didSelectPost() {
    if let item = extensionContext?.inputItems.first as? NSExtensionItem,
        let itemProvider = item.attachments?.first as? NSItemProvider,
        itemProvider.hasItemConformingToTypeIdentifier("public.url") {
        itemProvider.loadItem(forTypeIdentifier: "public.url", options: nil) { (url, error) in
            if let shareURL = url as? URL {
                // do what you want to do with shareURL
            }
            self.extensionContext?.completeRequest(returningItems: [], completionHandler:nil)
        }
    }
}

"public.url" peut être remplacé par la chaîne kUTTypeURL importée de MobileCoreServices

5
Joe