Chat SDKs iOS v3
Chat SDKs iOS
Chat SDKs
iOS
Version 3
Sendbird Chat SDK v3 for iOS is no longer supported as a new version is released. Check out our latest Chat SDK v4

Migration from SyncManager

Copy link

Local caching is available with Sendbird Chat SDK. Both local caching and SyncManager enables Sendbird Chat SDK for iOS to locally cache and retrieve data related to group channels and messages. However, local caching is integrated into Chat SDK while SyncManager is an external add-on. Being internally integrated into Chat SDK allows for easier maintenance, improved stability, and enhanced usability.

The existing SyncManager for iOS will be deprecated soon, so it is highly recommended to migrate from SyncManager to the Chat SDK with local caching. In the meantime, SyncManager will continue to work if the dependency to SyncManager is not removed. The dependency should be deleted once the migration to local caching is completed.


Initialization

Copy link

There are two ways to initialize the Chat SDK, with local caching or without local caching. During the initialization, the useCaching determines whether the client app will use local caching with Sendbird Chat SDK or not. Its default value is false meaning the Chat SDK will be initialized without local caching.

In local caching, the completionHandler: callbacks is added to the initWithApplicationId method, which receives the initialization status through different event handlers. For Objective-C, the migrationStartHandler: is called when there's an upgrade in the local cache. Meanwhile, the completionHandler: informs the client app of whether the initialization is successful or not.

Note: If initialization fails to complete while the useCaching is set to true, Chat SDK will operate as if the useCaching is set to false.

Connect to Sendbird server

Copy link

The difference between local caching and SyncManager in terms of the SBDMain.connect() is whether it is necessary to call the SBDMain.connect() during initialization or not. Both local caching and SyncManager ensure that your client app is operational during offline mode. However, to use the offline mode in SyncManager, calling the SBDMain.connect() during the initialization process was optional. Instead, you only had to call the SBSMSyncManager.setup after the initWithApplicationId. In local caching, however, calling the SBDMain.connect() after the initWithApplicationId is required during the initialization process.

Local cachingSyncManager
// Initialize with the useLocalCaching set to true.
SBDMain.initWithApplicationId(APP_ID, useCaching: true) {
    os_log(.info, "Application: Called when there's a change in the local database.")
} completionHandler: { error in
    if error != nil {
        os_log(.info, "Application: Called when initialization failed.")
    }
    else {
        os_log(.info, "Application: Called when initialization is done.")
    }
}

SBDMain.connect(withUserId: userId) { user, error in
    if user != nil {
        if error != nil {
            // Proceed in offline mode with the data stored in the local database.
            // Later, connection will be made automatically
            // and can be notified through the SBDConnectionDelegate.didSucceedReconnection().
        }
        else {
            // Proceed in online mode.
        }
    }
    else {
        // No user is available.
        // Handle error.
    }
}

Objective-C

Copy link
Local cachingSyncManager
// Initialize with the useLocalCaching set to true.
[SBDMain initWithApplicationId:APP_ID useCaching:YES migrationStartHandler:^{
    NSLog(@"Application: Called when there's a change in the local database.");
} completionHandler:^(SBDError * _Nullable error) {
    if (error != nil) {
        NSLog(@"Application: Called when initialization failed.");
    }
    else {
        NSLog(@"Application: Called when initialization is done.");
    }
}];

[SBDMain connectWithUserId:USER_ID completionHandler:^(SBDUser * _Nullable user, SBDError * _Nullable error) {
    if (user != nil) {
        if (error != nil) {
            // Proceed in offline mode with the data stored in the local database.
            // Later, connection will be made automatically
            // and can be notified through the `didStartReconnection` of `SBDConnectionDelegate`.
        }
        else {
            // Proceed in online mode.
        }
    }
    else {
        // No user is available.
        // Handle error.
    }
}];

Group channel collection

Copy link

A SBDGroupChannelCollection allows you to swiftly create a channel list without missing any channel-related updates by retrieving group channels from both the local cache and Sendbird server. This page explains how to make a channel list using the collection and serves as a migration guide.

