Good evening!
It all started with the fact that a more or less convenient tool was needed to work with the VKontakte social networking API for iOS. However, Google quickly upset me with search results:
It seems to be all right, the most important thing is, but the use does not cause pleasant sensations.
Under the cut, I'll tell you how the updated version of the VKontakte iOS SDK v2 works, how it all began and what they finally came to.
')
Introduction
The description of the first version of Vkontakte iOS SDK on Habré can be found at
this link.
The second version is fundamentally different from the
first and the
one that is integrated into
ASASocialServices .
In order to better understand what has changed since the release of the first version, you need to understand what were the main features / disadvantages of the first version:
- Lack of ability to cache requests
- Requests were made simultaneously
- No status of uploading files to the VC server
- The inability to work with multiple users (meaning storing and reusing authorization data such as an access token)
- It was not possible to log out of the current authorized user account.
In the second version, many shortcomings, or rather all, were eliminated (new ones may have appeared, but we will try to fix and fix them over time) and now there are the following features / features in the SDK:
- a repository that allows you to work with multiple users
- caching requests for each user separately
- logout of the last logged in user
- Requests are now separate classes that can be used and customized (there is a connection between the requests and the repository)
- requests are now used by delegates to notify the status of the request (the use of blocks is considered, but no more)
- the ability to track the file upload status on the VC server
- the user is now an object in which all actions that he can perform (join the group, leave a message on the wall, etc.) are encapsulated
- documentation, which in the second version has become better, more complete and in which it will now be possible to find some interesting features in the work of classes / methods
Of the plans for the future, the following points can be distinguished:- The implementation of the class type VKRequest, which will already operate on blocks. The programmer will have the opportunity to select and use either requests + delegates, or requests + blocks.
- Improve the storage and add the ability for the programmer to specify their storage, which will respond to certain mandatory methods of the protocol VKStorageDataDelegate + VKStorageCacheDataDelegate.
- Implement the ability to auto-refresh cache data for specific queries. It may look something like this: in the background, at certain intervals a certain query will be carried out, which, if successful, will update the cache data, thereby speeding up subsequent retrieval of data on this query.
- Storing user cookies to implement automatic login and access token updates.
- Adding another method to VKConnectorDelegate, which will be called when any user actions are necessary (captcha input, data entry during application authorization, etc.)
- ...
Storage
The storage (
VKStorage
) was conceived as a certain item of data management for authorized users.
The repository can perform the following actions:
- Add a new object
- Delete a specific object
- Delete all data
- Delete all cache data
- Get the storage object by the specified user ID (the “keys” in the vault are user unique identifiers)
- Get all the objects that are in the repository
The storage consists of storage objects -
VKStorageItem
, which is nothing more than an object containing two fields - a user access token and a cache object.
To initialize the storage object, it suffices to specify a user access token and the main directory for the cache (not specifically for this user, but in general).
The access tokens are stored in
NSUserDefaults
, but the cache data in
NSCachesDirectory
.
Interface class
VKStorage
.
Contact the documentation more often if you have any questions or you have some doubts:

Data caching
When implementing the query caching mechanism, I wanted to get something convenient, simple and flexible.
VKCachedData
class is responsible for caching user requests.
The class instance is initialized by the directory in which query caches will be stored (in this case, the path to the directory must be unique for each user).
What actions can be performed:
- Add certain data for the specified NSURL to the cache (there were several reasons to use NSURL, not NSURLRequest, and the main reason was the fact that all requests in the VC are made using the GET + method, no additional headers are sent, but POST requests are not cached)
The current view may be subject to review and change. - Add specific data for the specified NSURL to the cache with the specified lifetime.
Possible values ​​of cache lifetime:
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 * 24 * 60 * 60, VKCachedDataLiveTimeOneYear = 365 * 24 * 60 * 60, } VKCachedDataLiveTime;
By default, the cache lifetime for all requests is one hour. - Delete cache for specified
NSURL
- Delete caching directory
- Delete all caches (without deleting the directory in which the data is located)
- Get cached data on the specified
NSURL
(you can process the returned data in standard mode or in offline mode)
When developing, I encountered the following problem: if every time the user logs in, he updates his access token, then the query cache will be stored under a different name each time (the cache name is the MD5 hash of the query string), although the logical query is the same therefore, when you call again, the data will be overwritten or re-requested from the network.
The solution turned out to be an exception to the access token from
NSURL
while saving the data to the cache. Thus, the same requests, but with different user access tokens will have the same cache file.
Now I’ll describe why and why the feature was introduced
offlineMove
(offline query mode): I imagined the usual situation when there is no network, but there is data in the cache, which means they need to be returned so as not to introduce any additional error messages or simple return nil. A feature of offline mode is the fact that even if the requested cache data is outdated (their lifetime has expired), they will be returned and they will not be deleted until the network appears and the next similar query does not update the data.
If there is no need to use query caching, then set the query cache lifetime to
VKCachedDataLiveTimeNever
.
Each request contains a
cacheLiveTime
field, which is the data cache lifetime of
only the current request. By default, the data cache lifetime is set to one hour.
Caching images, audio, video
As such, there is no separate method for image / audio / video caching, but this can be easily circumvented as follows (we will show with an example):
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 =
The specified track will be stored for a week, either until the system clears the cache folder for the need for free space, or you do not do it yourself.
Connector
The main role of
VKConnector
is to get a user access token and save it to the storage.
You can start the process of obtaining a user access token as follows:
[[VKConnector sharedInstance] startWithAppID:@"12345" permissions:@[@"friends", @"wall", @"groups"]];
After calling this method, the following authorization window will appear to the user:

After the user enters his data and clicks "Login":

