Всем доброго времени суток!
Сегодня у меня выдался выходной на работе, который я решил посветить, собственно, рассказу о том, какая новая информация залетела в мою головушку.
Для затравки, хочу сделать небольшую ремарку - тема, которую я попытаюсь сегодня чуточку осветить - очень обширная, поэтому я не стану охватывать необъятное, а опишу то, с чем непосредственно я и столкнулся.
Итак, в чем состояло мое ТЗ - Пользователь запускает Action Extension на какой-либо странице в Safari или другом браузере. Адрес страницы отправляется на back вместе с данными из User Defaults, в ответ получает URL, который тут же открывает.
Итого, проблемы, которые необходимо решить:
Создание самого App Extension
"Присоединение" его к основному приложению
Получение адреса изначально страницы для последующей отправки
Собственно, открытие URL (да, да, у App Extensions с этим есть небольшая заковырка)
Создать App Extension, как бы "удивительно" это не прозвучало, очень просто) В "таргетах" есть специальная кнопка)
![](https://habrastorage.org/getpro/habr/upload_files/ec5/318/3b7/ec53183b7a9e42118a67cef118725049.png)
![](https://habrastorage.org/getpro/habr/upload_files/bfb/cc8/a43/bfbcc8a438bc9511da44b091b58c79a5.png)
И затем перед вами откроется все то многообразие, которое для вас приберегли Купертиновцы) К слову, подробнее о каждом можно узнать из официальной документации. На мой весьма испорченный вкус, там весьма недурно описано каждое из расширений)
Второй этап - коннект приложения с его расширением - это хорошо описано в данной статье под заголовком Обмен Данными: App Groups
Пытаться рассказать об этом лучше я уже не стану, лишь продублирую весь маршрут: через Apple Developer Account создаем AppGroup (да, понадобится аккаунт разработчика), там получаем айди созданной группы, которую указываем в Capabilities у каждого таргета.
Затем, так как в моем ТЗ требовалось использовать те данные, которые хранились в UserDefaults, для правильной работы App Extension нужно было немного поменять синтаксис записи и чтения из UD.
//Запись в основном приложении
UserDefaults.standard.set(self.TTT, forKey: "...")
// TTT - значение, которое нужно записать
//Чтение в основном приложении
let userDefaults = UserDefaults(suiteName: "Ваш group id")
var ZZZ = userDefaults!.string(forKey: "...")
//в ZZZ записываем данные из UD
//Чтение в AppExtension
let userDefaults = UserDefaults(suiteName: "Ваш group id")
let ZZZ = userDefaults!.string(forKey: "...")
//С записью в AppExtension думаю разберетесь)
Третьим этапом в повестке было получение url той страницы, на которой пользователь находился, когда вызвал наше расширение. Для этого нужна некая штуковина, которая называется, если не ошибаюсь, JavaScript Injection.
Простыми словами, для того чтобы AppExtension мог каким-либо образом взаимодействовать с данными, которые находятся на странице, нужно использовать небольшой кусок кода на JS, который жестко регламентируется Apple и, как мне сообщил знакомый разработчик на JS/React - код этот из доисторических времен (ну это так, для общего образования)
Итак, вид этой "инжекции" таков:
var GetURL = function() {};
GetURL.prototype = {
run: function(arguments) {
arguments.completionFunction({ "URL" : document.URL });
},
finalize: function(arguments) {
var message = arguments["statusMessage"];
if (message) {
alert(message);
}
}
};
var ExtensionPreprocessingJS = new GetURL;
В arguments.completionFunction можно получать не только URL, но и другие параметры, к примеру, заголовок страницы. для этого добавим
parameters.completionFunction({"URL": document.URL, "title": document.title });
Теперь для того, чтобы использовать свежеполученный url внутри AppExtension:
self.Pageurl = javaScriptValues["URL"] as String
Затем можно использовать его как вашей душе угодно!)
Остался последний пункт - открытие url) Да, если прошерстить документацию Apple по AppExtensions - вы найдете что-то вроде "Расширения не поддерживают метод open()". Придется выкручиваться, но выкрутас совсем несложный)
func openUrl(url: URL?) {
let selector = sel_registerName("openURL:")
var responder = self as UIResponder?
while let r = responder, !r.responds(to: selector) {
responder = r.next
}
_ = responder?.perform(selector, with: url)
}
Вот, собственно и решение. При помощи данной функции можно, к примеру, открывать основное приложение (через deep linking).
Что же, пожалуй, на этом закончу. Добавлю лишь одно размышление, к которому пришел, пока работал с данной фичей. AppExtensions имеют на самом деле весьма и весьма большой потенциал, но, судя по всему, и Купертиновцы, и рядовые разработчики, как-то подзабили на все что связано с расширениями. Это одновременно и расстраивает, и радует - если у Apple руки когда-нибудь все таки дойдут - скорее всего это будет что-то почти революционное!)
Спасибо и удачи во всех начинаниях!