Create a collection

Copy link

SyncManager's SBSMChannelCollection is changed to the SBDGroupChannelCollection in local caching. The SBDGroupChannelCollection instance can be created through the createGroupChannelCollection() method.

Create a SBDGroupChannelListQuery instance through the createMyGroupChannelListQuery() method and query setters. This will determine the number of channels to retrieve for the channel list.

Local cachingSyncManager
let query = SBDGroupChannel.createMyGroupChannelListQuery()
query?.limit = CHANNEL_LIST_LIMIT

groupChannelCollection = SBDGroupChannelCollection(query: query!)
//SBDGroupChannelCollectionDelegate has to be implemented.
groupChannelCollection?.delegate = self 

Objective-C

Copy link
Local cachingSyncManager
SBDGroupChannelListQuery *query = [SBDGroupChannel createMyGroupChannelListQuery];
query.limit = CHANNEL_LIST_LIMIT;

self.groupChannelCollection = [[SBDGroupChannelCollection alloc] initWithQuery:query];
self.groupChannelCollection.delegate = self;

Channel events

Copy link

In local caching, the SBDGroupChannelCollectionDelegate is used to determine how the client app would react to channel-related events. SyncManager's SBSMChannelCollectionDelegate, which is used to handle real-time events, should be changed as shown in the code below.


The following table shows when to call each event handler.

EventCalled when

addedChannels

- A new group channel is created as a real-time event.
- New group channels are fetched by changelog sync.
- It replaces SyncManager's SBSMChannelEventAction.insert.

updatedChannels

- The channel information that is included in the user's current chat view is updated as a real-time event.
- Updated channel information is fetched during changelog sync.
- It replaces SyncManager's SBSMChannelEventAction.update and SBSMChannelEventAction.move.

deletedChannelUrls

- A group channel is deleted as a real-time event.
- A channel deletion event is fetched during changelog sync.
- It replaces SyncManager's SBSMChannelEventAction.remove.

Local cachingSyncManager
extension ViewController: SBDGroupChannelCollectionDelegate {
    func channelCollection(_ collection: SBDGroupChannelCollection, context: SBDChannelContext, addedChannels channels: [SBDGroupChannel]) {

    }

    func channelCollection(_ collection: SBDGroupChannelCollection, context: SBDChannelContext, updatedChannels channels: [SBDGroupChannel]) {

    }

    func channelCollection(_ collection: SBDGroupChannelCollection, context: SBDChannelContext, deletedChannelUrls: [String]) {

    }
}

Objective-C

Copy link
Local cachingSyncManager
// LocalCachingViewController.h
@interface LocalCachingViewController : UIViewController<SBDGroupChannelCollectionDelegate>

@end

// LocalCachingViewController.m
@implementation LocalCachingViewController

#pragma mark - SBDGroupChannelCollectionDelegate

- (void)channelCollection:(SBDGroupChannelCollection *)collection
                  context:(SBDChannelContext *)context
            addedChannels:(NSArray<SBDGroupChannel *> *)channels {

}

- (void)channelCollection:(SBDGroupChannelCollection *)collection
                  context:(SBDChannelContext *)context
          updatedChannels:(NSArray<SBDGroupChannel *> *)channels {

}

- (void)channelCollection:(SBDGroupChannelCollection *)collection
                  context:(SBDChannelContext *)context
       deletedChannelUrls:(NSArray<NSString *> *)deletedChannelUrls {

}

@end

List channels

Copy link

SyncManager's fetch method retrieves channels from the local cache and delivers them to the SBSMChannelCollectionDelegate instance. In local caching, SBDGroupChannelCollection can retrieve channels through two new interfaces, hasMore and loadMore.

By default, cached channels are listed in reverse chronological order, meaning the channel that most recently received a message appears at the top of the list. The channel order is automatically updated in the local cache when a new message arrives.

MethodsDescription

hasMore

- Checks if there are more channels to load.
- Called whenever a user scroll reaches the top or bottom of the channel list depending on the implementation.

loadMore