The window will disappear with smooth animation.
User Authorization
Video .
The connector allows logout of the last logged in user using the
logout
method.
VKConnector
allows the programmer to monitor at what stage the user is currently authorized, whether the authorization window will be displayed, whether the window will be hidden, whether the access token has been updated or not, whether the access token is outdated or not, and so on. See
VKConnectorDelegate
for details.
It is also worth noting that when a user is reauthorized, his local access token (stored in the repository) is updated and saved for further requests.
Requests
Requests are in my opinion the most interesting implemented class (after the data cache :)).
In general, they allow you to make requests not only to the social network VKontakte (there is no hard link), but they also do not exclude convenient methods for working with this social network:
- (instancetype)initWithMethod:(NSString *)methodName options:(NSDictionary *)options;
A description of the method can be found in the documentation.
Requests are
asynchronous and work with delegates. Delegates must comply with the
VKRequestDelegate
protocol in which only one method is required — the server response handling method.
As optional methods are:
- handling the connection error message
- processing error message parsing server response from JSON format to Foundation object
- data load status
- data sending status
Each query has some very useful properties:
- Signature (signature)
- The cache lifetime for the current request (cacheLiveTime)
- Offline request mode (offlineMode)
Consider each property in more detail:
- Signature (signature)
The object signature can be any object, like a dictionary of some related data, or just a string. This was done with the idea that when one class processed several requests (getting friends and personal information about each user), it was necessary to somehow distinguish one request from another. It would be wrong and inconvenient to make the signature fixed, so it was decided to leave the choice of signature on the programmer.
It is worth knowing when making requests from the VKUser
class, each request is signed with a selector string of the method that created it. - The cache lifetime for the current request (cacheLiveTime)
The cache lifetime for a given query is determined by this property. Some data changes very often (news feed, user wall), which means it would be wrong to use aggressive caching and store data as long as possible, but other requests, such as a list of friends of a user, a list of groups, a list of subscribers, etc., can live quietly for a few days in a cache.
If there is a request for no one file / audio recording / video recording, then such things can be stored for a very long time and not changed, so you can use a maximum lifetime of one year for them ( VKCachedDataLiveTimeOneYear
). - Offline request mode (
offlineMode
)
Offline mode directly affects how cache data is returned. In the absence of an Internet connection, it is strongly recommended to use this mode. It will allow you to "extend" the lifetime of the data from the cache, which in standard mode would have to be deleted.
When creating a request, its execution does not begin immediately, but after the
start
call.
Consider an example:
VKRequest *infoRequest = [VKRequest requestMethod:@"users.get" options:@{} delegate:self]; // infoRequest.cacheLiveTime = VKCachedDataLiveTimeOneMonth; infoRequest.signature = @"Some signature string"; //- [infoRequest start]; //
You can safely cancel the request if you have a variable that refers to it, or cancel it in one of the methods of the
VKRequestDelegate
delegate.
Example:
[infoRequest start];
The most advanced method is:
+ (instancetype)requestHTTPMethod:(NSString *)httpMethod URL:(NSURL *)url headers:(NSDictionary *)headers body:(NSData *)body delegate:(id <VKRequestDelegate>)delegate;
As you can see, this method allows you to configure a request to the server with the maximum number of relevant parameters.
It may be useful when implementing audio / video uploads to the server.
Here is the description of the request (example) returned by the
description
method:
{ cacheLiveTime = 3600; delegate = "<ASAAppDelegate: 0x752c540>"; offlineMode = NO; request = "<NSMutableURLRequest https://api.vk.com/method/users.getFollowers>"; signature = "followersWithCustomOptions:"; }
User
The user class allows you to make requests on behalf of the currently active user.
Consider several class methods that play an important role when working with multiple users in an application:
+ (instancetype)currentUser
+ (BOOL)activateUserWithID:(NSUInteger)userID
+ (NSArray *)localUsers
Consider more.
+ (instancetype)currentUser
Getting the current active user. Here is how this method is described in the documentation:

+ (BOOL)activateUserWithID:(NSUInteger)userID
Makes the user with the specified user ID active. A useful method if your application plans to connect multiple user accounts.+ (NSArray *)localUsers
Getting a list of users in the repository. In the array there will be only user identifiers.
Now let's talk about the properties that also play an important role in how the results of the queries and the queries themselves will be processed.
- Start executing queries immediately
By default, all requests begin their execution immediately after calling the method in which they were created. In order to get control over the start / cancellation of the execution of requests, you must do the following:
[VKUser currentUser].startAllRequestsImmediately = NO; // , VKRequest *infoRequest = [[VKUser currentUser] infoWithCustomOptions:@{@"uids": @"1"}]; // - [infoRequest start];
If you want to manage only one request, you can do the following:
[VKUser currentUser].startAllRequestsImmediately = NO; VKRequest *infoRequest = [[VKUser currentUser] infoWithCustomOptions:@{....}]; [VKUser currentUser].startAllRequestsImmediately = YES;
- Offline mode
Allows you to perform all subsequent requests in offline mode, when the cache data is not deleted even if their expiration date has expired.
An example of getting users in a certain group:
[VKUser currentUser].delegate = self; [[VKUser currentUser] groupsGetMembersWithCustomOptions:@{ @"group_id": @"1", @"count" : @"100", @"offset": @"0" }];
Documentation
I always try to keep the documentation up to date and write about the possible features of using classes, methods, properties.
I believe that without good documentation, the programmer will not have much desire to understand someone else's code and generally use the SDK.
Several screenshots of current documentation that reflect its fullness and integrity:




In conclusion
The article, it seems to me, turned out to be quite long, so I’ll stop on this for now. He mentioned many things and tried to describe in such a way that you have a complete picture.
I want to note that the project is actively developing and supported.
Find the most current version at this link: GitHub (
github.com/AndrewShmig/Vkontakte-iOS-SDK-LV )