iOS
Migration

Migration from v2

The new and improved iOS SDK 3.0 (v3) supports your chat solution on any mobile apps and websites with the following new features:

  • The OpenChannel and GroupChannel classes have been added.
  • The UserMessage, FileMessage and AdminMessage have been added to handle various types of messages.
  • Event callbacks and new instances for various types of queries have been added.

We recommend you to migrate to v3 from the previous version by following the below instructions.


Installation

If you are using the CocoaPods,change the version of dependencies in the Podfile at the app level (not at the project level).

Light Color Skin
Copy
// v2 
target 'YOUR_TARGET' do
    pod 'SendBirdSDK', '~> 2.2'
end

// v3
target 'YOUR_TARGET' do
    pod 'SendBirdSDK', '~> 3.0'
end

Authentication

Initialization

As in v2, your client app should initialize the SendBird instance to communicate with SendBird server.

Light Color Skin
Copy
// v2
[SendBird initAppId:APP_ID];

// v3
[SBDMain initWithApplicationId:APP_ID];

Login

The loginWithUserId:andUserName:andUserImageUrl:andAccessToken: method is no longer used in v3. You only need to call the connectWithUserId:accessToken:completionHandler: once after the initWithApplicationId:.

Light Color Skin
Copy
// v2
[SendBird loginWithUserId:USER_ID andUserName:USER_NAME]; // When you allow guest login.
[SendBird loginWithUserId:USER_ID andUserName:USER_NAME andUserImageUrl:USER_IMAGE_URL andAccessToken:ACCESS_TOKEN]; // When you allow only permitted user login.

[SendBird setEventHandlerConnectBlock:^(SendBirdChannel *channel) {
    // Connect handler block.
} errorBlock:^(NSInteger code) {

}
...

}];

// v3
[SBDMain connectWithUserId:self.userIdTextField.text completionHandler:^(SBDUser * _Nullable user, SBDError * _Nullable error) { 
    // When you allow guest login.
    if (error != nil) { // Error.
        return;
    }
}];

[SBDMain connectWithUserId:USER_ID accessToken:ACCESS_TOKEN completionHandler:^(SBDUser * _Nullable user, SBDError * _Nullable error) {
    // When you allow only permitted user login.
    if (error != nil) { // Error.
        return;
    }
}];

If you want to update user information such as nickname, profile image or APNs device tokens with v3, use the updateCurrentUserInfoWithNickname:profileImage: ... : or registerDevicePushToken:completionHandler: methods after a connection is established.


Open channel

In v3, the object formerly known as open chat channel is now called open channel. Users who are participating in an open channel are referred to as participants of the channel. With the v3's SBDOpenChannel and SBDChannelListQuery classes, you can access and use a variety of features related to an open channel.

Retrieve a list of channels

Light Color Skin
Copy
// v2
self.channelListQuery = [SendBird queryChannelList];
[self.channelListQuery nextWithResultBlock:^(NSMutableArray *queryResult) {

}];

// v3
self.openChannelListQuery = [SBDOpenChannel createOpenChannelListQuery];
[self.openChannelListQuery loadNextPageWithCompletionHandler:^(NSArray<SBDOpenChannel *> * _Nullable channels, SBDError * _Nullable error) {
    if (error != nil) { // Error.
        return;
    }
}];

Connect to a channel

In v3, you only need one connection to handle multiple open channels. The connection is automatically made once you have called the connectWithUserId:accessToken:completionHandler: after the initWithApplicationId:. Plus, entering an open channel is much simpler in v3 than in v2, since you don’t need to fetch the URL of a specific channel and call the joinChannel:, queryMessageListInChannel:...: and connectWithMessageTs: to enter an open channel.