- If hasMore is true, retrieves channels from the local cache to show in the channel list.
- Called whenever a user scroll reaches the top or bottom of the channel list depending on the implementation.

Local cachingSyncManager
if groupChannelCollection.hasMore {
    groupChannelCollection.loadMore(completionHandler: { channels, error in
        // The channel list returns as a callback.
    })
}

Objective-C

Copy link
Local cachingSyncManager
if (self.groupChannelCollection.hasMore) {
    [self.groupChannelCollection loadMoreWithCompletionHandler:^(NSArray<SBDGroupChannel *> * _Nullable channels, SBDError * _Nullable error) {
        // The channel list returns as a callback.
    }];
}

Dispose of the collection

Copy link

SyncManager's SBSMChannelCollection has the remove() method which clears all the channels managed by the collection and stops synchronization process of the collection.

On the other hand, local caching uses the dispose() method to clear the existing channel list view. This method should be called when the user closes the channel list so that the SBDGroupChannelCollectionDelegate won't make any change to the channel list.

Local cachingSyncManager
groupChannelCollection.dispose()

Objective-C

Copy link
Local cachingSyncManager
[self.groupChannelCollection dispose];

Message collection

Copy link

A SBDMessageCollection allows you to swiftly create a chat view without missing any message-related updates by retrieving data from both the local cache and Sendbird server. This page explains how to create a chat view using the collection and serves as a migration guide.

Create a collection

Copy link

In local caching, the SBDMessageListParams is used instead of SyncManager's SBSMMessageFilter. A SBDMessageListParams instance will determine how to sort and order the retrieved messages. Then, specify the starting point of the message list in the chat view using the collection's builder.

Local cachingSyncManager
let messageListParams = SBDMessageListParams()
messageListParams.previousResultSize = 30
messageListParams.nextResultSize = 30

messageCollection = SBDMessageCollection(channel: GROUP_CHANNEL, startingPoint: STARTING_POINT, params: messageListParams)
// The SBDMessageCollectionDelegate has to be implemented.
messageCollection?.delegate = self 

Objective-C

Copy link
Local cachingSyncManager
SBDMessageListParams *messageListParams = [[SBDMessageListParams alloc] init];
messageListParams.previousResultSize = 30;
messageListParams.nextResultSize = 30;

self.messageCollection = [[SBDMessageCollection alloc] initWithChannel:GROUP_CHANNEL startingPoint:STARTING_POINT params:messageListParams];
// The SBDMessageCollectionDelegate has to be implemented.
self.messageCollection.delegate = self; 

Message events

Copy link

Use the SBDMessageCollectionDelegate to determine how the client app would react to message-related events.

A new addition to local caching is the didDetectHugeGap:. If more than 300 messages are missing in the local cache compared to the remote server, Sendbird Chat SDK determines that there is a huge gap. For further information, see Gap and synchronization.

The following table shows when to call each event handler.

DelegateCalled when

messageCollection:context:channel:addedMessages:

- A new message is created as a real-time event.
- New messages are fetched through the gap check API.

messageCollection:context:channel:deletedMessages:

- A message is deleted as a real-time event.
- Message deletion is detected during changelog sync.

messageCollection:context:channel:updatedMessages:

- A message is updated as a real-time event.
- Message update is detected during changelog sync.
- The status of a message changes.

messageCollection:context:updatedChannel:

- The channel information that is included in the user's current chat view is updated as a real-time event.
-Channel info update is detected during changelog sync.

messageCollection:context:deletedChannel:

- The current channel is deleted as a rea-time event.
- Channel deletion is detected during changelog sync.
- In both cases, the entire view should be disposed.

didDetectHugeGap:

- A huge gap is detected when more than 300 messages are missing in the local cache compared to the remote server. In this case, you need to dispose of the view and create a new SBDMessageCollection instance.

SyncManager's didReceive:succeededMessages:,didReceive:pendingMessages:, and didReceive:failedMessages: should be changed as shown in the code below.

