Записки Junior-а: Extension Today in iOS 8
Всем привет. С выходом версии iOS 8 компания Apple анонсировала свыше 4 000 новых API. Среди множества «вкусностей» я обратил свое внимание на технологию Extensions (расширения).
Ознакомившись в Интернете с целой горой материалов о новой фиче, мне захотелось на практике применить полученные знания — так сказать, совместить приятное с полезным.
Площадкой для эксперимента я выбрал одно из наших новых мобильных приложений, KeepSnap, которое в данный момент находится в iTunes Connect на стадии проверки и публикации в Apple App Store.
Было решено немного расширить функционал уже созданного приложения за счет задействования Extension Today (другими словами, виджета). Последний используется для предоставления мгновенной информации в Notification Center (Центр Уведомлений). В моем случае, это или быстрый переход фотографа на форму авторизации, или отображение его текущего баланса о проданных фотографиях и активности сервиса геолокации.
После согласования алгоритма работы и создания дизайн-макета будущего сообщения я приступил к работе.
Именно здесь начинается все самое интересное. Как оказалось, для реализации этой возможности мне предстояло решить несколько задач‚ вот некоторые из них:
- Как данные передаются между основным приложением и его виджетом?
- Как сообщить основному приложению о событиях, произошедших в виджете?
- Как перейти в нужное представление (страницу) внутри основного приложения по нажатию кнопки на виджете?
- Как запустить на выполнение основное приложение, находящееся в фоновом режиме?
Самым простым заданием было размещение готового виджета в Центре Уведомлений. Настроить отображение виджета можно следующим образом: установить приложение на свой смартфон, открыть Центр Уведомлений, перейти на закладку Today (Сегодня), в нижней части которого найти и нажать кнопку Edit (Изменить). Из списка предлагаемых к отображению виджетов выбрать нужный, нажав на кнопку в виде зеленого плюса.
В данном представлении можно удалять виджеты, а также менять порядок их отображения. Нажав на кнопку Ready (Готово) мы увидим наш виджет среди других, установленных на iPhone.
Чтобы воплотить дизайн-макет своего виджета в работающее приложение, я из готового шаблона Xcode 6 создал виджет Today и приступил к его оформлению в Storyboard. Шаблон автоматически создает UIViewController и визуальное представление будущего виджета. Дальнейшая работа сводится к оперированию стандартными объектами Interface Builder-а и созданию ссылок в виде IBOutlets и IBAcions для отображения вносимых изменений, а также обработке прикосновений пользователя к экрану в местах расположения активных элементов (кнопок).
Чтобы ответить на вопрос о том, как данные передаются между основным процессом и виджетом (отдельный процесс), нужно вспомнить о классе NSUserDefaults и применить его с небольшой модификацией под нашу задачу. Для начала необходимо освоить еще одну фичу iOS 8 под названием App Group.
Указанная технология позволяет объединять в группы приложения, созданные при помощи одноименного сертификата разработчика. Внутри группы такие приложения могут обмениваться данными даже в случае неактивности одного из них. В Target-е KeepSnap я создал группу Зcom.stfalcon.KeepSnap, потом тоже самое повторил для Target-а KeepSnapToday. Теперь Я получил механизм, при помощи которого мои данные могут передаваться между процессами в обе стороны.
В коде добавляю следующие строчки, чтобы прочитать
NSUserDefaults *defaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.stfalcon.Keepsnap"]; NSString *userLogin = [defaults objectForKey:@"userLogin"];
или записать
NSUserDefaults *defaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.stfalcon.Keepsnap"]; [defaults setObject:widgetTaped forKey:kDefaultsWidgetTaped]; [defaults synchronize];
в память устройства данные для обмена.
Аналогичный код использую на стороне основного приложения, чтобы замкнуть цепочку подобных действий.
Чтобы сообщить основному приложению о событиях, произошедших в виджете, необходимо применить технологию локальных уведомлений (класс NSNotifications). Алгоритм моих действий следующий: при нажатии кнопки на виджете через App Group я сохраняю в памяти устройства новое значение переменной, которая должна сообщить основному приложению о произошедшем событии.
Чтобы запустить основное приложение из любого другого приложения или виджета, необходимо настроить параметр URL Types на закладке Info Target-а KeepSnap.
При обработке события IBAction при нажатии на кнопку виджета запускается на обработку следующий код:
NSURL *url = [NSURL URLWithString:@"keepsnap://"]; [self.extensionContext openURL:url completionHandler:nil];
Дальше, в зависимости от состояния моего приложения (не запущено, выполняется, находится в фоновом режиме) создание сервера уведомлений будет происходить или в методе application:openURL:sourceApplication:annotation: объекта AppDelegete, или в методе viewDidLoad класса KSPMainViewController. Если значение переменной из буфера обмена изменилось, формируется рассылка соответствующего уведомления всем объектам, которые подписаны на его получение. Таким образом, основное приложение всегда будет знать о действиях пользователя, совершаемых им на отображении виджета.
При обработке полученного уведомления о том, что пользователь нажал одну из 2-х возможных кнопок на виджете, я вывожу на экран смартфона необходимое визуальное представление — либо форму авторизации (нажатие кнопки Please Sign In), либо форму настроек рабочих параметров для фотографа (нажатие круглой кнопки Geolocation). Дальше пользователь работает в привычном штатном режиме моего приложения :-).
Вот коротко о том, что такое виджеты, зачем они нужны и как их можно реализовать на моем конкретном примере. Мне технология очень понравилась — рекомендую к использованию всем, кто хочет что-то изменить в своем приложении и добавить ему новые возможности. Кстати, это отличный способ выделить свое приложение среди других, установленных на устройстве пользователя. Главное, не нагружать виджет различными вычислениями, ресурсоемкими процессами и зрелищными эффектами. Минимум необходимой информации и соблюдение требований Apple позволят вашему приложению занять свою нишу и выделиться на фоне конкурентов.
Моя статья посвящена одному из 6-ти возможных Extensions — виджету Today. Буду рад в будущем поделиться с вами своим новым опытом в реализации остальных типов расширений.