Light Color Skin
Copy
// v2
[SendBird joinChannel:CHANNEL_URL];
[[SendBird queryMessageListInChannel:CHANNEL_URL prevWithMessageTs:LLONG_MAX andLimit:LIMIT resultBlock:^(NSMutableArray *queryResult) {
    if (queryResult != nil) {
        // Connect to SendBird with max messages timestamp to receive new messages since last query.
        [SendBird connectWithMessageTs:MAX_MESSAGE_TIMESTAMP];
    } 
}];

// v3
[SBDOpenChannel getChannelWithUrl:CHANNEL_URL completionHandler:^(SBDOpenChannel * _Nonnull openChannel, SBDError * _Nullable error) {
    if (error != nil) { // Error.
        return;
    }
}];

Disconnect from a channel

In the same way as connect to a channel, the connection to SendBird server is automatically disconnected when you call the disconnectWithCompletionHandler: on application termination. If a participant wants to exit an open channel, just call the exitChannelWithCompletionHandler:.

Light Color Skin
Copy
// v2
SendBird.leave(CHANNEL_URL);
SendBird.disconnect();

// v3
[SBDOpenChannel getChannelWithUrl:CHANNEL_URL completionHandler:^(SBDOpenChannel * _Nullable openChannel, SBDError * _Nullable error) {
    if (error != nil) { // Error. 
        return;
    }
    
    [openChannel exitChannelWithCompletionHandler:^(SBDError * _Nullable error) {
        if (error != nil) { // Error.
            return;
        }
    }];
}];

Send a message to a channel

In v3, the steps of sending text and file messages are simplified into just the sendUserMessage:data:completionHandler: and sendFileMessageWithBinaryData:filename:type:size:data:progressHandler:completionHandler: methods. There are a number of methods with the same name but different parameters.

Light Color Skin
Copy
// v2
[SendBird sendMessage:MESSAGE];
[SendBird sendMessage:MESSAGE withData:DATA];

[SendBird uploadFile:FILE type:TYPE hasSizeOfFile:SIZE withCustomField:CUSTOM_FIELD uploadBlock:^(SendBirdFileInfo *fileInfo, NSError *error) {
    [SendBird sendFile:fileInfo];
}];

// v3
[openChannel sendUserMessage:MESSAGE data:DATA completionHandler:^(SBDUserMessage * _Nullable userMessage, SBDError * _Nullable error) {
    if (error != nil) { // Error. 
        return; 
    }
}];
[openChannel sendFileMessageWithBinaryData:FILE filename:FILE_NAME type:FILE_TYPE size:FILE_SIZE data:CUSTOM_DATA completionHandler:^(SBDFileMessage * _Nullable fileMessage, SBDError * _Nullable error) {
    if (error != nil) { // Error. 
        return; 
    }
    
}];

Receive messages through an event delegate

The ability of the setEventHandlerConnectBlock: is now replaced with the SBDChannelDelegate class. You can create and manage multiple channel delegates. See the Event Delegate page for more information.

Light Color Skin
Copy
// v2
[SendBird setEventHandlerConnectBlock:^(SendBirdChannel *channel) {

} errorBlock:^(NSInteger code) {

} ...

}];

// v3
@interface ChattingViewController : UIViewController<SBDChannelDelegate>

@end

@implementation OpenChannelChattingViewController

- (void)initViewController {
    [SBDMain addChannelDelegate:self identifier:self.description];
}

- (void)dismissCurrentViewController {
    [SBDMain removeChannelDelegateForIdentifier:self.description];
}

- (void)channel:(SBDBaseChannel * _Nonnull)sender didReceiveMessage:(SBDBaseMessage * _Nonnull)message {

}

@end

Load previous messages in a channel