Local cachingSyncManager
extension ViewController: SBDMessageCollectionDelegate {
    /**
     * SyncManager's following events should be handled through the messageCollection:context:channel:addedMessages: in local caching:
     *   1. collection(_:didReceive:succeededMessages:) SBSMMessageEventAction.insert.
     *   2. collection(_:didReceive:pendingMessages:) SBSMMessageEventAction.insert.
     */
    func messageCollection(_ collection: SBDMessageCollection, context: SBDMessageContext, channel: SBDGroupChannel, addedMessages messages: [SBDBaseMessage]) {

    }

    /**
     * SyncManager's following events should be handled through the messageCollection:context:channel:updatedMessages: in local caching:
     *   1. collection(:didReceive:succeededMessages:) SBSMMessageEventAction.update.
     *   2. collection(_:didReceive:pendingMessages:) SBSMMessageEventAction.insert when resending a failed message.
     *   3. collection(_:didReceive:failedMessages:) SBSMMessageEventAction.insert when sending or resending a message failed.
     */
    func messageCollection(_ collection: SBDMessageCollection, context: SBDMessageContext, channel: SBDGroupChannel, updatedMessages messages: [SBDBaseMessage]) {

    }

    /**
     * SyncManager's following events should be handled through the messageCollection:context:channel:deletedMessages: in local caching: 
     *   1. collection(_:didReceive:succeededMessages:) SBSMMessageEventAction.remove.
     *   2. collection(_:didReceive:failedMessages:) SBSMMessageEventAction.remove.
     */
    func messageCollection(_ collection: SBDMessageCollection, context: SBDMessageContext, channel: SBDGroupChannel, deletedMessages messages: [SBDBaseMessage]) {

    }
    
    /**
     * SyncManager's (_:didUpdate:) events should be handled through the messageCollection:context:updatedChannel: in local caching.
     */
    func messageCollection(_ collection: SBDMessageCollection, context: SBDMessageContext, updatedChannel channel: SBDGroupChannel) {
        
    }
    
    /**
     * SyncManager's(_:didRemove:) events should be handled through the messageCollection:context:deletedChannel: in local caching.
     */
    func messageCollection(_ collection: SBDMessageCollection, context: SBDMessageContext, deletedChannel channelUrl: String) {
        
    }
    
    /**
     * The didDetectHugeGap() is called when the SDK detects more than 300 messages missing while connecting online.
     * The current message collection should be disposed and a new MessageCollection is created.
     */
    func didDetectHugeGap(_ collection: SBDMessageCollection) {
        if messageCollection != nil {
            messageCollection!.dispose()
        }
        
        let firstItemPosition = self.getFirstItemPosition()
        if firstItemPosition >= 0 {
            let message = self.messages[firstItemPosition]
            
            messageCollection = SBDMessageCollection(channel: GROUP_CHANNEL, startingPoint: message.createdAt, params: messageListParams)
        }
        else {
            messageCollection = SBDMessageCollection(channel: GROUP_CHANNEL, startingPoint: messageCollection!.startingPoint, params: messageListParams)
        }
        
        messageCollection?.delegate = self
    }
}

Objective-C

Copy link
Local cachingSyncManager
// LocalCachingViewController.h
@interface LocalCachingViewController : UIViewController<SBDMessageCollectionDelegate>

@end

// LocalCachingViewController.m
@implementation LocalCachingViewController

#pragma mark - SBDMessageCollectionDelegate

/**
 * SyncManager's following events should be handled through the messageCollection:context:channel:addedMessages: in local caching:
 *   1. collection(_:didReceive:succeededMessages:) SBSMMessageEventAction.insert.
 *   2. collection(_:didReceive:pendingMessages:) SBSMMessageEventAction.insert.
 */
- (void)messageCollection:(SBDMessageCollection *)collection
                  context:(SBDMessageContext *)context
                  channel:(SBDGroupChannel *)channel
            addedMessages:(NSArray<SBDBaseMessage *> *)messages {
    
}

/**
 * SyncManager's following events should be handled through the messageCollection:context:channel:updatedMessages: in local caching:
 *   1. collection(:didReceive:succeededMessages:) SBSMMessageEventAction.update.
 *   2. collection(_:didReceive:pendingMessages:) SBSMMessageEventAction.insert when resending a failed message.
 *   3. collection(_:didReceive:failedMessages:) SBSMMessageEventAction.insert when sending or resending a message failed.
 */
