Расширение рассылки iOS: получите URL-адрес страницы при совместном использовании через контекстное меню в Safari

Что я хочу

Я пытаюсь выполнить следующий поток пользователей:

  • Пользователь просматривает веб-страницу в Safari iOS.
  • Пользователь выбирает какой-либо контент (текст и изображения) и ожидает появления контекстного меню.
  • Пользователь выбирает элемент "Поделиться...".
  • Пользователь выбирает мое расширение приложения в меню совместного доступа, которое появляется внизу.
  • Выбранный контент и URL-адрес веб-страницы передаются на удаленный сервер через HTT-вызов.

Что я пробовал

Я сделал расширение Share через Xcode. Здесь раздел NSExtension моего 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>

Здесь файл test.js:

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

Я ожидал следующего результата: в viewDidLoad метод extensionContext?.inputItems предоставил мне несколько элементов ввода, через которые я смог бы получить выбранный контент и веб-URL.

Что не так.

В viewDidLoad метод extensionContext?.inputItems предоставляет мне только один элемент - простое текстовое представление выбранного содержимого (даже когда я выбрал изображения и текст одновременно). Я могу жить с открытым текстом, но мне нужен URL-адрес веб-страницы.

Мой вопрос

Как я могу получить URL-адрес открытой веб-страницы при использовании расширения Share для совместного использования выбранного контента через контекстное меню в iOS Safari?

Ответ 1

Я провел довольно сложную часть дня, читая документы по этому поводу, и пробовал разные перестановки расширений, поскольку я искал точно (я думаю), что вы пытались сделать.

Я пришел к выводу, что этот точный поток не может быть достигнут на iOS. Если пользователь выбирает текст и использует контекстное меню (например, "Копировать", "Смотри вверх", "Поделиться"...), единственное, что когда-либо будет получать ваше расширение - это NSItemProvider с текстом, который они выбрали, т.е. а не plist с результатами предварительной обработки javascript. Когда они выбирают "Поделиться" из этого меню, расширение появляется тогда и только тогда, когда вы установили NSExtensionActivationSupportsText в YES в файле расширения Info.plist.

Чтобы запустить javascript предварительной обработки, расширение должно иметь NSExtensionActivationSupportsWebPageWithMaxCount установить значение больше 0, в docs, Если расширение вызывается через выбранное контекстное меню, этот файл javascript никогда не запускается.

Однако можно получить довольно близкое к желаемому потоку. Если пользователь находится в Safari и выбирает какой-то текст, а затем вместо нажатия "Share" в контекстном меню кратковременно нажимает значок "Share" в нижней части пользовательского интерфейса Safari, тогда NSItemProvider возвращается как plist и NSExtensionJavaScriptPreprocessingFile запускается. Мой файл javascript выглядит следующим образом:

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

что означает, что объект plist, возвращаемый в расширение, имеет как URL-адрес страницы, так и выбранный текст.

Если единственной целью расширения является URL-адрес общего доступа, а обычный текст без URL-адреса не является разумным вариантом использования, вы, вероятно, не должны иметь NSExtensionActivationSupportsText, установленный в YES. Например, такое приложение, как Pocket, разрешено, но если пользователь выбирает какой-либо текст в Safari и затем пытается поделиться через контекстное меню, Pocket не может делать ничего значимого только с открытым текстом и без URL-адреса страницы, поэтому он просто появляется вверх довольно загадочное сообщение об ошибке.

Я опубликовал код для моего расширения, если вы хотите посмотреть.

Ответ 2

Swift 3

Попробуйте что-то по строкам:

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" можно заменить на строку kUTTypeURL, импортированную из MobileCoreServices