Как передавать данные между iOS-приложениями с помощью URL Schemes
Большинство iOS-разработчиков в курсе, что с помощью URL-схем можно, например, запустить Safari из своего приложения. Однако не все знают, что в разрабатываемом приложении А можно зарегистрировать собственную URL-схему, которая в дальнейшем может использоваться другими приложениями Б или В для вызова приложения А с заданными параметрами.
Зачем это нужно?
URL-схемы являются довольно удобным способом передачи данных в iOS-приложение из, например, другого iOS-приложения, зачастую в весьма специфических ситуациях. Например автору этого блога в определенный момент времени пришлось искать способ передачи параметров одного сложного объекта разрабатываемой системы от одного пользователя мобильного приложения другому пользователю.
Если Вы гадаете, для чего нужно так извращаться, я приведу Вам практический пример. Представьте себе, что Вы разрабатываете мобильную часть сложной клиент-серверной системы, в которой пользователь оперирует некими сложными объектами. Пользователь может создавать, редактировать, удалять эти объекты из мобильного приложения. В определенный момент времени перед Вами возникает задача передачи параметров такого сложного объекта от одного пользователя к другому.
Одним из способов решить данную задачу будет реализовать в мобильном приложении поддержку специальной URL-схемы, и дать пользователям возможность посылать из приложения электронные письма со специально сформированной строкой вида appurlscheme://id
, где appurlscheme://
представляет собой URL-схему, а id
- идентификатор объекта, которым пользователь хочет поделиться с товарищем.
Получатель письма может перейти по этой ссылке (а все это безобразие будет выглядеть как обычная ссылка), только вместо мобильного Safari откроется наше приложение, которое при открытии получит параметр id
и запросит у сервера копию объекта (чтобы не попортить объект отправителя). И дело в шляпе! :)
Как это сделать?
Ниже я приведу пример построения пары приложений, одно из которых будет использовать URL-схему для вызова другого и передачи в него текстовой строки. Используя данный пример нетрудно построить более сложные и практически полезные приложения.
Для реализации всего нижеперечисленного необходимо устройство с iOS для запуска приложений.
Приложение Sender
Данное приложение будет вызывать другое приложение (которое мы назовем Receiver) и передавать в него данные. Создайте новый проект с названием Sender на базе шаблона Single View Application.
Далее приведите h-файл view controller-а к следующему виду:
Далее идем в Interface Builder и создаем на нашем View 3 кнопки и 1 TextField, располагая их примерно так, как на рисунке ниже.
Соединяем необходимые IBAction-ы и IBOutlet (надеюсь, это не составит серьезных затруднений для моих читателей).
После этого необходимо добавить следующий код в m-файл view controller-а:
Ключевыми здесь являются два метода - openURL
и canOpenURL
.
Метод openURL
осуществляет переход непосредственно к контенту, расположенному по передаваемой ссылке.
Метод canOpenURL
проверяет, может ли iOS открыть передаваемую ссылку. Если в качестве URL-схемы будет передана схема, не зарегистрированная в iOS (и отличная, например, от http://
, https://
, ftp://
и т.п.), этот метод вернет NO
.
В случае методов openYoutube:
и openMaps:
в результате выполнения метода openURL
произойдет запуск соответствующих мобильных приложений iOS - YouTube и Maps. Я не буду подробно останавливаться на этих двух методах, как формировать адресную строку для них прекрасно описано в документации Apple.
Про метод openReceiverApp:
поговорим чуть подробнее. В этом методы мы берем введенную пользователем в TextField строку, преобразуем ее к виду валидной строки URL при помощи метода stringByAddingPercentEscapesUsingEncoding:
(в результате этого, например, пробелы заменяются на строку вида %20
), добавляем перед результатом строку receiverapp://
, которая и будет нашей кастомной URL-схемой в данном примере.
После этого мы с помощью метода canOpenURL:
проверяем, может ли iOS запустить приложение Receiver с помощью нашей ссылки. Если может, просто запускаем Receiver. Если не может - выдаем соответствующее сообщение пользователю.
Если запустить полученное приложение на мобильном устройстве и попробовать понажимать на кнопки, мы убедимся, что приложение успешно запускает проигрывание видео в YouTube и отображение объекта по указанным координатам в Maps (см. рис. ниже).
При этом, если прямо сейчас нажать на кнопку запуска приложения Receiver, то мы получим сообщение об ошибке, как на рис. ниже.
когда оно еще не установлено на устройстве
Самое время создать приложение Receiver.
Приложение Receiver
Создайте новый проект с названием Receiver на базе шаблона Single View Application.
Далее нам необходимо зарегистрировать упомянутую нами ранее кастомную url-схему receiverapp://
. Для этого идем в plist-файл проекта и добавляем в нем ключ URL types
, а в нем добавляем ключ URL Schemes
на одном уровне с ключом URL identifier
(см. рис. ниже).
В URL Schemes
добавляем элемент с именем receiverapp
.
Особых изменений в отображаемом view данного приложения я не делал, можно просто добавить на него Label с текстом Receiver.
Далее идем в файл AppDelegate.m и приводим метод application:application didFinishLaunchingWithOptions:
к виду:
При обычном запуске этого приложения (не из приложения Sender!) приложение будет выдавать alert с текстом ошибки. Это сделано исключительно в целях тестирования и в реальном приложении такая функциональность совершенно ни к чему.
Попробуйте запустить полученное приложения Receiver, чтобы убедиться в том, что будет отображаться alert с ошибкой.
Для запуска приложения по ссылке с кастомной URL-схемой нам необходимо добавить в AppDelegate.m метод application:handleOpenURL:
:
Здесь мы извлекаем передаваемый текст из объекта NSURL и отображаем его пользователю.
Теперь можно запустить приложение Sender и из него запустить приложение Receiver.
Заключение
Несколько мыслей по поводу описанного механизма.
-
URL-схему можно использовать не только в нативном приложении, но и в виде обыкновенной html-ссылки вида
<a href="receiverapp://">Открыть объект в приложении Receiver</a>
. -
Не стоит передавать подобным образом между приложениями логины и пароли (да и вообще любые “чувствительные” для пользователя данные). Для этого существует Keychain API.
-
Не нужно использовать URL-схему, если вместо этого можно встроить требуемую функциональность в само приложение. Например вместо того, чтобы открыть координаты в Apple Maps, рассмотрите возможность встроить карты прямо в Ваше приложение. То же самое касается и отображения веб-страниц: вместо вызова Mobile Safari, в некоторых случаях, будет лучше отображать их прямо в самом приложении.
-
Вашей URL-схемой могут воспользоваться и сторонние разработчики для расширения функциональности своих приложений. Перечень существующих URL-схем, используемых в популярных приложениях можно найти, например, вот тут.