- (void)messageCollection:(SBDMessageCollection *)collection
                  context:(SBDMessageContext *)context
                  channel:(SBDGroupChannel *)channel
          updatedMessages:(NSArray<SBDBaseMessage *> *)messages {
    
}

/**
 * SyncManager's following events should be handled through the messageCollection:context:channel:deletedMessages: in local caching: 
 *   1. collection(_:didReceive:succeededMessages:) SBSMMessageEventAction.remove.
 *   2. collection(_:didReceive:failedMessages:) SBSMMessageEventAction.remove.
 */
- (void)messageCollection:(SBDMessageCollection *)collection
                  context:(SBDMessageContext *)context
                  channel:(SBDGroupChannel *)channel
          deletedMessages:(NSArray<SBDBaseMessage *> *)messages {
    
}

 /**
  * SyncManager's (_:didUpdate:) events should be handled through the messageCollection:context:updatedChannel: in local caching.
  */
- (void)messageCollection:(SBDMessageCollection *)collection
                  context:(SBDMessageContext *)context
           updatedChannel:(SBDGroupChannel *)channel {
    
}

/**
 * SyncManager's(_:didRemove:) events should be handled through the messageCollection:context:deletedChannel: in local caching.
 */
- (void)messageCollection:(SBDMessageCollection *)collection
                  context:(SBDMessageContext *)context
           deletedChannel:(NSString *)channelUrl {
    
}

/**
 * The didDetectHugeGap() is called when the SDK detects more than 300 messages missing while connecting online.
 * The current message collection should be disposed and a new MessageCollection is created.
 */
- (void)didDetectHugeGap:(SBDMessageCollection *)collection {
    if (self.messageCollection != nil) {
        [self.messageCollection dispose];
    }
    
    NSInteger firstItemPosition = [self getFirstItemPosition]; 
    if (firstItemPosition >= 0) {
        SBDBaseMessage *message = self.messages[firstItemPosition];
        
        self.messageCollection = [[SBDMessageCollection alloc] initWithChannel:GROUP_CHANNEL startingPoint:message.createdAt params:messageListParams];
    }
    else {
        self.messageCollection = [[SBDMessageCollection alloc] initWithChannel:GROUP_CHANNEL startingPoint:self.messageCollection.startingPoint params:messageListParams];
    }
    
    self.messageCollection.delegate = self;
}

@end

SyncManager's didReceiveNewMessage: used to notify a new message that had arrived should also be changed with the code below.

Local cachingSyncManager
class ViewController: UIViewController {
    // ...

    func setup() {
        SBDMain.add(self as SBDChannelDelegate, identifier: "MessageCollectionNewMessage")
    }
    // ...
}

extension ViewController: SBDChannelDelegate {
    // ...
    
    func channel(_ sender: SBDBaseChannel, didReceive message: SBDBaseMessage) {
        if sender.channelUrl != self.channel.channelUrl {
            // There's no new message for this channel.
            return
        }
        
        if self.isScrolledUp() {
            self.showNewMessageTooltip(message)
        }
    }
    
    // ...
}

Objective-C

Copy link
Local cachingSyncManager
// LocalCachingViewController.h
@interface LocalCachingViewController : UIViewController<SBDChannelDelegate>

@end

// LocalCachingViewController.m
@implementation LocalCachingViewController

- (void)setup {
    [SBDMain addChannelDelegate:self identifier:@"LocalCachingViewController"];
}

#pragma mark - SBDChannelDelegate

- (void)channel:(SBDBaseChannel * _Nonnull)sender didReceiveMessage:(SBDBaseMessage * _Nonnull)message {
    // ...
    
    if (![sender.channelUrl isEqualToString:self.channel.channelUrl]) {
        // There's no new message for this channel.
        return;
    }
    
    if ([self isScrolledUp]) {
        [self showNewMessageTooltip:message];
    }
    
    // ...
}

