Записки Junior-а: Extension Today in iOS 8

Записки Junior-а: Extension Today in iOS 8

Всем привет. С выходом версии iOS 8 компания Apple анонсировала свыше 4 000 новых API. Среди множества «вкусностей» я обратил свое внимание на технологию Extensions (расширения).

Ознакомившись в Интернете с целой горой материалов о новой фиче, мне захотелось на практике применить полученные знания — так сказать, совместить приятное с полезным.

Площадкой для эксперимента я выбрал одно из наших новых мобильных приложений, KeepSnap, которое в данный момент находится в iTunes Connect на стадии проверки и публикации в Apple App Store.

Было решено немного расширить функционал уже созданного приложения за счет задействования Extension Today (другими словами, виджета). Последний используется для предоставления мгновенной информации в Notification Center (Центр Уведомлений). В моем случае, это или быстрый переход фотографа на форму авторизации, или отображение его текущего баланса о проданных фотографиях и активности сервиса геолокации.

После согласования алгоритма работы и создания дизайн-макета будущего сообщения я приступил к работе.

Записки Junior-а: Extension Today in iOS 8

Записки Junior-а: Extension Today in iOS 8

Именно здесь начинается все самое интересное. Как оказалось, для реализации этой возможности мне предстояло решить несколько задач‚ вот некоторые из них:

  1. Как данные передаются между основным приложением и его виджетом?
  2. Как сообщить основному приложению о событиях, произошедших в виджете?
  3. Как перейти в нужное представление (страницу) внутри основного приложения по нажатию кнопки на виджете?
  4. Как запустить на выполнение основное приложение, находящееся в фоновом режиме?

Самым простым заданием было размещение готового виджета в Центре Уведомлений. Настроить отображение виджета можно следующим образом: установить приложение на свой смартфон, открыть Центр Уведомлений, перейти на закладку Today (Сегодня), в нижней части которого найти и нажать кнопку Edit (Изменить). Из списка предлагаемых к отображению виджетов выбрать нужный, нажав на кнопку в виде зеленого плюса.

Записки Junior-а: Extension Today in iOS 8

В данном представлении можно удалять виджеты, а также менять порядок их отображения. Нажав на кнопку Ready (Готово) мы увидим наш виджет среди других, установленных на iPhone.

Чтобы воплотить дизайн-макет своего виджета в работающее приложение, я из готового шаблона Xcode 6 создал виджет Today и приступил к его оформлению в Storyboard. Шаблон автоматически создает UIViewController и визуальное представление будущего виджета. Дальнейшая работа сводится к оперированию стандартными объектами Interface Builder-а и созданию ссылок в виде IBOutlets и IBAcions для отображения вносимых изменений, а также обработке прикосновений пользователя к экрану в местах расположения активных элементов (кнопок).

Чтобы ответить на вопрос о том, как данные передаются между основным процессом и виджетом (отдельный процесс), нужно вспомнить о классе NSUserDefaults и применить его с небольшой модификацией под нашу задачу. Для начала необходимо освоить еще одну фичу iOS 8 под названием App Group.

Записки Junior-а: Extension Today in iOS 8

Указанная технология позволяет объединять в группы приложения, созданные при помощи одноименного сертификата разработчика. Внутри группы такие приложения могут обмениваться данными даже в случае неактивности одного из них. В 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.

Записки Junior-а: Extension Today in iOS 8

При обработке события 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. Буду рад в будущем поделиться с вами своим новым опытом в реализации остальных типов расширений.