Changelog: Twilio IP Messaging iOS SDK
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.
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.
We recommend using these links in your projects. As we patch bugs, these links will automatically be updated with the fixes.
Links are provided to specific patch versions here. We don't recommend using these links unless you have a specific need for a certain patch of a release.
- The completion block for some operations previously would not fire in the event of a network or token related error, it will now be called consistently in the event of an error.
- The client's delegate
ipMessgingClient:onError:
is no longer called for transient network errors that result in a retry - Added connection state property to IP Messaging Client instances that indicates the last known state of the connection with Twilio. Possible values of
TWMClientConnectionState
are:
1TWMClientConnectionStateUnknown, ///< Client connection state is not yet known.2TWMClientConnectionStateDisconnected, ///< Client is offline and no connection attempt in process.3TWMClientConnectionStateConnected, ///< Client is online and ready.4TWMClientConnectionStateConnecting, ///< Client is offline and connection attempt is in process.5TWMClientConnectionStateDenied, ///< Client connection is denied because of invalid token.6TWMClientConnectionStateError ///< Client connection is in the erroneous state.
- Added IP Messaging Client delegate method which will convey changes to the connection state as they are detected:
ipMessagingClient:connectionStateChanged:
- Improved resiliency when the client is terminated without calling
shutdown
first. It was possible to receive crashes in third party crash reporters if the host application was terminated by the OS in the background or manually by the user leading to an unclean termination of the IP Messaging client. The SDK now listens for termination notification and attempts to shut down the IP Messaging client gracefully and will be more forgiving in the event this cleanup does not complete in time.
This release may be used with IP Messaging 0.15.1 posted below. It is also available in CocoaPods.
- Addresses an issue where connections lost while the application was in the background would not fail in a timely fashion upon brought back to the foreground.
This release may be used with IP Messaging 0.15.1 posted below. It is also available in CocoaPods.
- Addresses an issue where connections using IPv6 on iOS 10 may fail depending on network configuration.
- Initial memory footprint reduced
- Setting all messages read on a channel with no messages no longer results in message index 0 being set as the consumption horizon, will be nil instead
- Setting all messages read on a channel prior to accessing those messages could result in the consumption horizon not reflecting the locally loaded messages
- The *AsDate accessors no longer return nil NSDate objects in the event of a timestamp with .000 milliseconds
Note: This release of IP Messaging should be used in conjunction with the iOS Twilio Common 0.3.1 version
identity
property has been moved touserInfo.identity
- The legacy client initialization flow of synchronizing and loading every message for every channel has been removed along with the
ipMessagingClientWithAccessManager:delegate:
method. If you wish to maintain this flow, you can create aTwilioIPMessagingClientProperties
object with the following settings. Please note that the rest of the new initialization flow will also apply, please see the migration guide for detailssynchronizationStrategy = TWMClientSynchronizationStrategyAll
initialMessageCount = UINT_MAX // (UInt32.max in Swift)
- The asynchronous
channelsListWithCompletion:
has been removed, please use the synchronouschannelsList
instead after receiving notification of client synchronization. Prior to that event, this method will returnnil
- The delegate call
ipMessagingClient:channelHistoryLoaded:
has been removed, please see the newipMessagingClient:channel:synchronizationStatusChanged:
for notification of the initial message load completion or the various get messages methods onTWMMessages
for message loads after initial channel synchronization
- The delegate call
ipMessagingClient:channelHistoryLoaded:
has been removed, please see the newipMessagingClient:channel:synchronizationStatusChanged:
for notification of the initial message load completion or the various get messages methods onTWMMessages
for message loads after initial channel synchronization
- The
loadChannelsWithCompletion:
method has been removed, this operation is now performed internally during client synchronization when necessary
identity
property has been moved touserInfo.identity
TWMMessages
now has asetNoMessagesConsumed
method. This will reset the user's consumption horizon on the channel to no messages having been seen
- Messages now have developer definable attributes
- Channel has dateCreated and dateUpdated methods (with
*AsDate
variants for nativeNSDate*
objects) - Added reachability support:
- (BOOL)isReachabilityEnabled - indicates if reachability is available for the client's instance
- (void)ipMessagingClient:userInfo:updated: will alert to online and notifiable changes for the userInfo for the specified user
- (void)ipMessagingClient:channel:member:userInfo:updated: will alert to online and notifiable changes for the userInfo for the specified user
- (BOOL)isOnline - indicates whether the user is online
- (BOOL)isNotifiable - indicates whether the user is notifiable
- Synchronize completion block will now be executed at the appropriate time when called while a channel is in the process of being joined
- identity property is moved to userInfo.identity
- The legacy client initialization flow of synchronizing and loading every message for every channel will be removed along with the ipMessagingClientWithAccessManager:delegate: method. If you wish to maintain this flow, you can create a TwilioIPMessagingClientProperties object with the following settings. Please note that the rest of the new initialization flow will also apply, please see the migration guide for details. synchronizationStrategy = TWMClientSynchronizationStrategyAll initialMessageCount = UINT_MAX
- The asynchronous channelsListWithCompletion: will be removed, please use the synchronous channelsList instead after receiving notification of client synchronization. Prior to that event, this method will return nil.
- The delegate call ipMessagingClient:channelHistoryLoaded: will be removed, please see the new ipMessagingClient:channel:synchronizationStatusChanged: for notification of the initial message load completion or the various get messages methods on TWMMessages for message loads after initial channel synchronization.
- The delegate call ipMessagingClient:channelHistoryLoaded: will be removed, please see the new ipMessagingClient:channel:synchronizationStatusChanged: for notification of the initial message load completion or the various get messages methods on TWMMessages for message loads after initial channel synchronization.
- The loadChannelsWithCompletion: method is deprecated, this operation is now performed internally during client synchronization when necessary.
- identity property is moved to userInfo.identity
With this release of IP Messaging, we have introduced a new client and channel initialization flow. For 0.14.1, both the legacy initialization flow and the new flow are supported. In a near future release, we will be removing the now deprecated legacy initialization flow.
- Client loaded all channels and all members and messages on every channel upon startup
- To initialize channels
channelsListWithCompletion:
was called thenloadChannelsWithCompletion:
upon the resultant channels list - All messages were loaded and available upon client initialization
- Monitoring the
-ipMessagingClient:channelHistoryLoaded:
delegate callback indicated when each channel was fully ready
- Flexible control over whether channels are "synchronized" on startup
- Control over how many messages (0 .. ∞) are implicitly loaded when a joined channel is initially synchronized
- Explicit delegate callbacks are triggered at granular steps during client and channel initialization
- There exists an overall delegate callback and state which can be monitored for full client availability
Your existing code will continue to function using the original client initialization semantics but to take advantage of the new functionality, the follow changes must be made all together:
- Call the client creation method which takes a TwilioIPMessagingProperties object. This can be nil to use the current defaults.
- When using the new client creation scheme, the following methods have changed behavior:
channelsListWithCompletion:
returns an error and will be deprecated in an upcoming release, please use the synchronouschannelsList
instead. Note this will be nil until the client is synchronized to at least theTWMClientSynchronizationStatusChannelsListCompleted
status.- The
ipMessagingClient:channelHistoryLoaded:
method will no longer be called after messages are loaded. If your synchronization policy has full channel history loading (messagesToLoad == UINT_MAX) then history is available upon the channel reaching TWMChannelSynchronizationStatusAll status or thesynchronizeWithCompletion:
block is executed upon a successful synchronize. - TWMChannel
members
andmessages
will no longer block if the channel has not completed synchronization (TWMChannelSynchronizationStatusAll), they will immediately return nil
- Call
synchronizeWithCompletion:
for any channels you wish to interact with if your client synchronization strategy was specified asTWMClientSynchronizationStrategyChannelsList
- Monitor the
ipMessagingClient:synchronizationStatusChanged:
delegate method for updates to the synchronization status.TWMClientSynchronizationStatusChannelsListCompleted
indicates the channel objects are available and theTWMClientSynchronizationStatusCompleted
callback indicates the channel's data, including the specified number of initial messages, are ready.
- Use a default TwilioIPMessagingClientProperties object or nil passed to the
ipMessagingClientWithAccessManager:properties:delegate:
method - Listen to the TwilioIPMessagingClient's delegate callback for
ipMessagingClient:synchronizationStatusChanged:
. If 'status' is TWMClientSynchronizationStatusChannelsListCompleted, display the channels to the user you obtain from [client.channelsList allObjects] - When the user chooses a channel, verify its synchronizationStatus is TWMChannelSynchronizationStatusAll. If it is, you can operate on the channel normally; if it is not, the channel is not yet synchronized so you must call synchronizeWithCompletion:. Upon the completion block's calling with a successful result, the channel is fully ready to use. To ensure all channels are ready on demand you may use the synchronization strategy TWMClientSynchronizationStrategyAll in the client properties object but startup time will be longer as a result.
- (ADDED) TWMClientSynchronizationStrategy
- (ADDED) TWMClientSynchronizationStatus
- (ADDED) TWMChannelSynchronizationStatus
- (MOVED) TWMUserInfoUpdate (moved from TWMUserInfo header file, no other changes)
- (ADDED) TWMMessagesCompletion
- (ADDED) TWMClientSynchronizationStatus synchronizationStatus
- (ADDED) + (TwilioIPMessagingClient *)ipMessagingClientWithAccessManager:properties:delegate:
- (DEPRECATED) + (TwilioIPMessagingClient *)ipMessagingClientWithAccessManager:delegate:
- (ADDED) - (TWMChannels *)channelsList
- (DEPRECATED) - (void)channelsListWithCompletion:(TWMChannelListCompletion)completion
- (ADDED) TWMClientSynchronizationStrategy synchronizationStrategy
- (ADDED) uint initialMessageCount
- (ADDED) - (void)ipMessagingClient:synchronizationStatusChanged:
- (ADDED) - (void)ipMessagingClient:channel:synchronizationStatusChanged:
- (DEPRECATED) - (void)ipMessagingClient:channelHistoryLoaded:
- (DEPRECATED) - (void)loadChannelsWithCompletion:
- (ADDED) TWMChannelSynchronizationStatus synchronizationStatus
- (ADDED) - (void)synchronizeWithCompletion:
- (ADDED) - (void)ipMessagingClient:channel:synchronizationStatusChanged:
- (DEPRECATED) - (void)ipMessagingClient:channelHistoryLoaded:
- (ADDED) - (void)getLastMessagesWithCount:completion:
- (ADDED) - (void)getMessagesBefore:withCount:completion:
- (ADDED) - (void)getMessagesAfter:withCount:completion:
- (DEPRECATED) - (NSArray<TWMMessage *> *)allObjects
- (ADDED) NSDate *lastConsumptionTimestampAsDate
- (ADDED) NSDate *timestampAsDate
- (ADDED) NSDate *dateUpdatedAsDate
- Fixed a bug where AccessManager did not correctly report the token
expired
status after the application returned to the foreground
- Issue with SSL connectivity resolved on older 32bit simulators (iPhone 4S and prior) - requires the new Twilio Commons 0.2.1 (see below)
- You now have the ability to affect the level of verbosity of logging within the IP Messaging framework. You may set the logging level with the class method
+setLogLevel:
on the TwilioIPMessagingClient object at any time, including pre-initialization. See the header file or documentation for supported logging levels. During beta, the default logging level will remainTWMLogLevelDebug
. - Completion blocks now will convey failure reason details instead of a Success or Failure enumeration.
Breaking Changes: Twilio IP Messaging 0.14 brings a number of very useful changes which will require some changes in your pre-existing code.
The biggest change in 0.14 is the introduction of more descriptive responses in the event of an error during an operation. Previously, all callback blocks for IP Messaging operations returned a enumeration TWMResult
which had a Success or Failure value.
TWMResult
is now a full object with a new property and Boolean method available:
- (BOOL)isSuccessful
will return YES if the operation was successful or NO in the event of failure.
- (TWMError *)error
will hold an NSError derived object describing the nature of the failure, if the operation is not successful.
To adopt the new error reporting scheme, you should:
- Modify any references to
TWMResult
to be an object referenced,TWMResult *
instead of an enumeration scalar. - Modify any comparisons of
TWMResult
againstTWMResultSuccess
to instead verify the- (BOOL)isSuccessful
method returns YES - Expand and comparisons of
TWMResult
againstTWMResultFailure
to compare- (BOOL)isSuccessful
against NO and optionally interrogate theerror
property for additional details.
- On the TWMChannels object, the
-createChannelWithFriendlyName:type:completion:
method has been retired. Please see the-createChannelWithOptions:completion:
method for its replacement. - On the TwilioIPMessagingClient object, the
+ipMessagingClientWithToken:delegate:
method has been retired. Please see the+ipMessagingClientWithAccessManager:delegate:
method for its replacement. - The unused TWMErrorCodeKey constant has been removed from the TWMError header file.
- Addressed an issue with 32Bit platform builds and SSL
- Extensible UserInfo with FriendlyName and Attributes
- The user associated with the client as well as every member in channels has a TWMUserInfo object. TwilioIPMessagingClient and TWMMember have
userInfo
properties for the logged in user and each channel member's UserInfo respectively. - A user or channel members TWMUserInfo object is shared for a given identity, meaning any attributes or friendly name set on one member will be available in all channels.
- The TwilioIPMessagingClient class has an additional delegate callback,
ipMessagingClient:userInfo:changed:
, which will be called when the UserInfo changes for the logged in user or any user that is a member of a subscribed channel. - The TWMChannel class has an additional delegate callback,
ipMessagingClient:channel:member:userInfo:changed:
, which will be called when the user info changes for a given member. - The TWMUserInfoUpdate property will indicate what changed for the above userInfo:changed: events.
- The TWMChannel class now has a
memberWithIdentity:
method to obtain a reference to the TWMMember by identity.
- It is now possible to invite or add members to a channel you created without joining it first.
- Fix for duplicated session initialization which could result in duplicate callbacks after token renewal.
- The completion handler when deleting a channel sometimes does not execute. This will be fixed in a near-future release.
- The
identity
property on TWMMember and TwilioIPMessagingClass are now deprecated and will be removed in a future release. The preferred way to obtain the identity for these objects is with the new userInfo class, for example:member.userInfo.identity
.
- Message Consumption Horizon and Read Status
- Usage: When you consume a message, call one of three methods on the TWMMessages class:
- setLastConsumedMessageIndex: - updates the last consumed index to the value specified, if you set an 'earlier' message as the last consumed, it will move the pointer 'backwards'
- advanceLastConsumedMessageIndex: - updates the last consumed index to the value specified but only if the new value is > the existing value in the client
- setAllMessagesConsumed - updates the last consumed index to the index of the newest message known to the client
- messageForConsumptionIndex: - Returns the oldest message starting at index. If the message at index exists, it will be returned otherwise the next oldest message that presently exists will be returned. To see what your last consumed message for a given channel's TWMMessages are you can call:
- lastConsumedMessageIndex - returns the message index of the last message reported as consumed; this will return nil if you have not consumed any messages on this channel yet. Note that the index this returns may not exist anymore in the system. To determine a TWMMessage's index, a new method exists:
- index - returns the index of this TWMMessage To obtain a TWMMessage by its index from the TWMMessages collection:
- messageWithIndex: - returns the TWMMessage, if it exists, with the specified index Each TWMMember on a channel may have a consumption status:
- lastConsumedMessageIndex - returns the index of the last consumed message for this user or nil if no consumption status is available
- lastConsumptionTimestamp - returns the timestamp this user last updated their consumption status or nil if no consumption status is available
- Events fired:
- When a member on a channel you are on updates their consumption horizon - ipMessagingClient:channel:memberChanged:
- When you consume a message on a channel you are on - ipMessagingClient:channelChanged:, ipMessagingClient:channel:memberChanged:
- Usage: When you consume a message, call one of three methods on the TWMMessages class:
With this release, the mechanism for installing the IP Messaging framework with Cocoapods has changed. Instead of including two static links in your Podfile, you will instead specify a custom source
at the top of your Podfile and a single pod line:
1source 'https://github.com/twilio/cocoapod-specs'23pod 'TwilioIPMessagingClient'4
After making this change to your Podfile, run pod install
. For future IP Messaging updates, you can run pod update
to update IP Messaging and Common.
- Fixed a bug whereby automatic Twilsock reconnection did not always occur when moving into a foreground state
- Identity method on TwilioIPMessagingClient will now return the identity on the TwilioAccessManager class if one was able to be parsed from the JWT
- removed '-read_only_relocs' directive in podspec file
- Can now run alongside the Twilio Voice iOS SDK in a single iOS application.
- Attributes hash passed in createChannel options is now applied on channel creation.
- A single message changed event is triggered when a message is updated. In previous releases, multiple message changed events could fire for a single message update.
- A participant will no longer miss channel updates after leaving and re-joining the same channel in a single session.
- Member identities containing spaces are now able to join channels.
- Improved handling of update token actions which occur after the previous token has already expired.
- You may see an erroneous
CRITICAL
messages in the log related to not enough free threads; this error can be safely disregarded. - Users will not be notified of invitations to a private channel after they have previously declined an invitation to the same channel.
- Calling shutdown on a
TwilioIPMessagingClient
may take up to 30 seconds for a particularly busy instance. You should call this on a background thread to avoid blocking your main UI thread. Be sure to keep a strong reference to the client until this synchronous method returns. - Only Access Tokens provide expiry events. Capability Tokens, an authentication format used earlier during the IP Messaging Private Beta, do not raise expiry events.
TwilioAccessManager
may deadlock when updating the Access Token from the same thread that is handling thetokenExpired
delegate callback. Use a separate thread in order to ensure theupdateToken
operation does not block thetokenExpired
callback.- Twilio recommends using a minimum Access Token TTL of 4 minutes;
TwilioAccessManager
will alert the client 3 minutes prior to expiry to ensure sufficient time to obtain and set a new token before expiry. tokenExpired
event is called not at expiry but 3 minutes prior to ensure sufficient time to update to new token.
- The
TwilioIPMessagingClient
initialization methodipMessagingClientWithToken:
will be retired in favor ofipMessagingClientWithAccessManager:
. - The
createChannelWithFriendlyName:type:completion:
method onTWMChannels
will be retired in favor ofcreateChannelWithOptions:
, which takes anNSDictionary
of options.
- TwilioIPMessagingClient's
updateToken
method will now recover gracefully if a user's token has been allowed to completely expire.
- Inviting a user to a private channel after they have previously declined an invitation to that channel will not notify the user of the invitation.
- Calling shutdown on a
TwilioIPMessagingClient
may take up to 30 seconds for a particularly busy instance. You should call this on a background thread to avoid blocking your main UI thread. Be sure to keep a strong reference to the client until this synchronous method returns. - Only Access Tokens provide expiry events. Capability Tokens, an authentication format used earlier during the IP Messaging Private Beta, do not raise expiry events.
TwilioAccessManager
may deadlock when updating the Access Token from the same thread that is handling thetokenExpired
delegate callback. Use a separate thread in order to ensure theupdateToken
operation does not block thetokenExpired
callback.- Twilio recommends using a minimum Access Token TTL of 4 minutes;
TwilioAccessManager
will alert the client 3 minutes prior to expiry to ensure sufficient time to obtain and set a new token before expiry. tokenExpired
event is called not at expiry but 3 minutes prior to ensure sufficient time to update to new token.
- The
TwilioIPMessagingClient
initialization methodipMessagingClientWithToken:
will be retired in favor ofipMessagingClientWithAccessManager:
. - The
createChannelWithFriendlyName:type:completion:
method onTWMChannels
will be retired in favor ofcreateChannelWithOptions:
, which takes anNSDictionary
of options.
- TwilioIPMessagingClient.framework has a new dependency, twilio-rtc-common, which must be added to your project alongside ip-messaging. See the instructions here to download twilio-rtc-common or to install it using Cocoapods.
- The
updateToken:completion:
method onTwilioIPMessagingClient
has been removed in favor of relaying token updates throughTwilioAccessManager
- The class prefixes have changed from TW to TWM. New class prefixes are below.
Classes:
1TMChannel -> TWMChannel2TMChannels -> TWMChannels3TMMember -> TWMMember4TMMembers -> TWMMembers5TMMessage -> TWMMessage6TMMessages -> TWMMessages7TMError -> TWMError
Delegates:
TMChannelDelegate -> TWMChannelDelegate
Enumerations:
1TMChannelTypeEnum -> TWMChannelType2TMChannelTypePublic -> TWMChannelTypePublic3TMChannelTypePrivate -> TWMChannelTypePrivate45TMResultEnum -> TWMResult6TMResultSuccess -> TWMResultSuccess7TMResultFailure -> TWMResultFailure89TMChannelStatusEnum -> TWMChannelStatus10TMChannelStatusNotParticipating -> TWMChannelStatusNotParticipating11TMChannelStatusJoined -> TWMChannelStatusJoined12TMChannelStatusInvited -> TWMChannelStatusInvited
Blocks:
1TSCompletion -> TWMCompletion2TMChannelListCompletion -> TWMChannelListCompletion3TMChannelCompletion -> TWMChannelCompletion
TwilioAccessManager
is a new class for managing the Access Token lifecycle. This class provides token lifecycle events and mechanism to update the token used by clients through its delegate and exposes a standard interface for managing tokens across both Twilio IP Messaging and Twilio Video SDKs. You can see an example of how to use this new class in the IP Messaging Quickstart Guide.
- Only Access Tokens provide expiry events. Capability Tokens, an authentication format used earlier during the IP Messaging Private Beta, do not raise expiry events.
TwilioAccessManager
may deadlock when updating the Access Token from the same thread that is handling thetokenExpired
delegate callback. Use a separate thread in order to ensure theupdateToken
operation does not block thetokenExpired
callback.- Twilio recommends using a minimum Access Token TTL of 4 minutes;
TwilioAccessManager
will alert the client 3 minutes prior to expiry to ensure sufficient time to obtain and set a new token before expiry. tokenExpired
event is called not at expiry but 3 minutes prior to ensure sufficient time to update to new token
- The
TwilioIPMessagingClient
initialization methodipMessagingClientWithToken:
will be retired in favor ofipMessagingClientWithAccessManager:
. - The
createChannelWithFriendlyName:type:completion:
method onTWMChannels
will be retired in favor ofcreateChannelWithOptions:
, which takes anNSDictionary
of options.