@end

List messages

Copy link

SyncManager's fetchInDirection method retrieves messages from the local cache and delivers them to the SBSMMessageCollectionDelegate instance. In local caching, the SBDMessageCollection can retrieve and display messages through four new interfaces, hasPrevious, hasNext, loadPrevious, and loadNext.

Unlike the SBDGroupChannelCollection, pagination works in both directions for messages because messages can be shown in either chronological or reverse chronological order depending on how you set the value of startingPoint.

MethodDescription

hasPrevious

- Checks if there are more messages to load from the previous page.
- Called whenever a user scroll hits the top of the chat view.

loadPrevious

- If hasPrevious is true, retrieves messages from the local cache to show in the view.
- Called whenever a user scroll hits the top of the chat view.

hasNext

- Checks if there are more messages to load in the next page.
- Called whenever a user scroll hits the bottom of the chat view.

loadNext

- If hasNext is true, retrieves messages from the local cache to show in the view.
- Called whenever a user scroll hits the bottom of the chat view.

Policy

Copy link

In a SBDMessageCollection, the initialization is dictated by the SBDMessageCollectionInitPolicy. The SBDMessageCollectionInitPolicy determines how initialization deals with the message data retrieved from the local cache and API calls. Because we only support cacheAndReplaceByApi at this time, an additional implementation is required to clear the messages in the local cache before adding the messages from the remote server. Messages will first be retrieved from the cached list using cacheResultHandler:. Next, apiResultHandler: calls the API result list which then replaces the cached message list with messages received from the API call.

Local cachingSyncManager
// Initialize messages from the startingPoint.
messageCollection?.start(with: .cacheAndReplaceByApi, cacheResultHandler: { messages, error in
    // Messages will be retrieved from the local cache.
    // They might be too outdated compared to the startingPoint.
}, apiResultHandler: { messages, error in
    // Messages will be retrieved through API calls from Sendbird server.
    // According to the .cacheAndReplaceByApi,
    // the existing data source needs to be cleared
    // before adding retrieved messages to the local cache.
})

// Next direction
if messageCollection?.hasNext {
    messageCollection?.loadNext(completionHandler: { messages, error in
        // A message list returns as a callback.
    })
}

// Previous direction
if messageCollection?.hasPrevious {
    messageCollection?.loadPrevious(completionHandler: { messages, error in
        
    })
}

Objective-C

Copy link
Local cachingSyncManager
[self.messageCollection startCollectionWithInitPolicy:SBDMessageTypeFilterAll cacheResultHandler:^(NSArray<SBDBaseMessage *> * _Nullable messages, SBDError * _Nullable error) {
    // Messages will be retrieved from the local cache.
    // They might be too outdated compared to the startingPoint.
} apiResultHandler:^(NSArray<SBDBaseMessage *> * _Nullable messages, SBDError * _Nullable error) {
    // Messages will be retrieved through API calls from Sendbird server.
    // According to the .cacheAndReplaceByApi,
    // the existing data source needs to be cleared
    // before adding retrieved messages to the local cache.
}];

// Next direction
if (self.messageCollection.hasNext) {
    [self.messageCollection loadNextWithCompletionHandler:^(NSArray<SBDBaseMessage *> * _Nullable messages, SBDError * _Nullable error) {
        // A message list returns as a callback.
    }];
}

// Previous direction
if (self.messageCollection.hasPrevious) {
    [self.messageCollection loadPreviousWithCompletionHandler:^(NSArray<SBDBaseMessage *> * _Nullable messages, SBDError * _Nullable error) {
        // A message list returns as a callback.
    }];
}

SyncManager's resetViewpointTimestamp is used to reset the current message collection to the specified time. To reset a viewpoint timestamp in local caching, it is suggested that you dispose the current message collection and create a new collection.

Local cachingSyncManager
messageCollection?.dispose()
messageCollection = SBDMessageCollection(channel: channel, startingPoint: TARGET_TIMESTAMP, params: messageListParams)

Objective-C

