QMServices 0.6.2

QMServices 0.6.2

TestsTested
LangLanguage Obj-CObjective C
License BSD-3-Clause
ReleasedLast Release May 2018

Maintained by Andrey ivanov, Vitaliy Gorbachov, Stan Shaforenko, Illia Chemolosov.



 
Depends on:
QuickBlox>= 2.17
Bolts>= 1.9.0
 

  • By
  • Andrey Ivanov, Vitaliy Gorbachov and Vitaliy Gurkovsky

CocoaPods CocoaPods CocoaPods

QMServices

Easy-to-use services for Quickblox SDK, for speeding up development of iOS chat applications.

Features

  • High level API for Chat features including authentication service for logging to Quickblox REST and XMPP
  • Inbox persistent storage for messages, dialogs and users
  • Inbox memory storage for messages, dialogs and users
  • Bolts version of all methods. See [Bolts-iOS](https://github.com/BoltsFramework/Bolts-iOS "Bolts-iOS"") for more information.

Requirements

  • Xcode 6+
  • ARC

Dependencies

Installation

There are several ways to add QMServices to your project. They are described below:

1. Cocoapods

You can install QMServices using Cocoapods just by adding following line in your Podfile:

pod 'QMServices'

2. Using an Xcode subproject

Xcode sub-projects allow your project to use and build QMServices as an implicit dependency.

Add QMServices to your project as a Git submodule:

$ cd MyXcodeProjectFolder
$ git submodule add https://github.com/QuickBlox/q-municate-services-ios.git Vendor/QMServices
$ git commit -m "Added QMServices submodule"

This will add QMServices as a submodule and download Bolts as dependency. Drag Vendor/QMServices/QMServices.xcodeproj into your existing Xcode project.

Navigate to your project's settings, then select the target you wish to add QMServices to.

Navigate to Build Settings, then search for Header Search Paths and double-click it to edit

Add a new item using +: "$(SRCROOT)/Vendor/QMServices" and ensure that it is set to recursive

Navigate to Build Settings, then search for Framework Search Paths and double-click it to edit

Add a new item using +: "$(SRCROOT)/Vendor/QMServices/Frameworks"

** NOTE**

Only for manual installation: if you do not follow the steps below you will get compiler errors that Quickblox.framework and Bolts.framework are not found

Quickblox.framework and Bolts.framework in `"$(SRCROOT)/Vendor/QMServices/Frameworks"` does NOT contain binary data, they used only for generating bundles.
If you plan to use QMServices as sub-project, then
1. Download Quickblox.framework https://github.com/QuickBlox/quickblox-ios-sdk/archive/master.zip
2. Download Bolts.framework https://github.com/BoltsFramework/Bolts-ObjC/releases/download/1.5.1/Bolts-iOS.zip
3. Put the frameworks in the folder 'Vendor/QMServices/Frameworks'

** NOTE**: By default, QMServices subprojects reference Quickblox and Bolts frameworks at ../Frameworks. To change the path, you need to open Quickblox.xcconfig file and replace ../Frameworks with your path to the Quickblox.framework and Bolts.framework.

** NOTE** Please be aware that if you've set Xcode's Link Frameworks Automatically to No then you may need to add the Quickblox.framework, CoreData.framework to your project on iOS, as UIKit does not include Core Data by default. On OS X, Cocoa includes Core Data.

Now navigate to QMServices.xcodeproj subproject, open Build Settings, search for Framework Search Paths and locate Quickblox and Bolts frameworks folder there. Remember, that you have to link QMServices in Target Dependencies and (or) libQMServices.a in Link Binary with Libraries. Don't forget to add Quickblox and Bolts frameworks to your project.

Next step is to copy all bundles into your Copy bundle resources in Build Phases tab of your project settings. Navigate to QMServices.xcodeproj/Cache and move QMUsersCacheModel.bundle, QMContactListCacheModel.bundle and QMChatCacheModel.bundle that are existent in its subprojects to Copy Bundle Resources of your project. In a pop-up window select only "Create folder references".

If you are adding QMServices to the Swift project, you need to import them in your bridging header:

#import "QMServices.h"

To integrate Quckblox iOS SDK into your Swift project see our detailed guide here.

If you are still experiencing some crashes, check if you have set up correct Other linker flags for your project (-lxml2, -ObjC, -lstdc++) otherwise feel free to create an issue and let us know your problem.

Bundle generation

NOTE: You can skip this step if you do not use dialogs, messages and users memory and disc storage.

Bundle allows to pass .xcdatamodel file together with static library so it is required for QMChatCache and QMContactListCache projects.

To generate bundle for contact list you need to open QMServices project, navigate to Cache folder and select QMContactListCache.xcodeproj. Open project folder - you will see red QMContactListCacheModel.bundle. To create it select scheme QMContactListCacheModel and run it. After successful build QMContactListCacheModel.bundle color will change to black and you will be able to copy it to the project that uses QMServices. Include this bundle in your project.

To generate bundle for dialogs and messages you need to open QMServices project, navigate to Cache folder and select QMChatCache.xcodeproj. Open project folder - you will see red QMChatCacheModel.bundle. To create it select scheme QMChatCacheModel and run it. After successful build QMChatCacheModel.bundle` color will change to black and you will be able to copy it to the project that uses QMServices. Include this bundle in your project.

Architecture

QMServices contain:

  • QMAuthService
  • QMChatService
  • QMContactListService
  • QMUsersService

They all inherited from QMBaseService. To support CoreData caching you can use QMContactListCache, QMChatCache and QMUsersCache, which are inherited from QMDBStorage. Of course you could use your own database storage - just need to implement QMChatServiceDelegate, QMContactListServiceDelegate or QMUsersServiceDelegate depending on your needs.

Getting started

Add #import <QMServices.h> to your app's .pch file.

Service Manager

To start using services you could either use existing QMServicesManager class or create a subclass from it. Detailed explanation of the QMServicesManager class is below.

QMServicesManager has 2 functions - user login(login to REST API, chat)/logout(Logging out from chat, REST API, clearing persistent and memory cache) and establishing connection between QMChatCache and QMChatService to enable storing dialogs and messages data on disc.

Here is QMServicesManager.h:

@interface QMServicesManager : NSObject <QMServiceManagerProtocol, QMChatServiceCacheDataSource, QMChatServiceDelegate, QMChatConnectionDelegate>

+ (instancetype)instance;

- (void)logInWithUser:(QBUUser *)user completion:(void (^)(BOOL success, NSString *errorMessage))completion;
- (void)logoutWithCompletion:(dispatch_block_t)completion;

@property (nonatomic, readonly) QMAuthService* authService;
@property (nonatomic, readonly) QMChatService* chatService;

@end

And extension in QMServicesManager.m:

@interface QMServicesManager ()

@property (nonatomic, strong) QMAuthService* authService;
@property (nonatomic, strong) QMChatService* chatService;

@property (nonatomic, strong) dispatch_group_t logoutGroup;

@end

In init method, services and cache are initialised.

- (instancetype)init {
	self = [super init];
	if (self) {
		[QMChatCache setupDBWithStoreNamed:@"sample-cache"];
		[QMChatCache instance].messagesLimitPerDialog = 10;

		_authService = [[QMAuthService alloc] initWithServiceManager:self];
		_chatService = [[QMChatService alloc] initWithServiceManager:self cacheDataSource:self];
		[_chatService addDelegate:self];
		_logoutGroup = dispatch_group_create();
	}
	return self;
}
  • Cache setup (You could skip it if you don't need persistent storage).

    • Initiates Core Data database for dialog and messages:
     [QMChatCache setupDBWithStoreNamed:@"sample-cache"];
  • Services setup

    • Authentication service:
     _authService = [[QMAuthService alloc] initWithServiceManager:self];
    • Chat service (responsible for establishing chat connection and responding to chat events (message, presences and so on)):
     _chatService = [[QMChatService alloc] initWithServiceManager:self cacheDataSource:self];

Also you have to implement QMServiceManagerProtocol methods:

- (void)handleErrorResponse:(QBResponse *)response {
	// handle error response from services here
}

- (BOOL)isAuthorized {
	return self.authService.isAuthorized;
}

- (QBUUser *)currentUser {
	return [QBSession currentSession].currentUser;
}

To implement chat messages and dialogs caching you should implement following methods from QMChatServiceDelegate protocol:

- (void)chatService:(QMChatService *)chatService didAddChatDialogToMemoryStorage:(QBChatDialog *)chatDialog {
	[QMChatCache.instance insertOrUpdateDialog:chatDialog completion:nil];
}

- (void)chatService:(QMChatService *)chatService didAddChatDialogsToMemoryStorage:(NSArray *)chatDialogs {
	[QMChatCache.instance insertOrUpdateDialogs:chatDialogs completion:nil];
}

- (void)chatService:(QMChatService *)chatService didAddMessageToMemoryStorage:(QBChatMessage *)message forDialogID:(NSString *)dialogID {
	[QMChatCache.instance insertOrUpdateMessage:message withDialogId:dialogID completion:nil];
}

- (void)chatService:(QMChatService *)chatService didAddMessagesToMemoryStorage:(NSArray *)messages forDialogID:(NSString *)dialogID {
	[QMChatCache.instance insertOrUpdateMessages:messages withDialogId:dialogID completion:nil];
}

- (void)chatService:(QMChatService *)chatService didDeleteChatDialogWithIDFromMemoryStorage:(NSString *)chatDialogID {
    [QMChatCache.instance deleteDialogWithID:chatDialogID completion:nil];
}

- (void)chatService:(QMChatService *)chatService  didReceiveNotificationMessage:(QBChatMessage *)message createDialog:(QBChatDialog *)dialog {
	[QMChatCache.instance insertOrUpdateMessage:message withDialogId:dialog.ID completion:nil];
	[QMChatCache.instance insertOrUpdateDialog:dialog completion:nil];
}

- (void)chatService:(QMChatService *)chatService didUpdateChatDialogInMemoryStorage:(QBChatDialog *)chatDialog {
    [[QMChatCache instance] insertOrUpdateDialog:chatDialog completion:nil];
}

Also for prefetching initial dialogs and messages you have to implement QMChatServiceCacheDataSource protocol:

- (void)cachedDialogs:(QMCacheCollection)block {
	[QMChatCache.instance dialogsSortedBy:CDDialogAttributes.lastMessageDate ascending:YES completion:^(NSArray *dialogs) {
		block(dialogs);
	}];
}

- (void)cachedMessagesWithDialogID:(NSString *)dialogID block:(QMCacheCollection)block {
	[QMChatCache.instance messagesWithDialogId:dialogID sortedBy:CDMessageAttributes.messageID ascending:YES completion:^(NSArray *array) {
		block(array);
	}];
}

Logs

By default QMServices logging its information in developer console. You may want to disable them (for example for production, logs can slow your app sometimes). In order to do so use QMServicesManager static method:

+ (void)enableLogging:(BOOL)flag;

Just set it, for example, in your AppDelegate class like this:

[QMServicesManager enableLogging:NO];

Authentication

Login

This method logins user to Quickblox REST API backend and to the Quickblox Chat backend. Also it automatically tries to join to all cached group dialogs - to immediately receive incomming messages.

- (void)logInWithUser:(QBUUser *)user
		   completion:(void (^)(BOOL success, NSString *errorMessage))completion
{
	__weak typeof(self) weakSelf = self;
	[self.authService logInWithUser:user completion:^(QBResponse *response, QBUUser *userProfile) {
		if (response.error != nil) {
			if (completion != nil) {
				completion(NO, response.error.error.localizedDescription);
			}
			return;
		}
		
		[weakSelf.chatService connectWithCompletionBlock:^(NSError * _Nullable error) {
            //
            __typeof(self) strongSelf = weakSelf;
            
            [strongSelf.chatService loadCachedDialogsWithCompletion:^{
                NSArray* dialogs = [strongSelf.chatService.dialogsMemoryStorage unsortedDialogs];
                for (QBChatDialog* dialog in dialogs) {
                    if (dialog.type != QBChatDialogTypePrivate) {
                        [strongSelf.chatService joinToGroupDialog:dialog completion:^(NSError * _Nullable error) {
                            //
                            if (error != nil) {
                                NSLog(@"Join error: %@", error.localizedDescription);
                            }
                        }];
                    }
                }
                
                if (completion != nil) {
                    completion(error == nil, error.localizedDescription);
                }
                
            }];
        }];
	}];
}

Example of usage:

    // Logging in to Quickblox REST API and chat.
    [QMServicesManager.instance logInWithUser:selectedUser completion:^(BOOL success, NSString *errorMessage) {
        if (success) {
            // Handle success login
        } else {
            // Handle error with error message
        }
    }];

Logout

- (void)logoutWithCompletion:(dispatch_block_t)completion
{
    if ([QBSession currentSession].currentUser != nil) {
        __weak typeof(self)weakSelf = self;
                
        dispatch_group_enter(self.logoutGroup);
        [self.authService logOut:^(QBResponse *response) {
            __typeof(self) strongSelf = weakSelf;
            [strongSelf.chatService disconnectWithCompletionBlock:nil];
            [strongSelf.chatService free];
            dispatch_group_leave(strongSelf.logoutGroup);
        }];
        
        dispatch_group_enter(self.logoutGroup);
        [[QMChatCache instance] deleteAllDialogsWithCompletion:^{
            __typeof(self) strongSelf = weakSelf;
            dispatch_group_leave(strongSelf.logoutGroup);
        }];
        
        dispatch_group_enter(self.logoutGroup);
        [[QMChatCache instance] deleteAllMessagesWithCompletion:^{
            __typeof(self) strongSelf = weakSelf;
            dispatch_group_leave(strongSelf.logoutGroup);
        }];
        
        dispatch_group_notify(self.logoutGroup, dispatch_get_main_queue(), ^{
            if (completion) {
                completion();
            }
        });
    } else {
        if (completion) {
            completion();
        }
    }
}

Example of usage:

    [[QMServicesManager instance] logoutWithCompletion:^{
        // Handle logout
    }];

Fetching chat dialogs

Load all dialogs from REST API:

Extended request parameters could be taken from http://quickblox.com/developers/SimpleSample-chat_users-ios#Filters.

[QMServicesManager.instance.chatService allDialogsWithPageLimit:100 extendedRequest:nil iterationBlock:^(QBResponse *response, NSArray *dialogObjects, NSSet *dialogsUsersIDs, BOOL *stop) {
	// reload UI, this block is called when page is loaded
} completion:^(QBResponse *response) {
	// loading finished, all dialogs fetched
}];

These dialogs are automatically stored in QMDialogsMemoryStorage class.

Fetching chat messages

Fetching messages from REST API history:

[QMServicesManager instance].chatService messagesWithChatDialogID:@"53fdc87fe4b0f91d92fbb27e" completion:^(QBResponse *response, NSArray *messages) {
	// update UI, handle messages
}];

These message are automatically stored in QMMessagesMemoryStorage class.

Sending message

Send message to dialog:

QBChatMessage *message = [QBChatMessage message];
message.text = @"Awesome text";
message.senderID = 2308497;

[[QMServicesManager instance].chatService sendMessage:message type:QMMessageTypeText toDialogId:@"53fdc87fe4b0f91d92fbb27e" saveToHistory:YES saveToStorage:YES completion:nil];

Message is automatically added to QMMessagesMemoryStorage class.

Fetching users

[[[QMServicesManager instance].usersService getUsersWithIDs:@[@(2308497), @(2308498)]] continueWithBlock:^id(BFTask<NSArray<QBUUser *> *> *task) {
        if (task.error == nil) {
            // handle users
        }
        return nil;
}];

Users are automatically stored in QMUsersMemoryStorage class.

Subclass of QMServicesManager example

This example adds additional functionality - storing of users in contact list cache, error handling, storing currently opened dialog identifier.

Header file:

@interface ServicesManager : QMServicesManager <QMContactListServiceCacheDataSource>

// Replaces with any users service you are already using or going to use
@property (nonatomic, readonly) UsersService* usersService;

@property (nonatomic, strong) NSString* currentDialogID;

@end

Implementation file:

@interface ServicesManager ()

@property (nonatomic, strong) QMContactListService* contactListService;

@end

@implementation ServicesManager

- (instancetype)init {
	self = [super init];
    
	if (self) {
        [QMContactListCache setupDBWithStoreNamed:kContactListCacheNameKey];
		_contactListService = [[QMContactListService alloc] initWithServiceManager:self cacheDataSource:self];
		// Replace with any users service you are already using or going to use
		_usersService = [[UsersService alloc] initWithContactListService:_contactListService];
	}
    
	return self;
}

- (void)showNotificationForMessage:(QBChatMessage *)message inDialogID:(NSString *)dialogID
{
    if ([self.currentDialogID isEqualToString:dialogID]) return;
    
    if (message.senderID == self.currentUser.ID) return;
    
    NSString* dialogName = @"New message";
    
    QBChatDialog* dialog = [self.chatService.dialogsMemoryStorage chatDialogWithID:dialogID];
    
    if (dialog.type != QBChatDialogTypePrivate) {
        dialogName = dialog.name;
    } else {
        QBUUser* user = [[StorageManager instance] userByID:dialog.recipientID];
        if (user != nil) {
            dialogName = user.login;
        }
    }
    
    // Display notification UI
}

- (void)handleErrorResponse:(QBResponse *)response {
    
    [super handleErrorResponse:response];
    
    if (![self isAuthorized]) return;
	NSString *errorMessage = [[response.error description] stringByReplacingOccurrencesOfString:@"(" withString:@""];
	errorMessage = [errorMessage stringByReplacingOccurrencesOfString:@")" withString:@""];
	
	if( response.status == 502 ) { // bad gateway, server error
		errorMessage = @"Bad Gateway, please try again";
	}
	else if( response.status == 0 ) { // bad gateway, server error
		errorMessage = @"Connection network error, please try again";
	}
    
    // Display notification UI
}

#pragma mark QMChatServiceCache delegate

- (void)chatService:(QMChatService *)chatService didAddMessageToMemoryStorage:(QBChatMessage *)message forDialogID:(NSString *)dialogID {
    [super chatService:chatService didAddMessageToMemoryStorage:message forDialogID:dialogID];
    
    [self showNotificationForMessage:message inDialogID:dialogID];
}

#pragma mark QMContactListServiceCacheDelegate delegate

- (void)cachedUsers:(QMCacheCollection)block {
	[QMContactListCache.instance usersSortedBy:@"id" ascending:YES completion:block];
}

- (void)cachedContactListItems:(QMCacheCollection)block {
	[QMContactListCache.instance contactListItems:block];
}

@end

QMAuthService

This class is responsible for authentication operations.

Current user authorisation status:

@property (assign, nonatomic, readonly) BOOL isAuthorized;

Sign up user and login to Quickblox.

- (QBRequest *)signUpAndLoginWithUser:(QBUUser *)user completion:(void(^)(QBResponse *response, QBUUser *userProfile))completion;

Login user to Quickblox.

- (QBRequest *)logInWithUser:(QBUUser *)user completion:(void(^)(QBResponse *response, QBUUser *userProfile))completion;

Login with facebook session token.

- (QBRequest *)logInWithFacebookSessionToken:(NSString *)sessionToken completion:(void(^)(QBResponse *response, QBUUser *userProfile))completion;

Logout user from Quickblox.

- (QBRequest *)logInWithFacebookSessionToken:(NSString *)sessionToken completion:(void(^)(QBResponse *response, QBUUser *userProfile))completion;

QMAuthService + Bolts

QMAuthService also has all methods implemented using BFTasks.

Sign up user and log's in to Quickblox using Bolts.

- (BFTask *)signUpAndLoginWithUser:(QBUUser *)user;

Login user to Quickblox using Bolts.

- (BFTask *)loginWithUser:(QBUUser *)user;

Login with facebook session token using Bolts.

- (BFTask *)loginWithFacebookSessionToken:(NSString *)sessionToken;

Logout user from Quickblox using Bolts.

- (BFTask *)logout;

QMChatService

This class is responsible for operation with messages and dialogs.

Connect user to Quickblox chat.

- (void)connectWithCompletionBlock:(QBChatCompletionBlock)completion;

Disconnect user from Quickblox chat.

- (void)disconnectWithCompletionBlock:(QBChatCompletionBlock)completion;

Join user to group dialog.

- (void)joinToGroupDialog:(QBChatDialog *)dialog completion:(QBChatCompletionBlock)completion;

Create group chat dialog with occupants on Quickblox.

- (void)createGroupChatDialogWithName:(NSString *)name photo:(NSString *)photo occupants:(NSArray *)occupants
completion:(void(^)(QBResponse *response, QBChatDialog *createdDialog))completion;

Create private chat dialog with opponent on Quickblox.

- (void)createPrivateChatDialogWithOpponent:(QBUUser *)opponent
completion:(void(^)(QBResponse *response, QBChatDialog *createdDialog))completion;

Change dialog name.

- (void)changeDialogName:(NSString *)dialogName forChatDialog:(QBChatDialog *)chatDialog
completion:(void(^)(QBResponse *response, QBChatDialog *updatedDialog))completion;

Change dialog avatar.

- (void)changeDialogAvatar:(NSString *)avatarPublicUrl forChatDialog:(QBChatDialog *)chatDialog
completion:(void(^)(QBResponse *response, QBChatDialog *updatedDialog))completion;

Add occupants to dialog.

- (void)joinOccupantsWithIDs:(NSArray *)ids toChatDialog:(QBChatDialog *)chatDialog
completion:(void(^)(QBResponse *response, QBChatDialog *updatedDialog))completion;

Deletes dialog on service and in cache.

- (void)deleteDialogWithID:(NSString *)dialogId
completion:(void(^)(QBResponse *response))completion;

Recursively fetch all dialogs from Quickblox.

- (void)allDialogsWithPageLimit:(NSUInteger)limit
				extendedRequest:(NSDictionary *)extendedRequest
				 iterationBlock:(void(^)(QBResponse *response, NSArray *dialogObjects, NSSet *dialogsUsersIDs, BOOL *stop))iterationBlock
					 completion:(void(^)(QBResponse *response))completion;

Send system message to users about adding to dialog with dialog inside.

- (void)sendSystemMessageAboutAddingToDialog:(QBChatDialog *)chatDialog
                                  toUsersIDs:(NSArray *)usersIDs
                                  completion:(QBChatCompletionBlock)completion;

Send message about updated dialog with dialog inside and notification.

- (void)sendMessageAboutUpdateDialog:(QBChatDialog *)updatedDialog
                withNotificationText:(NSString *)notificationText
                    customParameters:(NSDictionary *)customParameters
                          completion:(QBChatCompletionBlock)completion;

Send message about accepting or rejecting contact requst.

- (void)sendMessageAboutAcceptingContactRequest:(BOOL)accept
                                   toOpponentID:(NSUInteger)opponentID
                                     completion:(QBChatCompletionBlock)completion;

Sending notification message about adding occupants to specific dialog.

- (void)sendNotificationMessageAboutAddingOccupants:(NSArray *)occupantsIDs
                                           toDialog:(QBChatDialog *)chatDialog
                               withNotificationText:(NSString *)notificationText
                                         completion:(QBChatCompletionBlock)completion;
                                         

Sending notification message about leaving dialog.

- (void)sendNotificationMessageAboutLeavingDialog:(QBChatDialog *)chatDialog
                             withNotificationText:(NSString *)notificationText
                                       completion:(QBChatCompletionBlock)completion;
                                         

Sending notification message about changing dialog photo.

- (void)sendNotificationMessageAboutChangingDialogPhoto:(QBChatDialog *)chatDialog
                                   withNotificationText:(NSString *)notificationText
                                             completion:(QBChatCompletionBlock)completion;
                                         

Sending notification message about changing dialog name.

- (void)sendNotificationMessageAboutChangingDialogName:(QBChatDialog *)chatDialog
                                  withNotificationText:(NSString *)notificationText
                                            completion:(QBChatCompletionBlock)completion;
                                         

Fetches 100 messages starting from latest message in cache.

- (void)messagesWithChatDialogID:(NSString *)chatDialogID completion:(void(^)(QBResponse *response, NSArray *messages))completion;

Fetches 100 messages that are older than oldest message in cache.

- (BFTask <NSArray <QBChatMessage *> *> *)loadEarlierMessagesWithChatDialogID:(NSString *)chatDialogID;

Fetch dialog with dialog identifier.

- (void)fetchDialogWithID:(NSString *)dialogID completion:(void (^)(QBChatDialog *dialog))completion;

Load dialog with dialog identifier from Quickblox server and save to local storage.

- (void)loadDialogWithID:(NSString *)dialogID completion:(void (^)(QBChatDialog *loadedDialog))completion;

Fetch dialogs updated from date.

- (void)fetchDialogsUpdatedFromDate:(NSDate *)date
 					   andPageLimit:(NSUInteger)limit
 					 iterationBlock:(void(^)(QBResponse *response, NSArray *dialogObjects, NSSet *dialogsUsersIDs, BOOL *stop))iteration
 					completionBlock:(void (^)(QBResponse *response))completion;

Send message to dialog.

- (void)sendMessage:(QBChatMessage *)message
		   toDialog:(QBChatDialog *)dialog
      saveToHistory:(BOOL)saveToHistory
      saveToStorage:(BOOL)saveToStorage
         completion:(QBChatCompletionBlock)completion;

Send attachment message to dialog.

- (void)sendAttachmentMessage:(QBChatMessage *)attachmentMessage
                     toDialog:(QBChatDialog *)dialog
          withAttachmentImage:(UIImage *)image
                   completion:(QBChatCompletionBlock)completion;

Mark message as delivered.

- (void)markMessageAsDelivered:(QBChatMessage *)message completion:(QBChatCompletionBlock)completion;

Mark messages as delivered.

- (void)markMessagesAsDelivered:(NSArray<QBChatMessage *> *)messages completion:(QBChatCompletionBlock)completion;

Send read status for message and update unreadMessageCount for dialog in storage.

- (void)readMessage:(QBChatMessage *)message completion:(QBChatCompletionBlock)completion;

Send read status for messages and update unreadMessageCount for dialog in storage.

- (void)readMessages:(NSArray<QBChatMessage *> *)messages forDialogID:(NSString *)dialogID completion:(QBChatCompletionBlock)completion;

QMChatService + Bolts

QMChatService also has all methods implemented using BFTasks.

Connect user to Quickblox chat using Bolts.

- (BFTask *)connect;

Disconnect user from Quickblox chat using Bolts.

- (BFTask *)disconnect;

Join user to group dialog using Bolts.

- (BFTask *)joinToGroupDialog:(QBChatDialog *)dialog;

Create group chat dialog with occupants on Quickblox using Bolts.

- (BFTask *)createGroupChatDialogWithName:(NSString *)name photo:(NSString *)photo occupants:(NSArray *)occupants;

Create private chat dialog with opponent on Quickblox using Bolts.

- (BFTask *)createPrivateChatDialogWithOpponent:(QBUUser *)opponent;

Change dialog name using Bolts.

- (BFTask *)changeDialogName:(NSString *)dialogName forChatDialog:(QBChatDialog *)chatDialog;

Change dialog avatar using Bolts.

- (BFTask *)changeDialogAvatar:(NSString *)avatarPublicUrl forChatDialog:(QBChatDialog *)chatDialog;

Add occupants to dialog using Bolts.

- (BFTask *)joinOccupantsWithIDs:(NSArray *)ids toChatDialog:(QBChatDialog *)chatDialog;

Deletes dialog on service and in cache using Bolts.

- (BFTask *)deleteDialogWithID:(NSString *)dialogID;

Recursively fetch all dialogs from Quickblox using Bolts.

- (BFTask *)allDialogsWithPageLimit:(NSUInteger)limit
                    extendedRequest:(NSDictionary *)extendedRequest
                     iterationBlock:(void(^)(QBResponse *response, NSArray *dialogObjects, NSSet *dialogsUsersIDs, BOOL *stop))iterationBlock;

Send system message to users about adding to dialog with dialog inside using Bolts.

- (BFTask *)sendSystemMessageAboutAddingToDialog:(QBChatDialog *)chatDialog
                                      toUsersIDs:(NSArray *)usersIDs;

Send message about accepting or rejecting contact requst using Bolts.

- (BFTask *)sendMessageAboutAcceptingContactRequest:(BOOL)accept
                                       toOpponentID:(NSUInteger)opponentID;

Sending notification message about adding occupants to specific dialog using Bolts.

- (BFTask *)sendNotificationMessageAboutAddingOccupants:(NSArray *)occupantsIDs
                                               toDialog:(QBChatDialog *)chatDialog
                                   withNotificationText:(NSString *)notificationText;
                                         

Sending notification message about leaving dialog using Bolts.

- (BFTask *)sendNotificationMessageAboutLeavingDialog:(QBChatDialog *)chatDialog
                                 withNotificationText:(NSString *)notificationText;
                                         

Sending notification message about changing dialog photo using Bolts.

- (BFTask *)sendNotificationMessageAboutChangingDialogPhoto:(QBChatDialog *)chatDialog
                                       withNotificationText:(NSString *)notificationText;
                                         

Sending notification message about changing dialog name using Bolts.

- (BFTask *)sendNotificationMessageAboutChangingDialogName:(QBChatDialog *)chatDialog
                                      withNotificationText:(NSString *)notificationText;
                                         

Fetches messages with chat dialog ID using Bolts.

- (BFTask *)messagesWithChatDialogID:(NSString *)chatDialogID;

Fetch dialog with dialog identifier using Bolts.

- (BFTask *)fetchDialogWithID:(NSString *)dialogID;

Load dialog with dialog identifier from Quickblox server and save to local storage using Bolts.

- (BFTask *)loadDialogWithID:(NSString *)dialogID;

Fetch dialogs updated from date using Bolts.

- (BFTask *)fetchDialogsUpdatedFromDate:(NSDate *)date
                           andPageLimit:(NSUInteger)limit
                         iterationBlock:(void(^)(QBResponse *response, NSArray *dialogObjects, NSSet *dialogsUsersIDs, BOOL *stop))iteration;

Send message to dialog using Bolts.

- (BFTask *)sendMessage:(QBChatMessage *)message
               toDialog:(QBChatDialog *)dialog
          saveToHistory:(BOOL)saveToHistory
          saveToStorage:(BOOL)saveToStorage;

Send attachment message to dialog using Bolts.

- (BFTask *)sendAttachmentMessage:(QBChatMessage *)attachmentMessage
                         toDialog:(QBChatDialog *)dialog
              withAttachmentImage:(UIImage *)image;

Mark message as delivered using Bolts.

- (BFTask *)markMessageAsDelivered:(QBChatMessage *)message;

Send read status for message and update unreadMessageCount for dialog in storage using Bolts.

- (BFTask *)readMessage:(QBChatMessage *)message;

QMDialogsMemoryStorage

This class is responsible for in-memory dialogs storage.

Adds chat dialog and joins if chosen.

- (void)addChatDialog:(QBChatDialog *)chatDialog andJoin:(BOOL)join completion:(void(^)(QBChatDialog *addedDialog, NSError *error))completion;

Adds chat dialogs and joins.

- (void)addChatDialogs:(NSArray *)dialogs andJoin:(BOOL)join;

Deletes chat dialog.

- (void)deleteChatDialogWithID:(NSString *)chatDialogID;

Find dialog by identifier.

- (QBChatDialog *)chatDialogWithID:(NSString *)dialogID;

Find private chat dialog with opponent ID.

- (QBChatDialog *)privateChatDialogWithOpponentID:(NSUInteger)opponentID;

Find unread dialogs.

- (NSArray *)unreadDialogs;

Fetch all dialogs.

- (NSArray *)unsortedDialogs;

Fetch all dialogs sorted by last message date.

- (NSArray *)dialogsSortByLastMessageDateWithAscending:(BOOL)ascending;

Fetch all dialogs sorted by updated at.

- (NSArray *)dialogsSortByUpdatedAtWithAscending:(BOOL)ascending;

Fetch dialogs with specified sort descriptors.

- (NSArray *)dialogsWithSortDescriptors:(NSArray *)descriptors;

QMMessagesMemoryStorage

This class is responsible for in-memory messages storage.

Add message.

- (void)addMessage:(QBChatMessage *)message forDialogID:(NSString *)dialogID;

Add messages.

- (void)addMessages:(NSArray *)messages forDialogID:(NSString *)dialogID;

Replace all messages for dialog.

- (void)replaceMessages:(NSArray *)messages forDialogID:(NSString *)dialogID;

Update message.

- (void)updateMessage:(QBChatMessage *)message;

Fetch messages.

- (NSArray *)messagesWithDialogID:(NSString *)dialogID;

Delete messages for dialog.

- (void)deleteMessagesWithDialogID:(NSString *)dialogID;

Fetch message by identifier.

- (QBChatMessage *)messageWithID:(NSString *)messageID fromDialogID:(NSString *)dialogID;

Fetch last message.

- (QBChatMessage *)lastMessageFromDialogID:(NSString *)dialogID;

Checks if dialog has messages.

- (BOOL)isEmptyForDialogID:(NSString *)dialogID;

Fetch oldest(first) message.

- (QBChatMessage *)oldestMessageForDialogID:(NSString *)dialogID;

QMChatAttachmentService

This class is responsible for attachment operations (sending, receiving, loading, saving).

Attachment status delegate:

@property (nonatomic, weak) id<QMChatAttachmentServiceDelegate> delegate;

Get attachment image. (Download from Quickblox or load from disc).

- (void)getImageForAttachmentMessage:(QBChatMessage *)attachmentMessage completion:(void(^)(NSError *error, UIImage *image))completion;

QMContactListService

This class is responsible for contact list operations.

Add user to contact list.

- (void)addUserToContactListRequest:(QBUUser *)user completion:(void(^)(BOOL success))completion;

Remove user from contact list.

- (void)removeUserFromContactListWithUserID:(NSUInteger)userID completion:(void(^)(BOOL success))completion;

Accept contact request.

- (void)acceptContactRequest:(NSUInteger)userID completion:(void (^)(BOOL success))completion;

Reject contact request.

- (void)rejectContactRequest:(NSUInteger)userID completion:(void(^)(BOOL success))completion;

QMContactListMemoryStorage

This class is responsible for in-memory contact list storage.

Update contact list memory storage.

- (void)updateWithContactList:(QBContactList *)contactList;

Update contact list memory storage with array of contact list items.

- (void)updateWithContactList:(QBContactList *)contactList;

Fetch contact list item.

- (QBContactListItem *)contactListItemWithUserID:(NSUInteger)userID;

Fetch user ids from contact list memory storage.

- (NSArray *)userIDsFromContactList;

QMUsersService

This class is responsible for operations with users and uses BFTasks.

Load users to memory storage from disc cache.

- (BFTask<NSArray<QBUUser *> *> *)loadFromCache;

###Get users

There are several ways to get users by methods below. By default every get method first checking for a specific user in cache. If such user was found in cache method will exclude him from server request, and send request only for users, that weren't found in local cache. If you want to update users in cache, you need to force them to be loaded from server, even though they are already being cached. Every get method has also its implementation with forceLoad flag, set it to YES in order to force users loading from server.

Get user by id:

- (BFTask<QBUUser *> *)getUserWithID:(NSUInteger)userID;

Get users by ids:

- (BFTask<NSArray<QBUUser *> *> *)getUsersWithIDs:(NSArray<NSNumber *> *)usersIDs;

Get users by ids with extended pagination parameters:

- (BFTask<NSArray<QBUUser *> *> *)getUsersWithIDs:(NSArray<NSNumber *> *)usersIDs page:(QBGeneralResponsePage *)page;

Get users by emails:

- (BFTask<NSArray<QBUUser *> *> *)getUsersWithEmails:(NSArray<NSString *> *)emails;

Get users by emails with extended pagination parameters:

- (BFTask<NSArray<QBUUser *> *> *)getUsersWithEmails:(NSArray<NSString *> *)emails page:(QBGeneralResponsePage *)page;

Get users by facebook ids:

- (BFTask<NSArray<QBUUser *> *> *)getUsersWithFacebookIDs:(NSArray<NSString *> *)facebookIDs;

Get users by facebook ids with extended pagination parameters:

- (BFTask<NSArray<QBUUser *> *> *)getUsersWithFacebookIDs:(NSArray<NSString *> *)facebookIDs page:(QBGeneralResponsePage *)page;

Get users by logins:

- (BFTask<NSArray<QBUUser *> *> *)getUsersWithLogins:(NSArray<NSString *> *)logins;

Get users by logins with extended pagination parameters:

- (BFTask<NSArray<QBUUser *> *> *)getUsersWithLogins:(NSArray<NSString *> *)logins page:(QBGeneralResponsePage *)page;

###Search users

Search for users by full name:

- (BFTask<NSArray<QBUUser *> *> *)searchUsersWithFullName:(NSString *)searchText;

Search for users by full name with extended pagination parameters:

- (BFTask<NSArray<QBUUser *> *> *)searchUsersWithFullName:(NSString *)searchText page:(QBGeneralResponsePage *)page;

Search for users by tags:

- (BFTask<NSArray<QBUUser *> *> *)searchUsersWithTags:(NSArray<NSString *> *)tags;

Search for users by tags with extended pagination parameters:

- (BFTask<NSArray<QBUUser *> *> *)searchUsersWithTags:(NSArray<NSString *> *)tags page:(QBGeneralResponsePage *)page;

QMUsersMemoryStorage

This class is responsible for in-memory users storage.

Delegate for getting UsersMemoryStorage user ids.

@property (weak, nonatomic) id <QMUsersMemoryStorageDelegate> delegate;

Add users

Add user to memory storage.

- (void)addUser:(QBUUser *)user;

Add users to memory storage.

- (void)addUsers:(NSArray<QBUUser *> *)users;

Get users

Get all users from memory storage without sorting.

- (NSArray<QBUUser *> *)unsortedUsers;

Get all users in memory storage sorted by key.

- (NSArray<QBUUser *> *)usersSortedByKey:(NSString *)key ascending:(BOOL)ascending;

Get all contacts in memory storage sorted by key.

- (NSArray *)contactsSortedByKey:(NSString *)key ascending:(BOOL)ascending;

Get users with ids without some id.

- (NSArray<QBUUser *> *)usersWithIDs:(NSArray *)IDs withoutID:(NSUInteger)ID;

Get string created from users full names, separated by ",".

- (NSString *)joinedNamesbyUsers:(NSArray *)users;

Get user with user id.

- (QBUUser *)userWithID:(NSUInteger)userID;

Get users with user ids.

- (NSArray<QBUUser *> *)usersWithIDs:(NSArray *)ids;

Get users with user logins.

- (NSArray<QBUUser *> *)usersWithLogins:(NSArray<NSString *> *)logins;

Get users with user emails.

- (NSArray<QBUUser *> *)usersWithEmails:(NSArray<NSString *> *)emails;

Get users with user facebook ids.

- (NSArray<QBUUser *> *)usersWithFacebookIDs:(NSArray<NSString *> *)facebookIDs;

Search and Exclude

Search for users excluding users with users ids. Result dictionary will contain an array of found users, and an array of not found search criteria (ids, logins, emails etc).

- (NSDictionary *)usersByExcludingUsersIDs:(NSArray<NSNumber *> *)ids;

Search for users excluding users with logins.

- (NSDictionary *)usersByExcludingLogins:(NSArray<NSString *> *)logins;

Search for users excluding users with email.

- (NSDictionary *)usersByExcludingEmails:(NSArray<NSString *> *)emails;

Search for users excluding users with facebook IDs.

- (NSDictionary *)usersByExcludingFacebookIDs:(NSArray<NSString *> *)facebookIDs;

Documentation

For more information see our inline code documentation.

License

See LICENSE.txt