Light Color Skin
Copy
// v2
[[SendBird queryMessageListInChannel:CHANNEL_URL prevWithMessageTs:LLONG_MAX andLimit:LIMIT resultBlock:^(NSMutableArray *queryResult) {

}];

// v3
SBDPreviousMessageListQuery *previousMessageQuery = [self.channel createPreviousMessageListQuery];
[previousMessageQuery loadPreviousMessagesWithLimit:LIMIT reverse:YES completionHandler:^(NSArray<SBDBaseMessage *> * _Nullable messages, SBDError * _Nullable error) {
    if (error != nil) { // Error.
        return;
    }
}];

Retrieve a list of all participants of a channel

A participant refers to the participating user in an open channel. Once a user exits the open channel, the user is no longer a participant of that channel and the retrieved results of a query do not include the user.

Light Color Skin
Copy
// v2
SendBirdMemberListQuery *query = [SendBird queryMemberListInChannel:CHANNEL_URL];
[query nextWithResultBlock:^(NSMutableArray *queryResult) {
        
} errorBlock:^(NSError *error) {
    
}];

// v3
self.query = [self.channel createParticipantListQuery];
[self.query loadNextPageWithCompletionHandler:^(NSArray<SBDUser *> * _Nullable users, SBDError * _Nullable error) {
    if (error != nil) { // Error.
        return;
    }
}];

Group channel

In v3, the object formerly known as messaging channel is now called group channel. Users who are joining in a group channel are referred to as members of the channel. With the SBDGroupChannel and SBDGroupChannelListQuery classes, you can access and use a variety of features related to a group channel.

Create a channel

All startMessaging related methods are replaced by createChannel and createChannelWithUserIds.

Light Color Skin
Copy
// v2
[SendBird startMessagingWithUserIds:USER_IDS];

// v3
[SBDGroupChannel createChannelWithUserIds:USER_IDS isDistinct:YES/NO completionHandler:^(SBDGroupChannel * _Nullable channel, SBDError * _Nullable error) {
    if (error != nil) { // Error.
        return;
    }
}];

Retrieve a list of channels

Light Color Skin
Copy
// v2
self.channelListQuery = [SendBird queryMessagingChannelList];
[self.channelListQuery nextWithResultBlock:^(NSMutableArray *queryResult) {

}];

// v3
self.groupChannelListQuery = [SBDGroupChannel createMyGroupChannelListQuery];
self.groupChannelListQuery.limit = LIMIT;
self.groupChannelListQuery.order = SBDGroupChannelListOrderChronological;
self.groupChannelListQuery.includeEmptyChannel = YES/OR;

[self.groupChannelListQuery loadNextPageWithCompletionHandler:^(NSArray<SBDGroupChannel *> * _Nullable channels, SBDError * _Nullable error) {
    if (error != nil) { // Error.
        return;
    }
}];

Connect to a channel

In v3, you only need one connection to handle multiple group channels. The connection is automatically made once you have called the connectWithUserId:accessToken:completionHandler: after the initWithApplicationId:. Plus, joining a group channel is much simpler in v3 than in v2, since you don’t need to fetch the URL of a specific channel and call the queryMessageListInChannel:...:, joinChannel: and connectWithMessageTs: to join the channel.

Light Color Skin
Copy
// v2
[[SendBird queryMessageListInChannel:CHANNEL_URL] loadWithMessageTs:LLONG_MAX prevLimit:PREV_LIMIT andNextLimit:NEXT_LIMIT resultBlock:^(NSMutableArray *queryResult) {
    [SendBird joinChannel:CHANNEL_URL];
    [SendBird connectWithMessageTs:MAX_MESSAGE_TIMESTAMP];
} endBlock:^(NSError *error) {

}];

// v3
// Do nothing.

Disconnect from a channel

In the same way as connect to a channel, the connection to SendBird server is automatically disconnected when you call the disconnectWithCompletionHandler: on application termination. If a participant wants to leave the open channel, just call the exitChannelWithCompletionHandler:.

Light Color Skin
Copy
// v2
[SendBird disconnect];

// v3
// Do nothing.

Invite users to a channel

Light Color Skin
Copy
// v2
[SendBird inviteMessagingWithChannelUrl:CHANNEL_URL andUserIds:USER_ID];

// v3
[self.groupChannel inviteUserId:USER_IDS completionHandler:^(SBDError * _Nullable error) {
    if (error != nil) { // Error.
        return;
    } 
}];

Remove a user from channel members

Light Color Skin
Copy
// v2
[SendBird endMessagingWithChannelUrl:CHANNEL_URL];

// v3
[groupChannel leaveChannelWithCompletionHandler:^(SBDError * _Nullable error) {
    if (error != nil) { // Error.
        return;
    } 
}];

Send a message to a channel

In v3, the steps of sending text and file messages are simplified into just the sendUserMessage:data:completionHandler: and sendFileMessageWithBinaryData:filename:type:size:data:progressHandler:completionHandler: methods. There are a number of methods with the same name but different parameters.

Light Color Skin
Copy
// v2
[SendBird sendMessage:MESSAGE];
[SendBird sendMessage:MESSAGE withData:DATA];

[SendBird uploadFile:FILE type:TYPE hasSizeOfFile:SIZE withCustomField:CUSTOM_FIELD uploadBlock:^(SendBirdFileInfo *fileInfo, NSError *error) {
    [SendBird sendFile:fileInfo];
}];

// v3
[groupChannel sendUserMessage:MESSAGE data:DATA completionHandler:^(SBDUserMessage * _Nullable userMessage, SBDError * _Nullable error) {
    if (error != nil) { // Error.
        return;
    }
}];
[groupChannel sendFileMessageWithBinaryData:FILE filename:FILE_NAME type:FILE_TYPE size:FILE_SIZE data:CUSTOM_DATA completionHandler:^(SBDFileMessage * _Nullable fileMessage, SBDError * _Nullable error) {
    if (error != nil) { // Error.
        return;
    }
}];

Receive messages through an event delegate

The ability of the setEventHandlerConnectBlock: is now replaced with the SBDChannelDelegate class. You can create and manage multiple channel delegates. See the Event Delegate page for more information.

Light Color Skin
Copy
// v2
[SendBird setEventHandlerConnectBlock:^(SendBirdChannel *channel) {

} errorBlock:^(NSInteger code) {

} ...

}];

// v3
@interface ChattingViewController : UIViewController<SBDChannelDelegate>

@end

@implementation OpenChannelChattingViewController

- (void)initViewController {
    [SBDMain addChannelDelegate:self identifier:self.description];
}

- (void)dismissCurrentViewController {
    [SBDMain removeChannelDelegateForIdentifier:self.description];
}

- (void)channel:(SBDBaseChannel * _Nonnull)sender didReceiveMessage:(SBDBaseMessage * _Nonnull)message {

}

@end

Load previous messages in a channel

Light Color Skin
Copy
// v2
[[SendBird queryMessageListInChannel:CHANNEL_URL prevWithMessageTs:LLONG_MAX andLimit:LIMIT resultBlock:^(NSMutableArray *queryResult) {

}];

// v3
SBDPreviousMessageListQuery *previousMessageQuery = [self.channel createPreviousMessageListQuery];
[previousMessageQuery loadPreviousMessagesWithLimit:LIMIT reverse:YES completionHandler:^(NSArray<SBDBaseMessage *> * _Nullable messages, SBDError * _Nullable error) {
    if (error != nil) { // Error.
        return;
    }    
}];

Monitor group channels with a notification handler

Also, the ability of the registerNotificationHandlerMessagingChannelUpdatedBlock: in v2 is now replaced with the SBDChannelDelegate. See the Event Delegate page for more information.

Light Color Skin
Copy
// v2
[SendBird registerNotificationHandlerMessagingChannelUpdatedBlock:^(SendBirdMessagingChannel *channel) {
    
} mentionUpdatedBlock:^(SendBirdMention *mention) {
    
}];

// v3
@interface ChattingViewController : UIViewController<SBDChannelDelegate>

@end

@implementation OpenChannelChattingViewController

- (void)initViewController {
    [SBDMain addChannelDelegate:self identifier:self.description];
}

- (void)dismissCurrentViewController {
    [SBDMain removeChannelDelegateForIdentifier:self.description];
}
@end

Retrieve a list of all members of a channel

Light Color Skin
Copy
// v2
[messagingChannel members];

// v3
[messagingChannel members];

Typing Indicators

Light Color Skin
Copy
// v2
[SendBird typeStart];
[SendBird typeEnd];

// v3
[groupChannel startTyping];
[groupChannel endTyping];

Retrieve the read receipts of members

With v3, there is more than one way to retrieve read receipts. You can get a timestamp for a specific member as did in v2 or get the automatically calculated read receipts.

Light Color Skin
Copy
// v2
long timestamp = [messagingChannel getLastReadMillis:USER_ID];

// v3
long timestamp = [groupChannel getLastSeenAtByUserId:USER_ID];
int unreadCount = [channel getReadReceiptOfMessage:msg];

Broadcast the read status of a message

Light Color Skin
Copy
// v2
[SendBird markAsRead];

// v3
[groupChannel markAsRead];

Channel metadata

You can create, update, and read metadata and metacounter in v3.

Light Color Skin
Copy
// v2
[SendBird queryChannelMetaDataWithChannelUrl:CHANNEL_URL] setMetaData:DATA_DICTIONARY resultBlock:^(NSDictionary *response) {
    
} endBlock:^(NSInteger code) {
    
}];
[SendBird queryChannelMetaDataWithChannelUrl:CHANNEL_URL] getMetaDataWithKeys:KEYS resultBlock:^(NSDictionary *response) {
    
} endBlock:^(NSInteger code) {
    
}];