Copy link
Local cachingSyncManager
[self.messageCollection dispose];
self.messageCollection = [[SBDMessageCollection alloc] initWithChannel:channel startingPoint:TARGET_TIMESTAMP params:messageListParams];

Send a message

Copy link

In local caching, the result of sending a message is handled internally through the SBDMessageCollectionDelegate. First, pending messages are delivered to local caching's messageCollection(_:context:channel:addedMessages:). Whether the message succeeds or fails in sending, the result will be delivered to the messageCollection(_:context:channel:updatedMessages:). Thus, the process of sending the callbacks from the sendUserMessage() and the sendFileMessage() to handleSendMessageResponse(), as done in SyncManager, is no longer needed.

Note: Don't add the pending, succeeded or failed message objects of the sendMessage() callback to your message list data source. This can cause duplicate messages in the chat view.

Local cachingSyncManager
// User Message
channel.sendUserMessage(with: userMessageParams, completionHandler: nil)

// File Message
channel.sendFileMessage(with: fileMessageParams, completionHandler: nil)

Objective-C

Copy link
Local cachingSyncManager
// User Message
[channel sendUserMessageWithParams:userMessageParams completionHandler:nil];

// File Message
[channel sendFileMessageWithParams:fileMessageParams completionHandler:nil];

Resend a failed message

Copy link

In local caching, the result of resending a message is handled internally through the SBSMMessageCollectionDelegate. First, pending messages are delivered to local caching's messageCollection(_:context:channel:updatedMessages:). Whether the message has succeeded or failed in sending, the result will be delivered to messageCollection(_:context:channel:updatedMessages:). Thus, the process of sending the callbacks from resendMessage() to handleSendMessageResponse(), as done in SyncManager, is no longer needed.

Note: Don't add the pending, succeeded or failed message objects of the resendMessage() callback to your message list data source. This can cause duplicate messages in the chat view.

Local cachingSyncManager
// User Message
channel.resendUserMessage(with: userMessage, completionHandler: nil)

// File Message
let params = failedFileMessage.getParams()
channel.resendFileMessage(with: failedFileMessage, binaryData: params?.file, completionHandler: nil)

// Pending Messages
// This should be called after the messageCollection.start.(with:cacheResultHandler:apiResultHandler:).
let pendingMessageList = messageCollection?.getPendingMessages()

// Failed Messages
// This should be called after the messageCollection.start.(with:cacheResultHandler:apiResultHandler:).
let failedMessageList = messageCollection?.getFailedMessages()

Objective-C

Copy link
Local cachingSyncManager
// User Message
[channel resendUserMessageWithMessage:userMessage completionHandler:nil];

// File Message
SBDFileMessageParams *params = [failedFileMessage getFileMessageParams];
[channel resendFileMessageWithMessage:failedFileMessage binaryData:params.file completionHandler:nil];

// Pending Messages
NSArray<SBDBaseMessage *> *pendingMessageList = [self.messageCollection getPendingMessages];
// This should be called after the 
// startCollectionWithInitPolicy:cacheResultHandler:cacheResultHandler: of SBDMessageCollection.

// Failed Messages
NSArray<SBDBaseMessage *> *failedMessageList = [self.messageCollection getFailedMessages];
// This should be called after the 
// startCollectionWithInitPolicy:cacheResultHandler:cacheResultHandler: of SBDMessageCollection.

Update a message

Copy link

SyncManager had to recognize that a message was successfully sent. The delivery status had to be manually set through SyncManager's messageCollection?.updateMessage(updatedMessage). In local caching, however, updating messages is handled internally and delivered to the messageCollection(_:context:channel:updatedMessages:).

Local cachingSyncManager
channel.updateUserMessage(withMessageId: message.messageId, userMessageParams: newUserMessageParams, completionHandler: nil)

Objective-C

Copy link
Local cachingSyncManager
[channel updateUserMessageWithMessageId:message.messageId userMessageParams:newUserMessageParams completionHandler:nil];

Delete a message

Copy link

There are two cases in deleting a message:

Deleting a sent message.

In SyncManager, the process of delivering the result of message deletion through the deleteMessage() was required. However, this process is not needed in local caching.

