Skip to contentSkip to navigationSkip to topbar
Rate this page:
On this page

Migration Guide: iOS 0.16.0


(error)

Danger

Programmable Chat has been deprecated and is no longer supported. Instead, we'll be focusing on the next generation of chat: Twilio Conversations. Find out more about the EOL process here(link takes you to an external page).

If you're starting a new project, please visit the Conversations Docs to begin. If you've already built on Programmable Chat, please visit our Migration Guide to learn about how to switch.


Changes to developer projects

changes-to-developer-projects page anchor

Overview of Changes

overview-of-changes page anchor
  • Twilio IP Messaging is now known as Twilio Programmable Chat, the classes within the iOS SDK are updated to reflect this
  • Access Manager is now an optional helper, distributed separately. You have the option to initialize with only an access token now.
  • Throughout the SDK, previously synchronous behavior has been made asynchronous and in some places paged to better address large chat instances.
  • Various minor additions and changes

  • Update your pod lines:
    • REMOVE: References to TwilioIPMessagingClient
    • REMOVE: References to TwilioCommon (if present)
    • ADD: Reference to TwilioChatClient: pod 'TwilioChatClient', '~> 0.16.0'
  • If you are keeping AccessManager integration:
    • ADD: Reference to TwilioAccessManager, if desired: pod 'TwilioAccessManager', '~> 0.1.1'
  • Update your pod repositories with: pod repo update
  • Run pod install to perform the installation. This will remove the previous TwilioIPMessagingClient and TwilioCommon components and add the TwilioChatClient and optionally TwilioAccessManager.
  • Remove the existing references and binaries TwilioIPMessagingClient.framework and TwilioCommon.framework files from your project.
  • Integrate the TwilioChatClient:
    • Drag the TwilioChatClient.framework dynamic framework from the download location into your target's Embedded Binaries section in General settings, selecting 'Copy items if needed' when prompted
    • Add a new Run Script Build Phase to remove simulator architectures during AppStore builds
      • Open the target's settings
      • Select Build Phases
      • Add a new Run Script phrase, move it to below the Embed Frameworks step if it is not there already
      • Set the command run to: bash "${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}/TwilioChatClient.framework/remove_archs"
  • If you are keeping AccessManager integration:
    • Drag the TwilioChatClient.framework dynamic framework from the download location into your target's Embedded Binaries section in General settings, selecting 'Copy items if needed' when prompted
    • Add a new Run Script Build Phase to remove simulator architectures during AppStore builds
      • Open the target's settings
      • Select Build Phases
      • Add a new Run Script phrase, move it to below the Embed Frameworks step if it is not there already
      • Set the command run to: bash "${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}/TwilioAccessManager.framework/remove_archs"

Twilio IP Messaging is now Twilio Chat, several changes are needed to your code but should be largely addressed with a simple search and replace.

As is generally advisable, ensure you have a backup of your code and/or have checked in any uncommitted changes to your SCM before making these changes.

Review then perform a search and replace within your project on the following. IMPORTANT: You must match case on the search and replaces or they will likely apply incorrectly.

Objective-C

