# Presence
## Presence PropertiesARTPresence PropertiesAbly::Realtime::Presence Attributesio.ably.lib.realtime.Presence MembersIO.Ably.Realtime.Presence Properties
The `Presence` object exposes the following public propertiesattributesmembers:
### syncCompletesync_complete?SyncComplete
A `boolean` field indicating whether the presence member set is synchronized with server after a channel attach.
When a channel is attached, the Ably service immediately synchronizes the presence member set with the client. Typically this process completes in milliseconds, however when the presence member set is very large, bandwidth constraints may slow this synchronization process down.
## Methods
### enterEnterAsync
In order to enter and be present on a channel, the client must [be identified by having a client ID](https://faqs.ably.com/authenticated-and-identified-clients), [have permission to be present](https://faqs.ably.com/using-capabilities-to-manage-client-access-privileges-on-channels), and be attached to the channel. For simplicity, the library will implicitly attach to a channel when entering. Entering when already entered is treated as an [update](#update).
There are two overloaded versions of this method. With both versions, a callbackblockcompletion listener can optionally be passed in to be notified of success or failure to enter.
`Deferrable enter() -> yields`
`void enter(CompletionListener listener)`
`enter(data: nil, callback: ((ARTErrorInfo?) -> Void)?)`
`Task EnterAsync()`
Enter a presence channel without any data. If the channel is `initialized` (i.e. no attempt to attach has yet been made for this channel), then calling `enter` will implicitly attach the channel.
`enter(Object data, callback(ErrorInfo err))`
`Deferrable enter(Object data) -> yields`
`void enter(Object data, CompletionListener listener)`
`enter(data: AnyObject?, callback: ((ARTErrorInfo?) -> Void)?)`
`Task EnterAsync(object clientData)`
Enter a presence channel and provide data that is associated with the current present member. If the channel is `initialized` (i.e. no attempt to attach has yet been made for this channel), then calling `enter` will implicitly attach the channel.
`enter(Object data?): Promise`
Enter a presence channel with optional data that is associated with the current present member. If the channel is `initialized` (i.e. no attempt to attach has yet been made for this channel), then calling `enter` will implicitly attach the channel.
#### Parameters
| Parameter | Description | Type |
|-----------|-------------|------|
| data | data payload for the current present member. The supported payload types are Strings, JSON objects and arrays, buffers containing arbitrary binary data, and nullstrings, plain object convertible to json, binary data as byte arrays, and null. | `Object` |
| Parameter | Description | Type |
|-----------|-------------|------|
| data | data payload for the current present member. The supported payload types are Strings, JSON objects and arrays, buffers containing arbitrary binary data, and nullStrings, JsonObject, binary data as byte arrays, and nullStrings, Hash or Array objects that can be serialized to JSON using `to_json`, binary data as `ASCII-8BIT` byte arrays, and nullThe supported payload types are `NS``String`, `NS``Dictionary` or `NS``Array` objects that can be serialized to JSON, binary data as `NSData`, and `nil`. | `Object` |
| listener&blockcallback | Listener to be notified on completionyields upon successfully entering the channelcalled upon successfully entering the channel, or with an error | [CompletionListener](#completion-listener) |
#### Returns
Returns a promise. On success, the promise resolves. On failure, the promise is rejected with an [ErrorInfo](https://ably.com/docs/api/realtime-sdk/types#error-info) object that details the reason why it was rejected.
#### Callback result
On successfully entering the channel, `err` is null. On failure to enter, `err` contains an [ErrorInfo](#error-info) object describing the failure reason.
#### Listener result
On successfully entering the channel, the `onSuccess` method of the [CompletionListener](#completion-listener) is called. On failure to enter, the `onError` method is called with an [ErrorInfo](#error-info) argument describing the failure reason.
#### Task result
On successfully entering the channel, the method will complete. On failure to enter, an `AblyException` will be thrown with an [ErrorInfo](#error-info) object describing the failure reason.
#### Returns
A [Deferrable](https://ably.com/docs/api/realtime-sdk/types#deferrable) object is returned from the method.
On successfully entering the channel, the registered success blocks for the [Deferrable](https://ably.com/docs/api/realtime-sdk/types#deferrable) and any block provided to the method are executed. On failure to enter, the `errback` callbacks of the [Deferrable](https://ably.com/docs/api/realtime-sdk/types#deferrable) are called with an [ErrorInfo](#error-info) argument describing the failure reason.
### leaveLeave
In order to leave the presence set of a channel, the client must have already [entered and been present](#enter).
There are two overloaded versions of this method. With both versions, a callbackblockcompletion listener can optionally be passed in to be notified of success or failure to leave.
`Deferrable leave() -> yields`
`void leave(CompletionListener listener)`
`leave(data: nil, callback: ((ARTErrorInfo?) -> Void)?)`
`Task LeaveAsync()`
Leave a presence channel without emitting any data.
`leave(Object data, callback(ErrorInfo err))`
`Deferrable leave(Object data) -> yields`
`void leave(Object data, CompletionListener listener)`
`leave(data: AnyObject?, callback: ((ARTErrorInfo?) -> Void)?)`
`Task LeaveAsync(object clientData)`
Leave a presence channel and emit data that is associated with the current leaving member.
`leave(Object data?): Promise`
Leave a presence channel and emit an optional data that is associated with the current leaving member.
#### Parameters
| Parameter | Description | Type |
|-----------|-------------|------|
| data | data payload for the current present member. The supported payload types are Strings, JSON objects and arrays, buffers containing arbitrary binary data, and nullstrings, plain objects convertible to json, binary data as byte arrays, and null. | `Object` |
| Parameter | Description | Type |
|-----------|-------------|------|
| data | data payload for the current present member. The supported payload types are Strings, JSON objects and arrays, buffers containing arbitrary binary data, and nullStrings, JsonObject, binary data as byte arrays, and nullStrings, Hash or Array objects that can be serialized to JSON using `to_json`, binary data as `ASCII-8BIT` byte arrays, and nullThe supported payload types are `NS``String`, `NS``Dictionary` or `NS``Array` objects that can be serialized to JSON, binary data as `NSData`, and `nil`. | `Object` |
| listener&blockcallback | Listener to be notified on completionyields upon successfully leaving the channelcalled upon leaving the channel, or with an error | [CompletionListener](#completion-listener) |
#### Returns
Returns a promise. On success, the promise resolves. On failure, the promise is rejected with an [ErrorInfo](https://ably.com/docs/api/realtime-sdk/types#error-info) object that details the reason why it was rejected.
#### Callback result
On successfully leaving the channel, `err` is null. On failure to leave, `err` contains an [ErrorInfo](#error-info) object describing the failure reason.
#### Listener result
On successfully leaving the channel, the `onSuccess` method of the [CompletionListener](#completion-listener) is called. On failure to leave, the `onError` method is called with an [ErrorInfo](#error-info) argument describing the failure reason.
#### Task result
On successfully leaving the channel, the method will complete. On failure to leave, an `AblyException` will be thrown with an [ErrorInfo](#error-info) object describing the failure reason.
#### Returns
A [Deferrable](https://ably.com/docs/api/realtime-sdk/types#deferrable) object is returned from the method.
On successfully leaving the channel, the registered success blocks for the [Deferrable](https://ably.com/docs/api/realtime-sdk/types#deferrable) and any block provided to the method are executed. On failure to leave, the `errback` callbacks of the [Deferrable](https://ably.com/docs/api/realtime-sdk/types#deferrable) are called with an [ErrorInfo](#error-info) argument describing the failure reason.
### updateUpdate
Clients can update their member data on the channel which will trigger a broadcast of this update to all presence subscribers. The [pre-requisites for](#update) `update``Update` are the same as for [`enter`](#enter).[`Enter`](#enter). If an attempt to `update``Update` is made before the client has entered the channel, the update is treated as an `enter``Enter`.
A callbackblockcompletion listener can optionally be passed in to be notified of success or failure to update the member data.
`update(Object data, callback(ErrorInfo err))`
`update(Object data?): Promise`
`Deferrable update(Object data) -> yields`
`void update(Object data, CompletionListener listener)`
`update(data: AnyObject?, callback: ((ARTErrorInfo?) -> Void)?)`
`Task UpdateAsync(object clientData)`
Update the current member's data and broadcast an update event to all subscribers. `data` may be `null`. If the channel is `initialized` (i.e. no attempt to attach has yet been made for this channel), then calling `update` will implicitly attach the channel.
#### Parameters
| Parameter | Description | Type |
|-----------|-------------|------|
| data | data payload for the current present member. The supported payload types are Strings, JSON objects and arrays, buffers containing arbitrary binary data, and nullstrings, plain objects convertible to json, binary data as byte arrays, and null. | `Object` |
| Parameter | Description | Type |
|-----------|-------------|------|
| data | data payload for the current present member. The supported payload types are Strings, JSON objects and arrays, buffers containing arbitrary binary data, and nullStrings, JsonObject, binary data as byte arrays, and nullStrings, Hash or Array objects that can be serialized to JSON using `to_json`, binary data as `ASCII-8BIT` byte arrays, and nullThe supported payload types are `NS``String`, `NS``Dictionary` or `NS``Array` objects that can be serialized to JSON, binary data as `NSData`, and `nil`. | `Object` |
| listener&blockcallback | Listener to be notified on completionyields upon successfully updating the member datacalled upon updating the channel, or with an error | [CompletionListener](#completion-listener) |
#### Returns
Returns a promise. On success, the promise resolves. On failure, the promise is rejected with an [ErrorInfo](https://ably.com/docs/api/realtime-sdk/types#error-info) object that details the reason why it was rejected.
#### Callback result
On successfully updating the data, `err` is null. On failure to update, `err` contains an [ErrorInfo](#error-info) object describing the failure reason.
#### Listener result
On successfully updating the data, the `onSuccess` method of the [CompletionListener](#completion-listener) is called. On failure to update, the `onError` method is called with an [ErrorInfo](#error-info) argument describing the failure reason.
#### Task result
On successfully entering the channel, the method will complete. On failure to enter, an `AblyException` will be thrown with an [ErrorInfo](#error-info) object describing the failure reason. The methods needs to be awaited otherwise the exception won't be thrown.
#### Returns
A [Deferrable](https://ably.com/docs/api/realtime-sdk/types#deferrable) object is returned from the method.
On successfully updating the data, the registered success blocks for the [Deferrable](https://ably.com/docs/api/realtime-sdk/types#deferrable) and any block provided to the method are executed. On failure to update, the `errback` callbacks of the [Deferrable](https://ably.com/docs/api/realtime-sdk/types#deferrable) are called with an [ErrorInfo](#error-info) argument describing the failure reason.
### getGet
Get the current presence member set for this channel. Typically, this method returns the member set immediately as the member set is retained in memory by the client. However, by default this method will wait until the presence member set is synchronized, so if the synchronization is not yet complete following a channel being attached, this method will wait until the presence member set is synchronized.
When a channel is attached, the Ably service immediately synchronizes the presence member set with the client. Typically this process completes in milliseconds, however when the presence member set is very large, bandwidth constraints may slow this synchronization process down.
When a channel is `initialized` (i.e. no attempt to attach has yet been made for this channel), then calling `get` will implicitly attach the channel.
`get(Object params?): Promise`
`get(Object options, callback(ErrorInfo err, PresenceMessage[] members))`
`Deferrable get(Hash options) -> yields PresenceMessage[]`
`PresenceMessage[] get(Param[] options)`
`get(query: ARTRealtimePresenceQuery, callback: ([ARTPresenceMessage], ARTErrorInfo?) -> Void)`
`Task> GetAsync(GetOptions { bool waitForSync = true, string clientId = "", string connectionId = "" })`
Gets an array of members present on the channel as [PresenceMessage](#presence-message) objects.
#### Parameters
| Parameter | Description | Type |
|-----------|-------------|------|
| paramsoptionsquery | an optional objectobjectset of parameters containing query parameters as specified below. | [`Param[]`](/docs/api/realtime-sdk/presence#param)`PaginatedRequestParams` |
| Parameter | Description | Type |
|-----------|-------------|------|
| optionsquery | an optional object containing query parametersan optional set of symbol key and value pairs containing the query parameters as specified below. | |
| &blockcallback | yields a [`PresenceMessage[]`](/docs/api/realtime-sdk/presence#presence-message) arraycalled with a [ARTPresenceMessage], or with an error | |
#### `options` parameters`params` parameters`ARTRealtimePresenceQuery` properties`GetOptions` properties
| Property | Description | Type |
|----------|-------------|------|
| clientId:client_id | when provided, will filter array of members returned that match the provided [clientId](https://ably.com/docs/api/realtime-sdk#client-id)[client_id](https://ably.com/docs/api/realtime-sdk#client-id)[ClientId](https://ably.com/docs/api/realtime-sdk#client-id) string | `String` |
| connectionId:connection_id | when provided, will filter array of members returned that match the provided [connectionId](https://ably.com/docs/api/realtime-sdk/connection#id)[ConnectionId](https://ably.com/docs/api/realtime-sdk/connection#id)[connection_id](https://ably.com/docs/api/realtime-sdk/connection#id) string | `String` |
| waitForSync:wait_for_sync | A boolean value that by default waits for the initial presence synchronization following channel attachment to complete before returning the members present. When false, the current list of members is returned without waiting for a complete synchronization.
_Default: true_ | `Boolean` |
#### Returns
Returns a promise. On success, the promise is fulfilled with an array of [PresenceMessage](#presence-message) objects corresponding to the current set of present members on the channel. On failure, the promise is rejected with an [ErrorInfo](https://ably.com/docs/api/realtime-sdk/types#error-info) object that details the reason why it was rejected.
#### Callback result
On success, `members` contains an array of [PresenceMessage](#presence-message) objects corresponding to the current set of present members on the channel.
On failure to retrieve the current presence member set, `err` contains an [ErrorInfo](#error-info) object with the failure reason.
#### Returns
On success, the returned array of [PresenceMessage](#presence-message) objects corresponds to the current set of present members on the channel.
Failure to retrieve the current presence member set will raise an [AblyException](https://ably.com/docs/api/realtime-sdk/types#ably-exception)
#### Returns
On success, the returned enumerable of [`#PresenceMessage`](#presence-message) objects correspond to the current set of present members on the channel.
Failure to retrieve the current presence member set will raise an [AblyException](https://ably.com/docs/api/realtime-sdk/types#ably-exception)
#### Returns
A [Deferrable](https://ably.com/docs/api/realtime-sdk/types#deferrable) object is returned from the method.
On success, the registered success blocks for the [Deferrable](https://ably.com/docs/api/realtime-sdk/types#deferrable) and any block provided to the method yield an array of [PresenceMessage](#presence-message) objects to the current set of present members on the channel.
Failure to retrieve the current presence member set will trigger the `errback` callbacks of the [Deferrable](https://ably.com/docs/api/realtime-sdk/types#deferrable) with an [ErrorInfo](#error-info) object with the failure reason.
### historyHistory
`history(Object options, callback(ErrorInfo err, PaginatedResult resultPage))`
`history(Object params?): Promise>`
`Deferrable history(Hash options) -> yields PaginatedResult`
`PaginatedResult history(Param[] options)`
`history(query: ARTRealtimeHistoryQuery?, callback: (ARTPaginatedResult?, ARTErrorInfo?) -> Void) throws`
`Task> HistoryAsync(PaginatedRequestParams query, bool untilAttach = false [deprecated])`
Gets a [paginated](#paginated-result) set of historical presence message events for this channel. If the [channel is configured to persist messages to disk](https://faqs.ably.com/how-long-are-messages-stored-for,) then the presence message event history will [typically be available for 24 - 72 hours](https://faqs.ably.com/how-long-are-messages-stored-for.) If not, presence message events are only retained in memory by the Ably service for two minutes.
#### Parameters
| Parameter | Description | Type |
|-----------|-------------|------|
| paramsoptionsquery | an optional objectobjectPaginatedRequestParams object containing query parameters, as specified in the [presence history API documentation](https://ably.com/docs/storage-history/history#presence-history) | [`Param[]`](/docs/api/realtime-sdk/presence#param)`PaginatedRequestParams` |
| Parameter | Description | Type |
|-----------|-------------|------|
| optionsquery | an optional object containing query parametersan optional set of key value pairs containing query parameters, as specified in the [presence history API documentation](https://ably.com/docs/storage-history/history#presence-history) | |
| &blockcallback | yields a `PaginatedResult` objectcalled with a `ARTPaginatedResult` object or an error | |
Further details of the supported `options` params, see [presence history API documentation](https://ably.com/docs/storage-history/history#presence-history.)
#### Returns
Returns a promise. On success, the promise is fulfilled with a [PaginatedResult](#paginated-result) object containing an array of [PresenceMessage](#presence-message) objects corresponding to the current page of results. On failure, the promise is rejected with an [ErrorInfo](https://ably.com/docs/api/realtime-sdk/types#error-info) object that details the reason why it was rejected.
#### Callback result
On success, `resultPage` contains a [PaginatedResult](#paginated-result) encapsulating an array of [PresenceMessage](#presence-message) objects corresponding to the current page of results. [PaginatedResult](#paginated-result) supports pagination using [next()](#paginated-result) and [first()](#paginated-result) methods.
On failure to retrieve message history, `err` contains an [ErrorInfo](#error-info) object with the failure reason.
#### Returns
On success, the returned [PaginatedResult](#paginated-result) encapsulates an array of [PresenceMessage](#presence-message) objects corresponding to the current page of results. [PaginatedResult](#paginated-result) supports pagination using [next](#paginated-result) and [first](#paginated-result) methods.
Failure to retrieve the message history will raise an [AblyException](https://ably.com/docs/api/realtime-sdk/types#ably-exception)
#### Returns
Returns a task that needs to be awaited.
On success, the returned [PaginatedResult](#paginated-result) encapsulates an array of [PresenceMessage](#presence-message) objects corresponding to the current page of results. [PaginatedResult](#paginated-result) supports pagination using [NextAsync](#paginated-result) and [FirstAsync](#paginated-result) methods.
Failure to retrieve the message history will raise an [AblyException](https://ably.com/docs/api/realtime-sdk/types#ably-exception.) Only if the task is awaited.
#### Returns
A [Deferrable](https://ably.com/docs/api/realtime-sdk/types#deferrable) object is returned from the method.
On success, the registered success blocks for the [Deferrable](https://ably.com/docs/api/realtime-sdk/types#deferrable) and any block provided to the method yield a [PaginatedResult](#paginated-result) that encapsulates an array of [PresenceMessage](#presence-message) objects corresponding to the current page of results. [PaginatedResult](#paginated-result) supports pagination using [next()](#paginated-result) and [first()](#paginated-result) methods.
Failure to retrieve the message history will trigger the `errback` callbacks of the [Deferrable](https://ably.com/docs/api/realtime-sdk/types#deferrable) with an [ErrorInfo](#error-info) object with the failure reason.
### subscribeSubscribe
There are overloaded versions of this method:
`subscribe(listener(PresenceMessage)): Promise`
`subscribe(listener(PresenceMessage))`
`void subscribe(PresenceListener listener)`
`subscribe → yields PresenceMessage`
`subscribe(callback: (ARTPresenceMessage) -> Void) -> ARTEventListener`
`void Subscribe(Action handler)`
Subscribe to presence message events on this channel. The caller supplies a listener functionan implementation of the [PresenceListener](#presence-listener) interfacea blocka handler, which is called each time one or more presence events occurs such as a member entering or leaving a channel.
`subscribe(String action, listener(PresenceMessage))`
`subscribe(String action, listener(PresenceMessage)): Promise`
`void subscribe(PresenceMessage.Action action, PresenceListener listener)`
`subscribe(PresenceMessage::ACTION action) → yields PresenceMessage`
`subscribe(action: ARTPresenceAction, callback: (ARTPresenceMessage) -> Void) -> ARTEventListener`
`void Subscribe(PresenceAction action, Action handler)`
Subscribe to presence message events with a given [action](#presence-action) on this channel. The caller supplies a listener functionan implementation of the [PresenceListener](#presence-listener) interfacea blocka handler, which is called each time one or more presence events occurs such as a member entering or leaving a channel.
`subscribe(String[] actions, listener(PresenceMessage))`
`void subscribe(PresenceMessage.Action[] actions, PresenceListener listener)`
`subscribe(PresenceMessage::ACTION *actions) → yields PresenceMessage`
Subscribe a single listener to messages on this channel for multiple [action](#presence-action) values.
#### Parameters
| Parameter | Description | Type |
|-----------|-------------|------|
| action | The presence [`action` event](#presence-action) to subscribe to | `String`[PresenceMessage.Action](#presence-action)[PresenceMessage::ACTION](#presence-action) action |
| actions | An argumentarray of [`action` events](#presence-action) to subscribe to | `String[]``*argument` |
| listenerlistener&block | is a function of the form `function(presenceMessage)` to be called for each matching presence message eventMessage listener to be notified for matching presence message eventyields matching presence message event when received on the channel | [`PresenceListener`](#presence-listener) |
| Parameter | Description | Type |
|-----------|-------------|------|
| action | The presence [`action` event](#presence-action) to subscribe to | `ARTPresenceAction`[PresenceAction](#presence-action) |
| callbackhandler | called with each matching [presence message](#presence-message) when received on the channel | |
#### Returns
Returns a promise. On successful channel attachment, the promise is resolved. On failure, the promise is rejected with an [ErrorInfo](https://ably.com/docs/api/realtime-sdk/types#error-info) object that details the reason why it was rejected.
#### Considerations
* If the channel is `initialized` (i.e. no attempt to attach has yet been made for this channel), then calling `subscribe` will implicitly attach the channel. However, regardless of the implicit attach outcome, the listenerblockhandler will still be registered
* If `subscribe` is called more than once with the same listenerblockhandler, then duplicates will be registered. For example, if you `subscribe` twice with the same listenerblockhandler and a presence message is later received, the same listenerblockhandler will be invoked twice
* The registered listenerblockhandler remains active on the presence channel regardless of the underlying channel state. For example, if you call `subscribe` when the underlying channel is `attached` and it later becomes `detached` or even `failed`, when the channel is reattached and a presence message is received, the listenersblockshandlers originally registered will still be invoked. Listeners are only removed when calling [unsubscribe](#unsubscribe) or when the underlying channel is `released` using the `Realtime.channels.release(name)``Realtime.Channels.Release(name)` method
* If an exception is thrown in the subscribe listener and bubbles up to the event emitter, it will be caught and logged at `error` level, so as not to affect other listeners for the same event
### unsubscribeUnsubscribe
There are sixthree overloaded versions of this method:
`unsubscribe(String action, listener)`
`unsubscribe(String action, listener)`
`void unsubscribe(PresenceMessage.Action action, PresenceListener listener)`
`unsubscribe(PresenceMessage::ACTION action, &listener_proc)`
`unsubscribe(action: ARTPresenceAction, listener: ARTEventListener)`
`bool Unsubscribe(PresenceAction presenceAction, Action handler)`
Unsubscribe the given listener from presence message events on this channel for the given [action](#presence-action.) This removes an earlier event-specific subscription.
`unsubscribe(listener)`
`unsubscribe(listener)`
`void unsubscribe(PresenceListener listener)`
`unsubscribe(&listener_proc)`
`unsubscribe(listener: ARTEventListener)`
`bool Unsubscribe(Action handler)`
Unsubscribe the given listener from presence message events on this channel. This removes an earlier subscription.
`unsubscribe(String[] actions, listener)`
Unsubscribe the given listener from all presence actions in the array.
`unsubscribe(String action)`
Unsubscribe all listeners for a given [action](#presence-action.)
`unsubscribe(String[] actions)`
Unsubscribe all listeners for all presence actions in the array.
`unsubscribe()`
`void unsubscribe()`
`unsubscribe()`
`bool Unsubscribe()`
Unsubscribes all listeners to presence message events on this channel. This removes all earlier subscriptions.
#### Parameters
| Parameter | Description | Type |
|-----------|-------------|------|
| action | The presence [`action` event](#presence-action) to unsubscribe from | `String` |
| actions | An array of actions to unsubscribe from | `String[]` |
| listener | is the callback listener function that was previously subscribed | |
| Parameter | Description | Type |
|-----------|-------------|------|
| action | The presence [`action` event](#presence-action) to unsubscribe from | [PresenceMessage.Action](#presence-action)[PresenceMessage::ACTION](#presence-action) action`ARTPresenceAction` |
| listenerhandler&listener_blocklistener | previously registered listenerpreviously registered handlerpreviously registered listener blockprevious return value from a `subscribe` call | [`PresenceListener`](#presence-listener) |
### enterCliententer_clientEnterClientAsync
Enter this presence channel for the given `clientId``client_id``ClientId`. This method is provided to support typically server instances that act on behalf of multiple client IDs. See [Managing multiple client IDs](https://ably.com/docs/presence-occupancy/presence#presence-multiple-client-id) for more info. In order to be able to publish presence changes for arbitrary client IDs, the client library must have been instantiated either with an [API key](https://ably.com/docs/auth#api-keys,) or with a [token bound to a wildcard client ID](https://faqs.ably.com/can-a-client-emulate-any-client-id-i.e.-authenticate-using-a-wildcard-client-id.)
There are two overloaded versions of this method. With both versions, a callbackblockcompletion listener can optionally be passed in to be notified of success or failure to enter.
`Deferrable enter_client(String client_id) -> yields`
`void enterClient(String clientId, CompletionListener listener)`
`enterClient(clientId: String, data: nil, callback: ((ARTErrorInfo?) -> Void)?)`
`Task EnterClientAsync(string clientId)`
Enter a presence channel on behalf of the provided `clientId``client_id``ClientId` without any data. If the channel is `initialized` (i.e. no attempt to attach has yet been made for this channel), then calling `enter` will implicitly attach the channel.
`enterClient(String clientId, Object data, callback(ErrorInfo err))`
`Deferrable enter_client(String client_id, Object data) -> yields`
`void enterClient(String clientId, Object data, CompletionListener listener)`
`enterClient(clientId: String, data: AnyObject?, callback: ((ARTErrorInfo?) -> Void)?)`
`Task EnterClientAsync(string clientId, object clientData)`
Enter a presence channel on behalf of the provided `clientId``client_id``ClientId` and provide data that is associated with the current present member. If the channel is `initialized` (i.e. no attempt to attach has yet been made for this channel), then calling `enter` will implicitly attach the channel.
`enterClient(String clientId, Object data?): Promise`
Enter a presence channel on behalf of the provided `clientId` and provide an optional data that is associated with the current present member. If the channel is `initialized` (i.e. no attempt to attach has yet been made for this channel), then calling `enter` will implicitly attach the channel.
#### Parameters
| Parameter | Description | Type |
|-----------|-------------|------|
| data | data payload for the member. The supported payload types are Strings, JSON objects and arrays, buffers containing arbitrary binary data, and nullstrings, plain object convertible to json, binary data as byte arrays, and null. | `Object` |
| Parameter | Description | Type |
|-----------|-------------|------|
| data | data payload for the member. The supported payload types are Strings, JSON objects and arrays, buffers containing arbitrary binary data, and nullStrings, JsonObject, binary data as byte arrays, and nullStrings, Hash or Array objects that can be serialized to JSON using `to_json`, binary data as `ASCII-8BIT` byte arrays, and nullThe supported payload types are `NS``String`, `NS``Dictionary` or `NS``Array` objects that can be serialized to JSON, binary data as `NSData`, and `nil`. | `Object` |
| listener&blockcallback | Listener to be notified on completionyields upon successfully entering the channelcalled upon successfully entering the channel, or with an error | [`CompletionListener`](#completion-listener) |
#### Returns
Returns a promise. On success, the promise resolves. On failure, the promise is rejected with an [ErrorInfo](https://ably.com/docs/api/realtime-sdk/types#error-info) object that details the reason why it was rejected.
#### Callback result
On successfully entering the channel, `err` is null. On failure to enter, `err` contains an [ErrorInfo](#error-info) object describing the failure reason.
#### Listener result
On successfully entering the channel, the `onSuccess` method of the [CompletionListener](#completion-listener) is called. On failure to enter, the `onError` method is called with an [ErrorInfo](#error-info) argument describing the failure reason.
#### Returns
The method returns a `Task` that will need to be awaited. On success the method will complete and will not throw an exception. On failure to enter the method will throw an `AblyException` with an [ErrorInfo](#error-info) argument describing the failure reason.
#### Returns
A [Deferrable](https://ably.com/docs/api/realtime-sdk/types#deferrable) object is returned from the method.
On successfully entering the channel, the registered success blocks for the [Deferrable](https://ably.com/docs/api/realtime-sdk/types#deferrable) and any block provided to the method are executed. On failure to enter, the `errback` callbacks of the [Deferrable](https://ably.com/docs/api/realtime-sdk/types#deferrable) are called with an [ErrorInfo](#error-info) argument describing the failure reason.
### leaveClientleave_clientLeaveClientAsync
Leave this presence channel for the given `clientId``client_id``ClientId`. This method is provided to support typically server instances that act on behalf of multiple client IDs. See [Managing multiple client IDs](https://ably.com/docs/presence-occupancy/presence#presence-multiple-client-id) for more info. In order to leave the presence set of a channel, the client must have already [entered and been present](#enter-client.)
There are two overloaded versions of this method. With both versions, a callbackblockcompletion listener can optionally be passed in to be notified of success or failure to leave.
`Deferrable leave_client(String client_id) -> yields`
`void leaveClient(String clientId, CompletionListener listener)`
`leaveClient(clientId: String, data: nil, callback: ((ARTErrorInfo?) -> Void)?)`
`Task LeaveClientAsync(string clientId, object data)`
Leave a presence channel on behalf of the provided `clientId``client_id``ClientId` without emitting any data.
`Deferrable leave_client(String client_id, Object data) -> yields`
`void leaveClient(String clientId, Object data, CompletionListener listener)`
`leave(clientId: String, data: AnyObject?, callback: ((ARTErrorInfo?) -> Void)?)`
`Task LeaveClientAsync(string clientId)`
Leave a presence channel on behalf of the provided `clientId``client_id``ClientId` and emit data that is associated with the current leaving member.
`leaveClient(String clientId, Object data?): Promise`
Leave a presence channel on behalf of the provided `clientId` and emit an optional data that is associated with the current leaving member.
#### Parameters
| Parameter | Description | Type |
|-----------|-------------|------|
| data | data payload for the member. The supported payload types are Strings, JSON objects and arrays, buffers containing arbitrary binary data, and nullstrings, plain object convertible to json, binary data as byte arrays, and null. | `Object` |
| Parameter | Description | Type |
|-----------|-------------|------|
| data | data payload for the member. The supported payload types are Strings, JSON objects and arrays, buffers containing arbitrary binary data, and nullStrings, JsonObject, binary data as byte arrays, and nullStrings, Hash or Array objects that can be serialized to JSON using `to_json`, binary data as `ASCII-8BIT` byte arrays, and nullThe supported payload types are `NS``String`, `NS``Dictionary` or `NS``Array` objects that can be serialized to JSON, binary data as `NSData`, and `nil`. | `Object` |
| listener&blockcallback | Listener to be notified on completionyields upon successfully entering the channelcalled upon successfully entering the channel, or with an error | [`CompletionListener`](#completion-listener) |
#### Returns
Returns a promise. On success, the promise resolves. On failure, the promise is rejected with an [ErrorInfo](https://ably.com/docs/api/realtime-sdk/types#error-info) object that details the reason why it was rejected.
#### Callback result
On successfully leaving the channel, `err` is null. On failure to leave, `err` contains an [ErrorInfo](#error-info) object describing the failure reason.
#### Listener result
On successfully leaving the channel, the `onSuccess` method of the [CompletionListener](#completion-listener) is called. On failure to leave, the `onError` method is called with an [ErrorInfo](#error-info) argument describing the failure reason.
#### Returns
The method returns a `Task` that will need to be awaited. On success the method will complete and will not throw an exception. On failure to leave the method will throw an `AblyException` with an [ErrorInfo](#error-info) argument describing the failure reason.
#### Returns
A [Deferrable](https://ably.com/docs/api/realtime-sdk/types#deferrable) object is returned from the method.
On successfully leaving the channel, the registered success blocks for the [Deferrable](https://ably.com/docs/api/realtime-sdk/types#deferrable) and any block provided to the method are executed. On failure to leave, the `errback` callbacks of the [Deferrable](https://ably.com/docs/api/realtime-sdk/types#deferrable) are called with an [ErrorInfo](#error-info) argument describing the failure reason.
### updateClientupdate_clientUpdateClientAsync
Clients can update the member data on behalf of the given `clientId``client_id``ClientId` which will trigger a broadcast of this update to all presence subscribers. This method is provided to support typically server instances that act on behalf of multiple client IDs. See [Managing multiple client IDs](https://ably.com/docs/presence-occupancy/presence#presence-multiple-client-id) for more info. If an attempt to update is made before the member has entered the channel, the update is treated as an enter.
A callbackblockcompletion listener can optionally be passed in to be notified of success or failure to update the member data.
`updateClient(String clientId, Object data, callback(ErrorInfo err))`
`updateClient(String clientId, Object data?): Promise`
`Deferrable update_client(String client_id, Object data) -> yields`
`void updateClient(String clientId, Object data, CompletionListener listener)`
`update(clientId: String, data: AnyObject?, callback: ((ARTErrorInfo?) -> Void)?)`
`Task UpdateClientAsync(string clientId, object data)`
Update the member data on behalf of the provided `clientId``client_id``ClientId` and broadcast an update event to all subscribers. `data` may be `null`. If the channel is `initialized` (i.e. no attempt to attach has yet been made for this channel), then calling `enter` will implicitly attach the channel.
#### Parameters
| Parameter | Description | Type |
|-----------|-------------|------|
| data | data payload for the member. The supported payload types are Strings, JSON objects and arrays, buffers containing arbitrary binary data, and nullstrings, plain object convertible to json, binary data as byte arrays, and null. | `Object` |
| Parameter | Description | Type |
|-----------|-------------|------|
| data | data payload for the member. The supported payload types are Strings, JSON objects and arrays, buffers containing arbitrary binary data, and nullStrings, JsonObject, binary data as byte arrays, and nullStrings, Hash or Array objects that can be serialized to JSON using `to_json`, binary data as `ASCII-8BIT` byte arrays, and nullThe supported payload types are `NS``String`, `NS``Dictionary` or `NS``Array` objects that can be serialized to JSON, binary data as `NSData`, and `nil`. | `Object` |
| listener&blockcallback | Listener to be notified on completionyields upon successfully entering the channelcalled upon successfully entering the channel, or with an error | [`CompletionListener`](#completion-listener) |
#### Returns
Returns a promise. On success, the promise resolves. On failure, the promise is rejected with an [ErrorInfo](https://ably.com/docs/api/realtime-sdk/types#error-info) object that details the reason why it was rejected.
#### Callback result
On successfully updating the data, `err` is null. On failure to update, `err` contains an [ErrorInfo](#error-info) object describing the failure reason.
#### Listener result
On successfully updating the data, the `onSuccess` method of the [CompletionListener](#completion-listener) is called. On failure to update, the `onError` method is called with an [ErrorInfo](#error-info) argument describing the failure reason.
#### Returns
The method returns a Task that will need to be awaited. On success the method will complete and will not throw an exception. On failure to update the method will throw an `AblyException` with an [ErrorInfo](#error-info) argument describing the failure reason.
#### Returns
A [Deferrable](https://ably.com/docs/api/realtime-sdk/types#deferrable) object is returned from the method.
On successfully updating the data, the registered success blocks for the [Deferrable](https://ably.com/docs/api/realtime-sdk/types#deferrable) and any block provided to the method are executed. On failure to update, the `errback` callbacks of the [Deferrable](https://ably.com/docs/api/realtime-sdk/types#deferrable) are called with an [ErrorInfo](#error-info) argument describing the failure reason.
## Related types
## PresenceMessageARTPresenceMessageAbly::Models::PresenceMessageio.ably.lib.types.PresenceMessageIO.Ably.PresenceMessage
A `PresenceMessage` represents an individual presence update that is sent to or received from Ably.
#### PropertiesMembersAttributes
| Property | Description | Type |
|----------|-------------|------|
| actionactionAction | the event signified by a PresenceMessage. See [`Presence action`](https://ably.com/docs/api/realtime-sdk/types#presence-action)[`PresenceMessage.action`](https://ably.com/docs/api/realtime-sdk/types#presence-action)[`PresenceMessage.action`](https://ably.com/docs/api/realtime-sdk/types#presence-action)[`PresenceMessage::ACTION`](https://ably.com/docs/api/realtime-sdk/types#presence-action)[`PresenceMessage.action`](https://ably.com/docs/api/realtime-sdk/types#presence-action) | `enum { ABSENT, PRESENT, ENTER, LEAVE, UPDATE }``enum { Absent, Present, Enter, Leave, Update }``int enum { ABSENT, PRESENT, ENTER, LEAVE, UPDATE }``enum { :absent, :present, :enter, :leave, :update }``ARTPresenceAction` |
| dataData | The presence update payload, if provided | `String`, `ByteArray`, `JSONObject`, `JSONArray``String`, `byte[]`, plain C# object that can be converted to Json`String`, `StringBuffer`, `JSON Object``String`, `Binary` (ASCII-8BIT String), `Hash`, `Array``String`, `NSData`, `Dictionary`, `Array``NSString *`, `NSData *`, `NSDictionary *`, `NSArray *` |
| extrasExtras | Metadata and/or ancillary payloads, if provided. The only currently valid payloads for extras are the [`push`](https://ably.com/docs/push/publish#sub-channels), [`ref`](https://ably.com/docs/channels/messages#interactions) and [`privileged`](https://ably.com/docs/platform/integrations/webhooks#skipping) objects. | `JSONObject`, `JSONArray`plain C# object that can be converted to Json`JSON Object``Hash`, `Array``Dictionary`, `Array``NSDictionary *`, `NSArray *``Map`, `List` |
| idId | Unique ID assigned by Ably to this presence update | `String` |
| clientIdclient_idClientId | The client ID of the publisher of this presence update | `String` |
| connectionIdconnection_idConnectionId | The connection ID of the publisher of this presence update | `String` |
| timestampTimestamp | Timestamp when the presence update was received by Ably, as milliseconds since the epoch. | `Integer``Long Integer``DateTimeOffset``Time``NSDate` |
| encodingEncoding | This will typically be empty as all presence updates received from Ably are automatically decoded client-side using this value. However, if the message encoding cannot be processed, this attribute will contain the remaining transformations not applied to the `data` payload | `String` |
### PresenceMessage constructors
#### PresenceMessage.fromEncoded
`PresenceMessage.fromEncoded(Object encodedPresMsg, ChannelOptions channelOptions?) -> PresenceMessage`
A static factory method to create a [`PresenceMessage`](https://ably.com/docs/api/realtime-sdk/types#presence-message) from a deserialized `PresenceMessage`-like object encoded using Ably's wire protocol.
#### Parameters
| Parameter | Description | Type |
|-----------|-------------|------|
| encodedPresMsg | a `PresenceMessage`-like deserialized object. | `Object` |
| channelOptions | an optional [`ChannelOptions`](https://ably.com/docs/api/realtime-sdk/types#channel-options). If you have an encrypted channel, use this to allow the library to decrypt the data. | `Object` |
#### Returns
A [`PresenceMessage`](https://ably.com/docs/api/realtime-sdk/types#presence-message) object
#### PresenceMessage.fromEncodedArray
`PresenceMessage.fromEncodedArray(Object[] encodedPresMsgs, ChannelOptions channelOptions?) -> PresenceMessage[]`
A static factory method to create an array of [`PresenceMessages`](https://ably.com/docs/api/realtime-sdk/types#presence-message) from an array of deserialized `PresenceMessage`-like object encoded using Ably's wire protocol.
#### Parameters
| Parameter | Description | Type |
|-----------|-------------|------|
| encodedPresMsgs | an array of `PresenceMessage`-like deserialized objects. | `Array` |
| channelOptions | an optional [`ChannelOptions`](https://ably.com/docs/api/realtime-sdk/types#channel-options). If you have an encrypted channel, use this to allow the library to decrypt the data. | `Object` |
#### Returns
An `Array` of [`PresenceMessage`](https://ably.com/docs/api/realtime-sdk/types#presence-message) objects
## Presence actionARTPresenceActionio.ably.lib.types.PresenceMessage.ActionAbly::Models::PresenceMessage::ACTIONIO.Ably.PresenceAction
`Presence` `action` is a String with a value matching any of the [`Realtime Presence` states & events](https://ably.com/docs/presence-occupancy/presence#trigger-events.)
```javascript
var PresenceActions = [
'absent', // (reserved for internal use)
'present',
'enter',
'leave',
'update'
]
```
`io.ably.lib.types.PresenceMessage.Action` is an enum representing all the [`Realtime Presence` states & events](https://ably.com/docs/presence-occupancy/presence#trigger-events.)
```java
public enum Action {
ABSENT, // 0 (reserved for internal use)
PRESENT, // 1
ENTER, // 2
LEAVE, // 3
UPDATE // 4
}
```
`IO.Ably.PresenceAction` is an enum representing all the [`Realtime Presence` states & events](https://ably.com/docs/presence-occupancy/presence#trigger-events.)
```csharp
public enum Action {
Absent, // 0 (reserved for internal use)
Present, // 1
Enter, // 2
Leave, // 3
Update // 4
}
```
`Ably::Models::PresenceMessage::ACTION` is an enum-like value representing all the [`Realtime Presence` states & events](https://ably.com/docs/presence-occupancy/presence#trigger-events.) `ACTION` can be represented interchangeably as either symbols or constants.
#### Symbol states
```ruby
:absent # => 0 (reserved for internal use)
:present # => 1
:enter # => 2
:leave # => 3
:update # => 4
```
#### Constant states
```ruby
PresenceMessage::ACTION.Absent # => 0 (internal use)
PresenceMessage::ACTION.Present # => 1
PresenceMessage::ACTION.Enter # => 2
PresenceMessage::ACTION.Leave # => 3
PresenceMessage::ACTION.Update # => 4
```
#### Example usage
```ruby
# Example with symbols
presence.on(:attached) { ... }
# Example with constants
presence.on(Ably::Models::PresenceMessage::ACTION.Enter) { ... }
# Interchangeable
Ably::Models::PresenceMessage::ACTION.Enter == :enter # => true
```
`ARTPresenceAction` is an enum representing all the [`Realtime Presence` states & events](https://ably.com/docs/presence-occupancy/presence#trigger-events.)
```objc
typedef NS_ENUM(NSUInteger, ARTPresenceAction) {
ARTPresenceAbsent, // reserved for internal use
ARTPresencePresent,
ARTPresenceEnter,
ARTPresenceLeave,
ARTPresenceUpdate
};
```
```swift
enum ARTPresenceAction : UInt {
case Absent // reserved for internal use
case Present
case Enter
case Leave
case Update
}
```
## PaginatedRequestParams
`HistoryRequestParams` is a type that encapsulates the parameters for a history queries. For example usage see [`Channel#History`](https://ably.com/docs/api/realtime-sdk/history#channel-history.)
### Members
| Member | Description | Type |
|--------|-------------|------|
| Start | _null_ The start of the queried interval | `DateTimeOffset` |
| End | _null_ The end of the queried interval | `DateTimeOffset` |
| Limit | _null_ By default it is null. Limits the number of items returned by history or stats | `Integer` |
| Direction | _Backwards_ Enum which is either `Forwards` or `Backwards` | `Direction` enum |
| ExtraParameters | Optionally any extra query parameters that may be passed to the query. This is mainly used internally by the library to manage paging. | `Dictionary` |
## io.ably.lib.realtime.CompletionListener
A `io.ably.lib.realtime.CompletionListener` is an interface allowing a client to be notified of the outcome of an asynchronous operation.
```java
public interface CompletionListener {
// Called when the associated operation completes successfully,
public void onSuccess();
// Called when the associated operation completes with an error.
public void onError(ErrorInfo reason);
}
```
## PaginatedResultARTPaginatedResultAbly::Models::PaginatedResultio.ably.lib.types.PaginatedResultIO.Ably.PaginatedResult
A `PaginatedResult` is a type that represents a page of results for all message and presence history, stats and REST presence requests. The response from a [Ably REST API paginated query](https://ably.com/docs/api/rest-api/#pagination) is accompanied by metadata that indicates the relative queries available to the `PaginatedResult` object.
#### PropertiesMembersAttributes
| Property | Description | Type |
|----------|-------------|------|
| itemsItems | contains the current page of results (for example an Array of [`Message`](#message) or [`PresenceMessage`](#presence-message) objects for a channel history request) | `Array ``List ` |
### Methods
#### firstFirst
`first(callback(ErrorInfo err, PaginatedResult resultPage))`
`first(): Promise`
`PaginatedResult first`
`PaginatedResult first()`
`first(callback: (ARTPaginatedResult?, ARTErrorInfo?) -> Void)`
`Task> FirstAsync()`
Returns a new `PaginatedResult` for the first page of results. When using the Realtime library, the `first` method returns a [Deferrable](https://ably.com/docs/api/realtime-sdk/types#deferrable) and yields a [PaginatedResult](#paginated-result).The method is asynchronous and returns a Task which needs to be awaited to get the [PaginatedResult](#paginated-result).
Returns a promise. On success, the promise is fulfilled with a new `PaginatedResult` for the first page of results. On failure, the promise is rejected with an [`ErrorInfo`](https://ably.com/docs/api/realtime-sdk/types#error-info) object that details the reason why it was rejected.
#### hasNextHasNexthas_next?
`Boolean hasNext()`
`Boolean has_next?`
`Boolean HasNext()`
Returns `true` if there are more pages available by calling `next``Next` and returns `false` if this page is the last page available.
#### isLastIsLastlast?
`Boolean isLast()`
`Boolean last?`
`Boolean IsLast()`
Returns `true` if this page is the last page and returns `false` if there are more pages available by calling `next``Next` available.
#### nextNext
`next(callback(ErrorInfo err, PaginatedResult resultPage))`
`next(): Promise`
`PaginatedResult next`
`PaginatedResult next()`
`next(callback: (ARTPaginatedResult?, ARTErrorInfo?) -> Void)`
`Task> NextAsync()`
Returns a new `PaginatedResult` loaded with the next page of results. If there are no further pages, then `null`a blank PaginatedResult will be returned`Null``nil` is returned. The method is asynchronous and return a Task which needs to be awaited to get the `PaginatedResult`When using the Realtime library, the `first` method returns a [Deferrable](https://ably.com/docs/api/realtime-sdk/types#deferrable) and yields a [PaginatedResult](#paginated-result).
Returns a promise. On success, the promise is fulfilled with a new `PaginatedResult` loaded with the next page of results. If there are no further pages, then `null` is returned. On failure, the promise is rejected with an [`ErrorInfo`](https://ably.com/docs/api/realtime-sdk/types#error-info) object that details the reason why it was rejected.
#### current
`current(): Promise`
Returns a promise. On success, the promise is fulfilled with a new `PaginatedResult` loaded with the current page of results. On failure, the promise is rejected with an [`ErrorInfo`](https://ably.com/docs/api/realtime-sdk/types#error-info) object that details the reason why it was rejected.
#### Example
```javascript
const paginatedResult = await channel.history();
console.log('Page 0 item 0:' + paginatedResult.items[0].data);
const nextPage = await paginatedResult.next();
console.log('Page 1 item 1: ' + nextPage.items[1].data);
console.log('Last page?: ' + nextPage.isLast());
```
```nodejs
const paginatedResult = await channel.history();
console.log('Page 0 item 0:' + paginatedResult.items[0].data);
const nextPage = await paginatedResult.next();
console.log('Page 1 item 1: ' + nextPage.items[1].data);
console.log('Last page?: ' + nextPage.isLast());
```
```java
PaginatedResult firstPage = channel.history();
System.out.println("Page 0 item 0:" + firstPage.items[0].data);
if (firstPage.hasNext) {
PaginatedResult nextPage = firstPage.next();
System.out.println("Page 1 item 1:" + nextPage.items[1].data);
System.out.println("More pages?:" + Strong.valueOf(nextPage.hasNext()));
};
```
```csharp
PaginatedResult firstPage = await channel.HistoryAsync(null);
Message firstMessage = firstPage.Items[0];
Console.WriteLine("Page 0 item 0: " + firstMessage.data);
if (firstPage.HasNext)
{
var nextPage = await firstPage.NextAsync();
Console.WriteLine("Page 1 item 1:" + nextPage.Items[1].data);
Console.WriteLine("More pages?: " + nextPage.HasNext());
}
```
```ruby
# When using the REST sync library
first_page = channel.history
puts "Page 0 item 0: #{first_page.items[0].data}"
if first_page.has_next?
next_page = first_page.next
puts "Page 1 item 1: #{next_page.items[1].data}"
puts "Last page?: #{next_page.is_last?}"
end
# When using the Realtime EventMachine library
channel.history do |first_page|
puts "Page 0 item 0: #{first_page.items[0].data}"
if first_page.has_next?
first_page.next do |next_page|
puts "Page 1 item 1: #{next_page.items[1].data}"
puts "Last page?: #{next_page.is_last?}"
end
end
end
```
```objc
[channel history:^(ARTPaginatedResult *paginatedResult, ARTErrorInfo *error) {
NSLog(@"Page 0 item 0: %@", paginatedResult.items[0].data);
[paginatedResult next:^(ARTPaginatedResult *nextPage, ARTErrorInfo *error) {
NSLog(@"Page 1 item 1: %@", nextPage.items[1].data);
NSLog(@"Last page?: %d", nextPage.isLast());
}];
}];
```
```swift
channel.history { paginatedResult, error in
guard let paginatedResult = paginatedResult else {
print("No results available")
return
}
print("Page 0 item 0: \((paginatedResult.items[0] as! ARTMessage).data)")
paginatedResult.next { nextPage, error in
guard let nextPage = nextPage else {
print("No next page available")
return
}
print("Page 1 item 1: \((nextPage.items[1] as! ARTMessage).data)")
print("Last page? \(nextPage.isLast())")
}
}
```
### io.ably.lib.types.Param
`Param` is a type encapsulating a key/value pair. This type is used frequently in method parameters allowing key/value pairs to be used more flexible, see [`Channel#history`](https://ably.com/docs/api/realtime-sdk/history#channel-history) for an example.
Please note that `key` and `value` attributes are always strings. If an `Integer` or other value type is expected, then you must coerce that type into a `String`.
#### Members
| Member | Description | Type |
|--------|-------------|------|
| key | The key value | `String` |
| value | The value associated with the `key` | `String` |
### io.ably.lib.realtime.PresenceListener
A `io.ably.lib.realtime.Presence.PresenceListener` is an interface allowing a client to be notified when presence message events are received on a presence channel using a [presence subscription](https://ably.com/docs/presence-occupancy/presence.)
```java
public interface PresenceListener {
// Called when one or more presence messages are received
public void onPresenceMessage(PresenceMessage message);
}
```