Deleting a failed message.

The process is the same for both SyncManager and local caching where the failed message object is deleted explicitly from the local cache. In SyncManager, failed messages are deleted through the deleteMessage(). The same can be done through the removeFailedMessages() in local caching.

Local cachingSyncManager
// 1. Deleting a succeeded message. Delete from the channel object. The result is delivered to 
//the SBDMessageCollectionDelegate.messageCollection(_:context:channel:deletedMessages:).
channel.delete(message, completionHandler: nil)

// 2-1. Deleting a failed message. Delete from the collection only.
messageCollection?.removeFailedMessages([message], completionHandler: { requestIds, error in
})

// 2-2. Deleting all failed messages. Delete from the collection only.
messageCollection?.removeAllFailedMessages(completionHandler: { error in
    // All failed messages are deleted.
})

Objective-C

Copy link
Local cachingSyncManager
// 1. Deleting a succeeded message. Delete from the channel object. The result is delivered to 
//the messageCollection:context:channel:deletedMessages: of SBDMessageCollectionDelegate.
[channel deleteMessage:message completionHandler:nil];

// 2-1. Deleting a failed message. Delete from the collection only.
[self.messageCollection removeFailedMessages:@[message] completionHandler:^(NSArray<NSString *> * _Nullable requestIds, SBDError * _Nullable error) {
}];

// 2-2. Deleting all failed messages. Delete from the collection only.
[self.messageCollection removeAllFailedMessagesWithCompletionHandler:^(SBDError * _Nullable error) {
    // All failed messages are deleted.
}];

Dispose of the collection

Copy link

SyncManager's SBSMMessageCollection has a remove() method that clears all the messages managed by the collection and stops synchronization processes in the collection instance.

On the other hand, local caching uses the dispose() method to clear the existing chat view. You should call this method when the current user leaves the channel or when a new collection has to be created due to a huge gap detected by the didDetectHugeGap:.

Local cachingSyncManager
messageCollection?.dispose()

Objective-C

Copy link
Local cachingSyncManager
[self.messageCollection dispose];

Other methods

Copy link

The following are new cache-related interfaces that come with local caching. Local caching's SBDMain.clearCachedData() replaces the functionality of SyncManager's SBSMSyncManager.clearCache(), which deletes the entire data file. In addition, the SBDMain.clearCachedMessages() and the SBDMain.getCachedDataSize() are available in local caching. The following table describes each method and when it should be called in regards to the initWithApplicationId.

MethodDescription

SBDMain.clearCachedData()

- Deletes the entire data file.
- It must be called before the initWithApplicationId.

SBDMain.clearCachedMessages()

- Clears cached messages in a specific channel.
- It must be called after the initWithApplicationId.

SBDMain.getCachedDataSize()

- Checks for the current cached data size.
- It can be called before or after the initWithApplicationId.

Local cachingSyncManager
SBDMain.clearCachedData {  
}

SBDMain.clearCachedMessages(CHANNEL_URL) { error in
}

let cacheDataSize = SBDMain.getCachedDataSize()

Objective-C

Copy link
Local cachingSyncManager
[SBDMain clearCachedDataWithCompletionHandler:^{
        
}];

[SBDMain clearCachedMessages:CHANNEL_URL completionHandler:^(SBDError * _Nullable error) {
        
}];

NSUInteger cacheDataSize = [SBDMain getCachedDataSize];

In addition, SyncManager's messageCollection?.messageCount() is replaced wih the messageCollection?.getSucceededMessages() in local caching. It is used to count the number of succeeded messages in the collection.

Local cachingSyncManager
//A message collection provides a getter for the current message list in the message collection.
let succeededMessageList = messageCollection?.getSucceededMessages()
let messageCount = succeededMessageList?.count

Objective-C

Copy link
Local cachingSyncManager
//A message collection provides a getter for the current message list in the message collection.
NSArray<SBDBaseMessage *> *succeededMessageList = [self.messageCollection getSucceededMessages];
NSUInteger messageCount = succeededMessageList.count;