objective-c page anchor
  • TwilioIPMessaging to TwilioChat
  • TWM to TCH
  • ipMessagingClient: to chatClient:
  • Update ipMessagingClientWithAccessManager to chatClientWithToken and pass in a string Access Token instead of AccessManager (whether you are keeping AccessManager or not)
  • TwilioIPMessaging to TwilioChat
  • TWM to TCH
  • ipMessagingClient( to chatClient(
  • Update TwilioIPMessagingClient.init(accessManager: to TwilioChatClient.init(token: and pass in a string Access Token instead of AccessManager (whether you are keeping AccessManager or not) Deprecations and Changes:
TCHChannels
tchchannels page anchor

TCHChannels no longer has an allObjects method. User and unjoined public channels are now separately loaded and available through asynchronous accessors detailed below.

User and unjoined public channels are now separate in the system. You can access a user's channels with the new userChannelsWithCompletion: method. You can also obtain a list of public channels with the publicChannelsWithCompletion:. Both calls return a paginator and may page results. You can access the items for a given paginator with getItems. To determine if another page is present, you can query the boolean method hasNextPage. To load subsequent pages of results, use the requestNextPageWithCompletion: method.

Today, all user channels will be returned on the first page for userChannelsWithCompletion: but this will change in the future. Please make use of the hasNextPage method to determine completion of the query. Public channels are paged in groups of 50.

publicChannelsWithCompletion: returns a snapshot of current data for each public channel. To join a channel, you will use the sid on the channel list entry object to load the channel using the channelWithSidOrUniqueName:completion: method then call joinWithCompletion:. TCHChannels' synchronous channelWithId: and channelWithUniqueName: have been merged into a single asynchronous channelWithSidOrUniqueName:completion method which will fetch a channel by either its SID or unique name.

Added counts to user channel objects regardless of synchronization state:

  • getUnconsumedMessagesCountWithCompletion: - fetches the current number of unconsumed messages for the current user
  • getMessagesCountWithCompletion: - fetches the current number of messages on the channel
  • getMembersCountWithCompletion: - fetches the current number of members of the channel

Added createdBy property

TCHMembers no longer has an allObjects method. Members can be loaded with the asynchronous membersWithCompletion: method that returns a paginator. Today, all members will be returned on the first page but this will change in the future. Please make use of the hasNextPage method to determine completion of the query.

TWMMessages (now TCHMessages)'s allObjects method has been fully deprecated. Please use the asynchronous get*Messages family of methods as a replacement.

The synchronous messageWithIndex: and messageForConsumptionIndex: methods have been made asynchronous, accepting a callback as a parameter.

setAllMessagesConsumed now uses the most recent message on the server, rather than the client, since the most recent messages may not yet be loaded locally. Use setLastConsumedMessageIndex: or advanceLastConsumedMessageIndex: to reflect a local message id instead.

TwilioChatClientDelegate
twiliochatclientdelegate page anchor

channelAdded will no longer be called when public channels are added in the system, only upon the channel becoming part of the user channel list

channelAdded will no longer be called when public channels are added in the system, only upon the channel becoming part of the user channel list

  • Client's toastReceivedOnChannel:message: returns nil for message

Access Manager Migration

access-manager-migration page anchor

The AccessManager is optional now, and delivered separately. Your migration path here will differ depending on whether you wish to utilize the now optional AccessManager or not.

If you don't utilize AccessManager

if-you-dont-utilize-accessmanager page anchor
  • Remove references to #import <TwilioCommon/TwilioCommon.h>
  • Remove conformance declarations to the TwilioAccessManagerDelegate protocol
  • Remove TwilioAccessManagerDelegate methods accessManagerTokenExpired: and accessManager:error:
  • Remove references to TwilioAccessManager throughout your project
  • Remove references to import TwilioCommon
  • Remove conformance declarations to the TwilioAccessManagerDelegate protocol
  • Remove TwilioAccessManagerDelegate methods accessManagerTokenExpired(_ accessManager: TwilioAccessManager!) and accessManager(_ accessManager: TwilioAccessManager!, error: Error!)
  • Remove references to TwilioAccessManager throughout your project

If you are keeping AccessManager

if-you-are-keeping-accessmanager page anchor
  • Replace references to #import <TwilioCommon/TwilioCommon.h> with #import <TwilioAccessManager/TwilioAccessManager.h>
  • You will need to supply the identity for the user when you renew the token with your server, AccessManager is no longer aware of it.
  • TwilioAccessManager's delegates have changed in the following way:
    • Previously - (void)accessManagerTokenExpired:(TwilioAccessManager *)accessManager was actually called 3 minutes before expiration, it is now called at expiration. To have a chance to renew the token early, please implement - (void)accessManagerTokenWillExpire:(nonnull TwilioAccessManager *)accessManager instead which is called 3 minutes before expiration. An example:

_10
- (void)accessManagerTokenWillExpire:(TwilioAccessManager *)accessManager {
_10
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
_10
NSString *newToken = <...>;
_10
[accessManager updateToken:newToken];
_10
});
_10
}

  • - (void)accessManagerTokenExpired:(TwilioAccessManager *)accessManager is now called at token expiry.
  • - (void)accessManager:(TwilioAccessManager *)accessManager error:(NSError *)error is renamed to - (void)accessManagerTokenInvalid:(nonnull TwilioAccessManager *)accessManager and no longer passes an error object.
  • Like before, you will wish to call TwilioAccessManager 's updateToken:(NSString *)token method. Since AccessManager is no longer passed into the clients, you must register an update handler to convey token updates to your client(s). For each client you should register like this:

_10
__weak TwilioChatClient *weakClient = self.client;
_10
[self.accessManager registerClient:self.client
_10
forUpdates:^(NSString * _Nonnull updatedToken) {
_10
[weakClient updateToken:updatedToken];
_10
}];

  • Ensuring the reference to the client is weak within in block is necessary to prevent retain loops. AccessManager will weakly hold on to your client reference and cease updates when it goes out of scope - you can pass a weak or strong reference to the registerClient: method itself.
  • Replace references to import TwilioCommon with import TwilioAccessManager
  • You will need to supply the identity for the user when you renew the token with your server, AccessManager is no longer aware of it.
  • TwilioAccessManager's delegates have changed in the following way:
    • Previously accessManagerTokenExpired(_ accessManager: TwilioAccessManager!) was actually called 3 minutes before expiration, it is now called at expiration. To have a chance to renew the token early, please implement accessManagerTokenWillExpire(_ accessManager: TwilioAccessManager) instead which is called 3 minutes before expiration. AccessManager is also now non-optional. An example:

_11
func accessManagerTokenWillExpire(_ accessManager: TwilioAccessManager) {
_11
if let identity = self.identity {
_11
DispatchQueue.global(qos: .background).async {
_11
let token = <...>
_11
_11
if let token = token {
_11
accessManager.updateToken(token)
_11
}
_11
}
_11
}
_11
}

  • accessManagerTokenExpired(_ accessManager: TwilioAccessManager) is now called at token expiry.
  • accessManager(_ accessManager: TwilioAccessManager!, error: Error!) is renamed to accessManagerTokenInvalid(_ accessManager: TwilioAccessManager) and no longer passes an error object.
  • Like before, you will wish to call TwilioAccessManager 's updateToken(token) method. Since AccessManager is no longer passed into the clients, you must register an update handler to convey token updates to your client(s). For each client you should register like this:

_10
if let client = self.client {
_10
self.accessManager?.registerClient(client, // should not be an optional value
_10
forUpdates: { [weak client = self.client] (token) in
_10
client?.updateToken(token)
_10
})
_10
}


Rate this page: