- PVSM.RU - https://www.pvsm.ru -
Добрый вечер!
Всё началось с того, что необходим был более или менее удобный инструмент для работы с API социальной сети ВКонтакте под iOS. Однако Google меня достаточно быстро расстроил результатами поиска:
Вроде бы всё хорошо, самое главное есть, но вот использование не вызывает приятных ощущений.
Под катом я расскажу, как работает обновленная версия ВКонтакте iOS SDK v2, с чего всё начиналось и к чему в итоге пришли.
Вторая версия кардинально отличается от первой [3] и той [4], которая интегрирована в ASASocialServices [5].
Для того, чтобы лучше понять, что же изменилось после выхода первой версии, надо понять в чем были основные особенности/недостатки первой версии:
Во второй версии многие недостатки, а точнее все, были устранены (возможно появились новые, но и их мы со временем постараемся исправить и устранить) и теперь есть следующие возможности/фичи в SDK:
Из планов на будущее можно выделить следующие пункты:
Хранилище (VKStorage) задумывалось, как некий пункт управления данными авторизованных пользователей.
Хранилище может выполнять следующие действия:
Хранилище состоит из объектов хранилища — VKStorageItem, который является не более, чем объектом содержащим два поля — пользовательский токен доступа и объект кэша.
Для инициализации объекта хранилища достаточно указать пользовательский токен доступа и основную директорию для кэша (не конкретно для данного пользователя, а вообще).
Токены доступа хранилище хранит в NSUserDefaults, а вот данные кэша в NSCachesDirectory.
Интерфейс [6] класса VKStorage.
Чаще обращайтесь к документации, если возникают какие-то вопросы или вы в чем-то сомневаетесь:

При реализации механизма кэширования запросов хотелось получить нечто удобное, простое и гибкое.
За кэширование пользовательских запросов отвечает класс VKCachedData.
Экземпляр класса инициализируется директорией в которой будут храниться кэши запросов (в данном случае путь к директории должен быть уникальным для каждого пользователя).
Какие действия можно осуществлять:
typedef enum
{
VKCachedDataLiveTimeNever = 0,
VKCachedDataLiveTimeOneMinute = 60,
VKCachedDataLiveTimeThreeMinutes = 3 * 60,
VKCachedDataLiveTimeFiveMinutes = 5 * 60,
VKCachedDataLiveTimeOneHour = 1 * 60 * 60,
VKCachedDataLiveTimeFiveHours = 5 * 60 * 60,
VKCachedDataLiveTimeOneDay = 24 * 60 * 60,
VKCachedDataLiveTimeOneWeek = 7 * 24 * 60 * 60,
VKCachedDataLiveTimeOneMonth = 30 * 7 * 24 * 60 * 60,
VKCachedDataLiveTimeOneYear = 365 * 30 * 7 * 24 * 60 * 60,
} VKCachedDataLiveTime;
По умолчанию для всех запросов время жизни кэша составляет один час.
NSURL NSURL (обрабатывать возвращаемые данные можно в стандартном режиме, либо в оффлайн режиме)При разработке столкнулся со следующей проблемой: если при каждой новой авторизации пользователь будет обновлять свой токен доступа, то каждый раз кэш запроса будет храниться под другим именем (имя кэша представляет собой MD5 хэш строки запроса), хотя логически-то запрос один и то же, а следовательно при повторном вызове данные будут перезаписываться или заново запрашиваться из сети.
Решение оказалось в исключение токен доступа из NSURL при сохранении данных в кэш. Таким образом одинаковые запросы, но с разными пользовательскими токенами доступа будут иметь один файл кэша.
Теперь опишу о том, зачем и почему была введена фича offlineMove (оффлайн режим запросов): представил себе обычную ситуацию, когда отсутствует сеть, но данные в кэше есть, а значит их надо вернуть, чтобы не вводить какие-то дополнительные сообщения об ошибках или простого возврата nil. Особенностью оффлайн режима является тот факт, что даже если запрошенные данные кэша и устарели (их время жизни истекло), то они будут возвращены и не произойдет их удаления до тех пор, пока не появиться сеть и очередной такой же запрос не обновит данные.
Если нет надобности использовать кэширование запросов, то устанавливайте время жизни кэша запроса в VKCachedDataLiveTimeNever.
Каждый запрос содержит поле cacheLiveTime, которое является временем жизни кэша данных только текущего запроса. По умолчанию время жизни кэша данных устанавливается равным одному часу.
Как такового, отдельного метода для кэширования изображений/аудио/видео нет, но это легко обойти следующим образом (покажем на примере):
NSUInteger currentUserID = [VKUser currentUser].accessToken.userID;
VKStorageItem *item = [[VKStorage sharedStorage]
storageItemForUserID:currentUserID];
NSString *mp3Link = @"https://mp3.vk.com/music/pop/j-lo.mp3";
NSURL *mp3URL = [NSURL URLWithString:mp3Link];
NSData *mp3Data = //mp3 data from request
[item.cachedData addCachedData:mp3Data
forURL:mp3URL
liveTime:VKCachedDataLiveTimeOneMonth];
Указанный трек будет храниться в течение недели, либо пока система не очистить папку кэша за надобностью свободного места, либо вы сами этого не сделаете.
Основная роль VKConnector заключается в получении пользовательского токена доступа и его сохранение в хранилище.
Запустить процесс получения пользовательского токена доступа можно следующим образом:
[[VKConnector sharedInstance] startWithAppID:@"12345" permissions:@[@"friends", @"wall", @"groups"]];
После вызова данного метода перед пользователем появится такое вот окно авторизации:

