Одно из преимуществ Evernote — его вездесущность. Наши приложения работают практически на всех значимых мобильных платформах, на двух наиболее популярных компьютерных ОС и во всех остальных случаях (через веб-интерфейс). Но мы не собираемся останавливаться на этом.
Сейчас все больше и больше мобильных приложений поддерживают возможность чтения и отправки информации в Evernote. Нам это очень нравится, и мы бы хотели, чтобы так продолжалось и дальше — чем больше у вас будет способов получить доступ к своим заметкам, тем лучше (во всяком случае, нам так кажется). Будучи разработчиком, вы получаете выход на 30 с лишним миллионов наших пользователей и можете мгновенно увеличить ценность своего приложения в глазах этих людей, открыв им возможность связи с их внешней “цифровой памятью”.
Мы решили периодически публиковать руководства для разработчиков, которые только начинают осваивать платформу Evernote (или разработку в целом) и хотят интегрировать свои приложения с нашим сервисом.
В этом посте мы опишем конкретные шаги для интеграции Evernote в тестовое приложение iOS. Мы начнем новый проект в Xcode, загрузим и установим Evernote Software Development Kit (SDK) и создадим простое приложение, которое будет взаимодействовать с Evernote через Cloud API.
Прежде чем начать, перечислим, что вам понадобится для самостоятельной работы в дальнейшем:
- аккаунт на сервере sandbox.evernote.com — это сервер-“песочница” Evernote для разработчиков. Он используется для отладки ваших приложений, работащих через Evernote Cloud API. Тестовый аккаунт можно создать здесь.
- ключ Evernote API (Запросить ключ). Ключ API состоит из двух частей: consumer key и consumer secret. (Примечание: Если вы разрабатываете свое собственное приложение, то имейте в виду, что после окончания разработки приложения нужно будет попросить нас включить ваш ключ на основном сервере Evernote. Это можно сделать через форму на dev.evernote.com/support).
- последняя на момент написания версия Xcode — 4.3.2, установленная на Intel Mac.
Все в наличии? Отлично, тогда приступим.
Наше приложение будет делать ровно две вещи: показывать имя текущего пользователя и общее число заметок в его аккаунте.
* Стоит уточнить, что эту идею для приложения мы выбрали совершенно случайно и на момент начала работы не знали, есть ли API для более простого доступа к этой информации*
Закладываем фундамент
Прежде чем мы начнем писать код и впечатлять первых пользователей, нужно подготовить почву — создать проект XCode и установить Evernote SDK для iOS.
Создание проекта XCode
- Запустите XCode и создайте проект, используя меню: File > New > Project.
- Когда вас попросят указать шаблон проекта, выберите “Application” под “iOS” в меню слева и нажмите на “Single View Application”. Затем нажмите “Next”.
- На следующем экране вам нужно будет уточнить несколько характеристик нового приложения:
- В Product Name укажите “EvernoteCounter”.
- Company Identifier может быть произвольный. Это значение используется для идентификации вашего приложения в мире, но поскольку мы не собираемся пускать его дальше своего компьютера, это не имеет значения. В примере мы указали “com.somecompany”.
- Укажите в Class Prefix “EC” (сокращение от “EvernoteCounter”). Эта аббревиатура будет предшествовать всем именам классов, когда мы начнем писать код.
- Укажите в Device Family “iPhone”.
- Убедитесь, что сняты все три флажка.
- Когда вы закончите, поля должны быть заполнены так:
- В конце вас попросят указать место сохранения проекта. Выберите его на свое усмотрение.
Вот и все, ваш проект XCode готов. Отложим его в сторонку на несколько минут. Чтобы наше приложение могло взаимодействовать с Evernote Cloud API, нам понадобится SDK. Давайте добудем его и добавим к проекту.
Загрузка и установка Evernote SDK для iOS
- Все SDK Evernote доступны на Github. Среди них есть и iOS SDK.
- Нажмите на ссылку “Downloads” посередине справа.
- На появившейся странице нажмите “Download as zip”. Вы загрузите текущую версию SDK.
- Разархивируйте файл, и вы увидите каталог вроде этого:
В загруженном каталоге SDK выберите папку evernote-sdk-ios
и перетащите ее в ваш проект XCode:
XCode задаст вам пару вопросов по поводу того, что вы сейчас сделали. Все можно оставить по умолчанию — нажимайте “Finish”.
Evernote SDK для iOS требуется компонент Security.framework
, так что нужно включить его в процесс разработки приложения:
- Нажмите на проект верхнем левом углу окна XCode.
- Нажмите на “Build Phases” в центре верхней части окна.
- Раскройте список “Link Binary With Libraries”, затем нажмите на знак плюса внизу слева.
- В поисковой строке появившегося списка начните вводить “Security”.
- Когда в списке появится
Security.framework
, нажмите на него, чтобы выделить, а затем нажмите “Add”:
Теперь, когда все подготовительные работы завершены, настало время перейти к самому интересному.
Создание приложения
Как уже говорилось, наше приложение должно уметь делать только одну вещь — авторизовать пользователя в его аккаунте Evernote и показать общее число заметок в этом аккаунте.
Прежде чем мы углубимся в корневую функциональность нашего приложения, нужно сконфигурировать его для аутентификации через Evernote Cloud API с помощью OAuth. iOS SDK позволяет реализовать эту связку без проблем за пару минут.
Конфигурирование OAuth
Во-первых, нам нужно модифицировать ECAppDelegate.m
. По умолчанию Xcode автоматически создает для нас метод didFinishLaunchingWithOptions. До внесения изменений этот метод выглядит так:
Нажмите на изображение, чтобы просмотреть этот код на Github
Для того чтобы OAuth заработал, нам нужно создать экземпляр EvernoteSession
с корректным хостом и полномочиями аутентификации. Модифицированный ECAppDelegate.m
будет выглядеть так:
Нажмите на изображение, чтобы просмотреть этот код на Github
EVERNOTE_HOST
— удаленный хост, с которым мы будем взаимодействовать. Пока приложение находится на стадии разработки, нам нужно будет связываться с sandbox.evernote.com, нашим сервером-“песочницей”. Перед выпуском приложения в свет не забудьте заменить EVERNOTE_HOST
на www.evernote.com
и запросить активацию ключа на основном сервере, как мы писали ранее.
CONSUMER_KEY
и CONSUMER_SECRET
— две части ключа API, которые мы ранее получили. Так что вам нужно будет поменять имеющиеся значения параметрами своего реального ключа.
Далее мы инициализируем новый экземпляр EvernoteSession
, затем указываем его свойства: хост, consumerKey
и consumerSecret
. И наконец наша новая переменная сессии назначается singleton-объектом, который будет использоваться каждый раз, когда приложение будет взаимодействовать с Evernote Cloud API.
И еще нам нужно не забыть включить EvernoteSession.h в файл заголовка. Добавьте соответствующее объявление сразу после того, как наш ECViewController.h
будет включен в ECAppDelegate.m
:
Нажмите на изображение, чтобы просмотреть этот код на Github
Поскольку процедура OAuth подразумевает авторизацию наше приложения через веб-страницу, нужно убедиться, что наше приложение может обрабатывать открытые ссылки. К счастью это уже встроено в iOS SDK, и все, что нам нужно сделать — добавить этот метод в конец нашего файла ECAppDelegate.m
(прямо перед end
):
Нажмите на изображение, чтобы просмотреть этот код на Github
Создание пользовательского интерфейса
Теперь можно сделать простой интерфейс для нашего приложения. Нажмите на ECViewController.xib
в левой части. Откроется редактор интерефейса с настройками, расчитанными на экран iPhone. Здесь мы сможем перетаскивать, создавать и настраивать элементы интерфейса: кнопки, текстовые поля и т. д. Для этого приложения нам понадобится пара текстовых полей (одно для имени пользователя в Evernote, другое для числа заметок), подпись для каждого поля и кнопка, по нажатию которой будет запускаться процедура. (Обратите внимание, что текстовые поля должны иметь тип UILabel
, что позволит задавать их значения динамически; подробнее об этом мы расскажем чуть позже).
Перетащите все нужные элементы интерфейса из библиотеки объектов в поле редактора. Когда вы закончите, это должно выглядеть примерно так:
Нам понадобится объявить свойства IBOutlet
и метод IBAction
для обработки нажатий на нашу кнопку. Давайте добавим все это в наш файл ECViewController.h
:
Нажмите на изображение, чтобы просмотреть этот код на Github
Теперь свяжем наши текстовые области значений, которые будут показывать имя пользователя и число заметок с их соответствующими свойствами в ECViewController
(usernameField
и noteCountField
).
- Нажмите на
ECViewController.xib
в обозревателе проекта слева, чтобы открыть наш макет интерфейса. - Затем нажмите правой кнопкой мыши на “File’s Owner” под “Placeholders”, чтобы раскрыть панель связей.
- Нажмите на пустую область справа от
usernameField
и перетащите ее на соответствующую область значений так, как показано здесь: - Выполните то же самое с
noteCountField
.
Теперь надо связать нашу кнопку с методом retrieveUserNameAndNoteCount
, который мы объявили ранее. Для этого, удерживая Control, перетащите кнопку на “File’s Owner”. После того, как вы отпутстите кнопку мыши, выберите в появившемся окне “Sent Events” пункт retrieveUserNameAndNoteCount
.
Теперь у нас есть текстовые поля и кнопка, готовые для выполнения своих задач, и надо провести внутреннюю работу в ECViewController.m
. Вот как этот файл выглядит по умолчанию после того, как его сгенерировал XCode:
Нажмите на изображение, чтобы просмотреть этот код на Github
Чтобы выполнить наши задачи (показать имя пользователя и число заметок в аккаунте), нужно создать два метода.
Первый, разумеется, метод, вызываемый при нажатии на кнопку: retrieveUserNameAndNoteCount
.
Это метод будет:
- обеспечивать аутентификацию с Evernote Cloud API (и показывать сообщение об ошибке, если что-то пойдет не так);
- получать информацию о текущем пользователе в качестве объекта
EDAMUser
. (кстати, “EDAM” расшифровывается как “Evernote Data Access and Management”); - указывать имя пользователя в качестве значения в
usernameField
; - вызывать другой метод для получения числа заметок для данного пользователя.
Вот наш метод в законченном виде:
Нажмите на изображение, чтобы просмотреть этот код на Github
Только не пугайтесь — сейчас мы все это подробно разберем.
Во-первых, мы получаем локальный экземпляр EvernoteSession
(поскольку он является единственным экземпляром (singleton), то будет тем же, что мы создавали в ECAppDelegate.m
). Затем вызываем authenticateWithCompletionHandler
. Этот метод пытается проверить аутентифицировать нашу сессию с Evernote Cloud API (подробнее об этом в разделе про OAuth ниже). В случае ошибки во время аутентификации или же если аутентификация по каким-то причинам не удалась, информация об этом записывается с помощью NSLog и показывается в диалоговом окне (экземпляр UIAlertView
), и о неудачной аутентификации сообщается пользователю.
Если же аутентификация прошла успешно, мы можем перейти к основной логике нашего приложения. Важно помнить, что, как только приложение получит аутентификационный токен, он будет действовать в течение года, затем пользователю вновь придется авторизоваться. Одако, если пользователь решит переустановить ваше приложение, то ему нужно будет авторизоваться повторно.
Во-первых, нужно определить аккаунт, с которым мы работаем. Для этого создаем локальный экземпляр EvernoteUserStore
(userStore
) и вызываем его метод getUserWithSuccess
. Это асинхроннный запрос, который в ответ запрашивает функции, реализованные в виде блоков (по сути, это анонимные функции). Первый блок принимает единый параметр EDAMUser
и сообщает, что запрос прошел успешно. Второй блок (failure
) принимает один экземпляр NSError
, где описывается, что именно пошло не так. При обнаружении ошибки приложение просто регистрирует его и больше ничего не делает.
Если запрос к API прошел успешно, мы запрашиваем у нашего экземпляра EDAMUser
свойство username
и указываем его в качестве значения для usernameField
.
И наконец, мы вызываем наш другой метод countAllNotesAndSetTextField
:
Нажмите на изображение, чтобы просмотреть этот код на Github
Этот метод, о чем красноречиво говорит его название, подсчитывает число заметок в аккаунте и отображает его на экране. Давайте посмотрим, как он работает.
Во-первых, мы объявляем переменную счетчика noteCount
. В этой переменной будет вестись подсчет заметок аккаунта (подробнее об этом далее).
Затем мы создаем локальный экземпляр EvernoteNoteStore
под названием noteStore
. Используя этот объект, мы будем запрашивать у Evernote Cloud API доступ к заметкам, блокнотам и т. д., применяя такие методы как listNotebooksWithSuccess
(который мы вызываем в следующей строке). Поскольку Cloud API не содержит готового способа получения числа всех заметок в аккаунте, нам нужно проделать следующую последовательность действий:
- получить список всех блокнотов в аккаунте пользователя, используя
listNotebooksWithSuccess
; - пройтись по этому списку и для каждого блокнота получить число заметок.
Ответ listNotebooksWithSuccess
, как и getUserWithSuccess
, представляет собой пару блоков. Первый обрабатывает успешный ответ сервера и принимает единственный параметр NSArray
, который содержит коллекцию объектов EDAMNotebook
— по одному для каждого блокнота в аккаунте пользователя.
Каждый из имеющихся у нас объектов EDAMNotebook
содержит уникальный идентификатор блокнота GUID. Используя этот GUID, мы создаем экземпляр EDAMNoteFilter
, которые позволит нам найти заметки, имеющиеся в соответствующем блокноте. И наконец, имея EDAMNoteFilter
в качестве параметра, мы можем вызвать findNoteCountsWithFilter
, чтобы получить число заметок в данном блокноте (как экземпляр объекта EDAMNoteCollectionsCounts
).
Теперь, когда у нас есть число, мы прибавляем его к переменной noteCount
и обновляем noteCountField
на экране. И вот результат:
OAuth
Если сессия не прошла аутентификацию (то есть не получен токен), то при нажатии на кнопку приложение передаст контроль мобильному Safari, где откроется сайт Evernote. Там пользователь должен войти в свой аккаунт Evernote и авторизовать наше приложение для доступа к своему аккаунту.
После того, как пользователь авторизовался, браузер возвращает контроль приложению, и процесс продолжается, как если бы пользователь только что нажал кнопку. Если все прошло удачно, имя пользователя и число его заметок будут показаны на экране, как показано выше.
В заключение
И еще момент, которые стоит отметить: приложение EvernoteCounter создано для того, чтобы показать простоту интеграции и использования нашего iOS SDK. Если бы это было реальное приложение для массового использования, нужно было бы уделить гораздо больше внимания условиям, в которых потенциально могут возникать ошибки и работе над “защитными” программистскими практиками. Однако они были опущены здесь для того, чтобы не усложнять для понимания код тестового приложения.
Весь проект EvernoteCounter для Xcode доступен на Github. Если вы хотите помочь и улучшить код, не стесняйтесь предлагать свои правки (Обратите внимание, что мы не говорим о новой функциональности этого приложения, а лишь о том, чтобы сделать приложение еще более подходящим в качестве учебного пособия.)
Автор: Roberto