// v3
[channel createMetaData:DATA_DICTIONARY completionHandler:^(NSDictionary<NSString *,NSString *> * _Nullable metaData, SBDError * _Nullable error) {

}];
[channel updateMetaData:DATA_DICTIONARY completionHandler:^(NSDictionary<NSString *,NSObject *> * _Nullable metaData, SBDError * _Nullable error) {
          
}];
[channel getMetaDataWithKeys:KEYS completionHandler:^(NSDictionary<NSString *,NSObject *> * _Nullable metaData, SBDError * _Nullable error) {
         
}];

Channel metacounter

Light Color Skin
Copy
// v2
[SendBird queryChannelMetaCounterWithChannelUrl:CHANNEL_URL] increaseMetaCounterWithKey:KEY andAmount:AMOUNT resultBlock:^(NSDictionary<NSString*,NSNumber*> *response) {
    
} endBlock:^(NSInteger code) {
    
}];
[SendBird queryChannelMetaCounterWithChannelUrl:CHANNEL_URL] getMetaCounterWithKeys:KEYS resultBlock:^(NSDictionary *response) {
    
} endBlock:^(NSInteger code) {
    
}];

// v3
[channel increaseMetaCounters:COUNTER_DICTIONARY completionHandler:^(NSDictionary<NSString *,NSNumber *> * _Nullable metaCounters, SBDError * _Nullable error) {
    if (error != nil) { // Error.
        return;
    }
}];
[channel getMetaCountersWithKeys:KEYS completionHandler:^(NSDictionary<NSString *,NSNumber *> * _Nullable metaCounters, SBDError * _Nullable error) {
    if (error != nil) { // Error.
        return;
    }
}];

Event delegate

Also, the abilities of the registerNotificationHandlerMessagingChannelUpdatedBlock:, setEventHandlerConnectBlock:, and setSystemEventReceivedBlock: are all replaced with the SBDChannelDelegate. Your client app can get notified through channel delegates which support a variety of events. See the Event Delegate page for more information.


Push notifications

To register an app-specific device token of the current user to SendBird server in v3, it is recommended that you call the registerDevicePushToken:completionHandler: right after a connection is established. See the Push Notifications page for more information.

Light Color Skin
Copy
// v2 (AppDelegate.m)
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)devToken {
    // We recommend to run the below code when the notification setting of your app is a default value or the setting is true.
    [SendBird registerForRemoteNotifications:devToken];
}

// v3 (AppDelegate.m)
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)devToken {
    // ...

    // Save devToken to your own global variable.
    [SBDMain registerDevicePushToken:tempPushToken completionHandler:^(SBDPushTokenRegistrationStatus status, SBDError * _Nullable error) {
        if (error != nil) { // Error.
            // Registration failed.
            return;     
        }   
        else {
            if (status == SBDPushTokenRegistrationStatusPending) {
                // Registration is pending.
                // If you get this status, invoke `+ registerDevicePushToken:completionHandler:` with `[SBDMain getPendingPushToken]` after connection.
            }
            else {
                // Registration succeeded.
            }
        }
    }];
}

// v3 (ViewController.m)
[SBDMain connectWithUserId:self.userIdTextField.text completionHandler:^(SBDUser * _Nullable user, SBDError * _Nullable error) {
    [SBDMain registerDevicePushToken:[SBDMain getPendingPushToken] completionHandler:^(SBDPushTokenRegistrationStatus status, SBDError * _Nullable error) {
        if (error != nil) { // Error.
            // Registration failed.
            return;
        }
        else {
            if (status == SBDPushTokenRegistrationStatusPending) {
                NSLog(@"Push registration is pending.");
            }
            else {
                NSLog(@"APNS Token is registered.");
            }
        }
    }];
}];