После того, как пользователь введет свои данные и нажмет «Войти»:

Окно исчезнет с плавной анимацией.
Видео [7] пользовательской авторизации.
Коннектор позволяет произвести логаут последнего авторизовавшегося пользователя методом logout.
VKConnector позволяет программисту следить за тем на каком этапе сейчас авторизация пользователя, будет ли отображено окно авторизации, будет ли окно скрыто, удалось ли обновить токен доступа или нет, устарел ли токен доступа или нет и тд. Для получения подробной информации смотрите VKConnectorDelegate.
Так же стоит отметить, что при повторной авторизации пользователя его локальный токен доступа (находящийся в хранилище) обновляется и сохраняется для осуществления дальнейших запросов.
Запросы являются на мой взгляд самым интересным реализованным классом (после кэша данных :) ).
В целом они позволяют осуществлять запросы не только к социальной сети ВКонтакте (нет жесткой привязки), но так же не исключают удобные методы для работы именно с этой социальной сетью:
- (instancetype)initWithMethod:(NSString *)methodName
options:(NSDictionary *)options;
Описание метода можно найти в документации.
Запросы являются асинхронными и работают с делегатами. Делегаты должны соответствовать протоколу VKRequestDelegate в котором лишь один метод является обязательным — метод обработки ответа сервера.
В качестве опциональных методов являются:
У каждого запроса есть несколько очень полезных свойств:
Рассмотрим каждое свойство подробней:
VKUser, что каждый запрос подписан строкой селектора вызвавшего его метода.VKCachedDataLiveTimeOneYear).offlineMode)При создании запроса его выполнение начинается не сразу, а после вызова start.
Рассмотрим на примере:
VKRequest *infoRequest = [VKRequest requestMethod:@"users.get" options:@{} delegate:self];
//возможная настройка свойств
infoRequest.cacheLiveTime = VKCachedDataLiveTimeOneMonth;
infoRequest.signature = @"Some signature string";
//какие-то действия
[infoRequest start]; // запрос стартовал
Вы спокойно можете отметить запрос, если у вас есть переменная, которая на него ссылается, либо отменить в одном из методов делегата VKRequestDelegate.
Пример:
[infoRequest start]; // запрос стартовал
// какие-то действия
// надо отменить запрос
[infoRequest cancel];
Самым расширенным методом является:
+ (instancetype)requestHTTPMethod:(NSString *)httpMethod
URL:(NSURL *)url
headers:(NSDictionary *)headers
body:(NSData *)body
delegate:(id <VKRequestDelegate>)delegate;
Как видите данный метод позволяет настроит запрос к серверу с максимальным числом значимых параметров.
Может быть полезен при реализации загрузок аудио/видео на сервер.
Вот так выглядит описание запроса (пример) возвращаемое методом description:
{
cacheLiveTime = 3600;
delegate = "<ASAAppDelegate: 0x752c540>";
offlineMode = NO;
request = "<NSMutableURLRequest https://api.vk.com/method/users.getFollowers>";
signature = "followersWithCustomOptions:";
}
Пользовательский класс позволяет осуществлять запросы от лица текущего активного пользователя.
Рассмотрим несколько методов класса, которые играют важную роль при работе с несколькими пользователями в приложении:
+ (instancetype)currentUser+ (BOOL)activateUserWithID:(NSUInteger)userID + (NSArray *)localUsers Рассмотрим подробнее.
+ (instancetype)currentUser
+ (BOOL)activateUserWithID:(NSUInteger)userID + (NSArray *)localUsersТеперь поговорим о свойствах, которые тоже играют важную роль в том, как будут обрабатываться результаты запросов и сами запросы.
По умолчанию все запросы начинают своё выполнение немедленно после вызова метода в котором они были созданы. Для того, чтобы получить управление над стартом/отменой выполнением запросов необходимо поступить следующим образом:
[VKUser currentUser].startAllRequestsImmediately = NO; // работает для всех последующих запросов, а не только для одного
VKRequest *infoRequest = [[VKUser currentUser] infoWithCustomOptions:@{@"uids": @"1"}];
// какие-то действия
[infoRequest start];
Если хотите только одним запросом управлять, то можно поступить следующим образом:
[VKUser currentUser].startAllRequestsImmediately = NO;
VKRequest *infoRequest = [[VKUser currentUser] infoWithCustomOptions:@{....}];
[VKUser currentUser].startAllRequestsImmediately = YES;
//какие-то действия
[[VKUser currentUser] groupsJoinWithCustomOptions:@{...}]; // выполнение запроса стартует немедленно
Позволяет осуществлять все последующие запросы в оффлайн режиме, режиме, когда данные кэша не удаляются даже в случае истечения их срока жизни.
Пример получения пользователей находящихся в определенной группе:
[VKUser currentUser].delegate = self;
[[VKUser currentUser] groupsGetMembersWithCustomOptions:@{
@"group_id": @"1",
@"count" : @"100",
@"offset": @"0"
}];
Документацию я всегда стараюсь поддерживать в актуальном состоянии и писать о возможных особенностях использования классов, методов, свойств.
Считаю, что без хорошей документации у программиста не будет особого желания разбираться в чужом коде и вообще использовать SDK.
Несколько скриншотов текущей документации, которые отразят всю её полноту и целостность:




Статья, как мне кажется, получилась достаточно длинной, так что на этом пока остановлюсь. Упомянул о многом и старался описывать таким образом, чтобы у Вас сложилось целостная картина.
Хочу отметить, что проект активно развивается и поддерживается.
Найти самую актуальную версию можно по этой ссылке: GitHub ( github.com/AndrewShmig/Vkontakte-iOS-SDK-v2.0 [8] )
Автор: AndrewShmig
Источник [9]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/ios/38133
Ссылки в тексте:
[1] StonewHawk — GitHub: https://github.com/StonerHawk/Vkontakte-iOS-SDK
[2] maiorov/VKAPI — GitHub: https://github.com/maiorov/VKAPI
[3] AndrewShmig/Vkontakte-iOS-SDK: https://github.com/AndrewShmig/Vkontakte-iOS-SDK
[4] той: https://github.com/AndrewShmig/ASASocialServices)
[5] ASASocialServices: https://github.com/AndrewShmig/ASASocialServices
[6] Интерфейс: https://github.com/AndrewShmig/Vkontakte-iOS-SDK-v2.0/blob/master/Project/Vkontakte-iOS-SDK-v2.0/VKStorage/VKStorage.h
[7] Видео: http://www.youtube.com/watch?v=Amod8ZwPiRY&feature=youtu.be
[8] github.com/AndrewShmig/Vkontakte-iOS-SDK-v2.0: https://github.com/AndrewShmig/Vkontakte-iOS-SDK-v2.0
[9] Источник: http://habrahabr.ru/post/185766/
Нажмите здесь для печати.