---
source_url: https://www.pubnub.com/docs/sdks/cocoa-swift/api-reference/presence
title: Presence API for Cocoa Swift SDK
updated_at: 2026-06-12T11:25:04.330Z
---

> Documentation Index
> For a curated overview of PubNub documentation, see: https://www.pubnub.com/docs/llms.txt
> For the full list of all documentation pages, see: https://www.pubnub.com/docs/llms-full.txt


# Presence API for Cocoa Swift SDK

This SDK has been replaced by a new PubNub Swift SDK written purely in Swift. Check out the [Swift SDK overview](https://www.pubnub.com/docs/sdks/swift).

Presence lets you track who is online or offline and store custom state information. Presence shows:

* When a user has joined or left a channel
* How many users are subscribed to a particular channel (occupancy)
* Which channels a user or device is subscribed to
* Presence state associated with these users

Learn more about our Presence feature in the [Presence overview](https://www.pubnub.com/docs/general/presence/overview).

## Here now

:::warning Requires Presence
This method requires that the Presence add-on is [enabled](https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-) for your key in the [Admin Portal](https://admin.pubnub.com/).
:::

This method returns information about the current state of a channel, including a list of unique user IDs (universally unique identifiers, UUIDs) currently subscribed to the channel and the total occupancy count of the channel.

:::note Cache
This method has a 3-second response cache time.
:::

### Method(s)

To call `Here Now` you can use the following method(s) in the Swift SDK:

```swift
open func hereNowForChannel(
    _ channel: String,
    withCompletion closure: PubNub.PNHereNowCompletionBlock
)
```

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| channel | String | Yes |  | `Channel` name to retrieve the Here Now information. |
| closure | PNHereNowCompletionBlock | Yes |  | The completion `closure` has two arguments: result - in case of successful request processing (data field will contain results of presence audition operation); status - in case if error occurred during request processing (errorData contains error information). |

```swift
open func hereNowForChannel(
    _ channel: String,
    withVerbosity level: PNHereNowVerbosityLevel,
    completion closure: PubNub.PNHereNowCompletionBlock
)
```

| Parameter | Description |
| --- | --- |
| `channel` *Type: String | `Channel` name to retrieve the Here Now information. |
| `level` *Type: PNHereNowVerbosityLevel | PNHereNowVerbosityLevel enum filters the response based on the value selected. |
| `closure` *Type: PNHereNowCompletionBlock | The completion `closure` has two arguments: result - in case of successful request processing (data field will contain results of presence audition operation); status - in case if error occurred during request processing (errorData contains error information). |

### Sample code

#### Get a list of uuids subscribed to channel

```swift
// With .UUID client will pull out list of unique identifiers and occupancy information.
self.client.hereNowForChannel("my_channel", withVerbosity: .UUID,
                              completion: { (result, status) in

    if status == nil {

        /**
         Handle downloaded presence information using:
            result.data.uuids - list of uuids.
            result.data.occupancy - total number of active subscribers.
         */
    }
    else {

        /**
         Handle presence audit error. Check 'category' property to find
         out possible reason because of which request did fail.
         Review 'errorData' property (which has PNErrorData data type) of status
         object to get additional information about issue.

         Request can be resent using: status.retry()
         */
    }
})
```

### Response

Response objects which is returned by client when Here Now API for channel used:

```swift
open class PNPresenceGlobalHereNowData : PNServiceData {

    // Active channels list.
    open var channels: [String : [AnyHashable : Any]] { get }
    // Total number of active channels.
    open var totalChannels: NSNumber { get }
    // Total number of subscribers.
    open var totalOccupancy: NSNumber { get }
}

open class PNPresenceChannelGroupHereNowData : PNPresenceGlobalHereNowData {

}

open class PNPresenceChannelGroupHereNowResult : PNResult {

    // Stores reference on channel group presence request processing information.
    open var data: PNPresenceChannelGroupHereNowData { get }
}
```

### Other examples

#### Returning state

:::warning Requires Presence
This method requires that the Presence add-on is [enabled](https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-) for your key in the [Admin Portal](https://admin.pubnub.com/).
:::

```swift
/**
    With .state client aside from occupancy and unique identifiers will will pull out
    state information associated with them.
    */
self.client.hereNowForChannel("my_channel", withVerbosity: .state,
                                completion: { (result, status) in

    if status == nil {

        /**
            Handle downloaded presence information using:
            result.data.uuids - list of uuids. Each uuid entry will have next
                                fields: "uuid" - identifier and "state" if it
                                has been provided.
            result.data.occupancy - total number of active subscribers.
            */
    }
    else {

        /**
            Handle presence audit error. Check 'category' property
            to find out possible reason because of which request did fail.
            Review 'errorData' property (which has PNErrorData data type) of status
            object to get additional information about issue.

            Request can be resent using: status.retry()
            */
    }
})
```

##### Example response

```swift
{
    "status" : 200,
    "message" : "OK",
    "service" : "Presence",
    "uuids" : [
        {
            "uuid" : "myUUID0"
        },
        {
            "state" : {
                "abcd" : {
                    "age" : 15
                }
            },
            "uuid" : "myUUID1"
        },
        {
            "uuid" : "b9eb408c-bcec-4d34-b4c4-fabec057ad0d"
        },
        {
            "state" : {
                "abcd" : {
                    "age" : 15
                }
            },
            "uuid" : "myUUID2"
        },
        {
            "state" : {
                "abcd" : {
                    "age" : 24
                }
            },
            "uuid" : "myUUID9"
        }
    ],
    "occupancy" : 5
}
```

#### Return occupancy only

:::warning Requires Presence
This method requires that the Presence add-on is [enabled](https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-) for your key in the [Admin Portal](https://admin.pubnub.com/).
:::

You can return only the `occupancy` information for a single channel by specifying the channel and setting `UUIDs` to false:

```swift
// With .occupancy client will pull out only occupancy information.
self.client.hereNowForChannel("my_channel", withVerbosity: .occupancy,
                                completion: { (result, status) in

    if status == nil {

        /**
            Handle downloaded presence information using:
                result.data.occupancy - total number of active subscribers.
            */
    }
    else {

        /**
            Handle presence audit error. Check 'category' property
            to find out possible reason because of which request did fail.
            Review 'errorData' property (which has PNErrorData data type) of status
            object to get additional information about issue.

            Request can be resent using: status.retry()
            */
    }
})
```

##### Example response

```swift
{
    "status": 200,
    "message": "OK",
    "payload": {
        "channels": {
            "81d8d989-b95f-443c-a726-04fac323b331": {
                "uuids": [ "70fc1140-22b5-4abc-85b2-ff8c17b24d59" ],
                "occupancy": 1
            },
            "81b7a746-d153-49e2-ab70-3037a75cec7e": {
                "uuids": [ "91363e7f-584b-49cc-822c-52c2c01e5928" ],
                "occupancy": 1
            },
            "c068d15e-772a-4bcd-aa27-f920b7a4eaa8": {
                "uuids": [ "ccfac1dd-b3a5-4afd-9fd9-db11aeb65395" ],
                "occupancy": 1
            }
        },
        "total_channels": 3,
        "total_occupancy": 3
    },
    "service": "Presence"
}
```

## Here now for channel groups

Request information about subscribers on specific channel group. This API method will retrieve the list of UUIDs along with their state for each remote data object and the number of subscribers.

### Method(s)

To do `Here Now for Channel Groups` you can use the following method(s) in the Swift SDK:

```swift
open func hereNowForChannelGroup(
    _ group: String,
    withCompletion closure: PubNub.PNChannelGroupHereNowCompletionBlock
)
```

| Parameter | Description |
| --- | --- |
| `group` *Type: String | `Channel Group` name to retrieve the Here Now information. |
| `closure` *Type: PNChannelGroupHereNowCompletionBlock | The completion `closure` has two arguments: result - in case of successful request processing (data field will contain results of presence audition operation); status - in case if error occurred during request processing (errorData contains error information). |

```swift
open func hereNowForChannelGroup(
    _ group: String,
    withVerbosity level: PNHereNowVerbosityLevel,
    completion closure: PubNub.PNChannelGroupHereNowCompletionBlock
)
```

| Parameter | Description |
| --- | --- |
| `group` *Type: String | `Channel Group` name to retrieve the Here Now information. |
| `level` *Type: PNHereNowVerbosityLevel | PNHereNowVerbosityLevel enum filters the response based on the value selected. |
| `closure` *Type: PNChannelGroupHereNowCompletionBlock | The completion `closure` has two arguments: result - in case of successful request processing (data field will contain results of presence audition operation); status - in case if error occurred during request processing (errorData contains error information). |

### Sample code

#### Here now for channel groups

```swift
self.client.hereNowForChannelGroup("my_group", withCompletion: { (result, status) in

    if status == nil {

        /**
         Handle downloaded presence information using:
            result.data.channels - dictionary with active channels and presence information on
                                   each. Each channel will have next fields: "uuids" - list of
                                   subscribers; occupancy - number of active subscribers.
                                   Each uuids entry has next fields: "uuid" - identifier and
                                   "state" if it has been provided.
            result.data.totalChannels - total number of active channels.
            result.data.totalOccupancy - total number of active subscribers.
         */
    }
    else {

        /**
         Handle presence audit error. Check 'category' property
         to find out possible reason because of which request did fail.
         Review 'errorData' property (which has PNErrorData data type) of status
         object to get additional information about issue.

         Request can be resent using: status.retry()
         */
    }
})
```

### Response

Response objects which is returned by client when Here Now API for channel group used:

```swift
open class PNPresenceGlobalHereNowData : PNServiceData {

    // Active channels list.
    open var channels: [String : [AnyHashable : Any]] { get }
    // Total number of active channels.
    open var totalChannels: NSNumber { get }
    // Total number of subscribers.
    open var totalOccupancy: NSNumber { get }
}

open class PNPresenceChannelGroupHereNowData : PNPresenceGlobalHereNowData {

}

open class PNPresenceChannelGroupHereNowResult : PNResult {

    // Stores reference on channel group presence request processing information.
    open var data: PNPresenceChannelGroupHereNowData { get }
}
```

## Where now

:::warning Requires Presence
This method requires that the Presence add-on is [enabled](https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-) for your key in the [Admin Portal](https://admin.pubnub.com/).
:::

This method returns the list of channels a UUID is subscribed to.

:::note Timeout events
If the app restarts (or the page refreshes) within the heartbeat window, no timeout event is generated.
:::

### Method(s)

To call `whereNowUUID` you can use the following method(s) in the Swift SDK:

```swift
open func whereNowUUID(
    _ uuid: String,
    withCompletion closure: PubNub.PNWhereNowCompletionBlock
)
```

| Parameter | Description |
| --- | --- |
| `uuid` *Type: String | The UUID for which request should be performed. |
| `closure` *Type: PNWhereNowCompletionBlock | The completion `closure` which will be called when the processing is complete, has two arguments: `result` - in case of successful processing (`data` will contain results of presence operation); `status` - in case of error while processing (`errorData`contains error information). |

### Sample code

You simply need to define the `uuid` and the `callback` function to be used to send the data to as in the example below.

#### Get a list of channels a UUID is subscribed to

```swift
self.client.whereNowUUID(self.client.uuid(), withCompletion: { (result, status) in

    if status == nil {

        // Handle downloaded presence 'where now' information using: result.data.channels
    }
    else {

        /**
         Handle presence audit error. Check 'category' property
         to find out possible reason because of which request did fail.
         Review 'errorData' property (which has PNErrorData data type) of status
         object to get additional information about issue.

         Request can be resent using: status.retry()
         */
    }
})
```

### Response

Response objects which is returned by client when Where Now API is used:

```swift
open class PNPresenceWhereNowData : PNServiceData {

    // List of channels on which client subscribed.
    open var channels: [String] { get }
}

open class PNPresenceWhereNowResult : PNResult {

    // Stores reference on client presence request processing information.
    open var data: PNPresenceWhereNowData { get }
}
```

## User state

:::warning Requires Presence
This method requires that the Presence add-on is [enabled](https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-) for your key in the [Admin Portal](https://admin.pubnub.com/).
:::

Clients can set a dynamic custom state (score, game state, location) for their users on one or more channels and store it on a channel as long as the user stays subscribed.

The state is not persisted, and when the client disconnects, the state data is lost. For more information, refer to [Presence State](https://www.pubnub.com/docs/general/presence/presence-state).

### Method(s)

#### Set state

#### Set state on channels

```swift
open func setState(
    _ state: [String: Any]?,
    forUUID uuid: String,
    onChannel channel: String,
    withCompletion closure: PubNub.PNSetStateCompletionBlock? = nil
)
```

| Parameter | Description |
| --- | --- |
| `state`Type: [String : Any] | Reference on dictionary which should be bound to `uuid` on specified channel.`If value is nil, state will be removed for` uuid `on` channel. |
| `uuid` *Type: String | The unique user identifier for which `state` should be bound. |
| `channel` *Type: String | `Channel` name against which the store state information is stored. |
| `closure`Type: PNChannelStateCompletionBlock | The completion `closure` which will be called when the processing is complete, has one argument: request processing `status` - in case of error while processing (`errorData`contains error information). |

#### Set state on channel groups

```swift
open func setState(
    _ state: [String: Any]?,
    forUUID uuid: String,
    onChannelGroup group: String,
    withCompletion closure: PubNub.PNSetStateCompletionBlock? = nil
)
```

| Parameter | Description |
| --- | --- |
| `state`Type: [String : Any] | Reference on dictionary which should be bound to `uuid` on specified channel group.`If value is nil, state will be removed for` uuid `on` group. |
| `uuid` *Type: String | The unique user identifier for which `state` should be bound. |
| `group` *Type: String! | `Channel Group` name against which the store state information is stored. |
| `closure`Type: PNChannelStateCompletionBlock | The completion `closure` which will be called when the processing is complete, has one argument: request processing `status` - in case of error while processing (`errorData`contains error information). |

#### Get state

#### Get state from channels

```swift
open func stateForUUID(
    _ uuid: String,
    onChannel channel: String,
    withCompletion closure: PubNub.PNChannelStateCompletionBlock
)
```

| Parameter | Description |
| --- | --- |
| `uuid` *Type: String | The unique user identifier for which state should be retrieved. |
| `channel` *Type: String | `Channel` name to retrieve the state information. |
| `closure` *Type: PNChannelStateCompletionBlock | The completion `closure` which will be called when the processing is complete, has two arguments: `result` - in case of successful processing (`data` will contain results of client state retrieve operation); `status` - in case of error while processing (`errorData`contains error information). |

#### Get state from channel groups

```swift
open func stateForUUID(
    _ uuid: String,
    onChannelGroup group: String,
    withCompletion closure: PubNub.PNChannelGroupStateCompletionBlock
)
```

| Parameter | Description |
| --- | --- |
| `uuid` *Type: String | The unique user identifier for which state should be retrieved. |
| `group` *Type: String | `Channel Group` name to retrieve the state information. |
| `closure` *Type: PNChannelGroupStateCompletionBlock | The completion `closure` which will be called when the processing is complete, has two arguments: `result` - in case of successful processing (`data` will contain results of client state retrieve operation); `status` - in case of error while processing (`errorData`contains error information). |

### Sample code

#### Set state

```swift
self.client.setState(["Key": "Value"], forUUID: self.client.uuid(), onChannel: "my_channel",
                     withCompletion: { (status) in

    if !status.isError {

        // Client state successfully modified on specified channel.
    }
    else {

        /**
         Handle client state modification error. Check 'category' property
         to find out possible reason because of which request did fail.
         Review 'errorData' property (which has PNErrorData data type) of status
         object to get additional information about issue.

         Request can be resent using: status.retry()
         */
    }
})
```

#### Get state

```swift
self.client.stateForUUID(self.client.uuid(), onChannel: "chat",
                         withCompletion: { (result, status) in

    if status == nil {

        // Handle downloaded state information using: result.data.state
    }
    else{

        /**
         Handle client state audit error. Check 'category' property
         to find out possible reason because of which request did fail.
         Review 'errorData' property (which has PNErrorData data type) of status
         object to get additional information about issue.

         Request can be resent using: status.retry()
         */
    }
})
```

### Response

#### Set state

Response objects which is returned by client when Set State API for channels used:

```swift
open class PNClientStateUpdateData : PNChannelClientStateData {

}

open class PNClientStateUpdateStatus : PNErrorStatus {

    // Stores reference on client state for channel request processing information.
    open var data: PNClientStateUpdateData { get }
}
```

#### Get state

Response objects which is returned by client when Get State API for channel used:

```swift
open class PNChannelClientStateData : PNServiceData {

    // User-provided client state information.
    open var state: [String : Any] { get }
}

open class PNChannelClientStateResult : PNResult {

    // Stores reference on client state for channel request processing information.
    open var data: PNChannelClientStateData { get }
}
```

Response objects which is returned by client when Get State API for channel group used:

```swift
open class PNChannelGroupClientStateData : PNServiceData {

    // Multi channel client state information.
    open var channels: [String : [AnyHashable : Any]] { get }
}

open class PNChannelGroupClientStateResult : PNResult {

    // Stores reference on client state for channel group request processing information.
    open var data: PNChannelGroupClientStateData { get }
}
```

## User state (builder pattern)

:::warning Requires Presence
This method requires that the Presence add-on is [enabled](https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-) for your key in the [Admin Portal](https://admin.pubnub.com/).
:::

The state API is used to set/get key/value pairs specific to a subscriber `uuid`.

State information is supplied as a JSON object of key/value pairs.

### Method(s)

#### Set state

```swift
state().set()
    .uuid(String)
    .state([String: Any])
    .channels([String])
    .channelGroups([String])
    .performWithCompletion(PNSetStateCompletionBlock)
```

| Parameter | Description |
| --- | --- |
| `uuid`Type: String | Unique user identifier for which state should be bound. Current `PubNub` user ID will be used by default if not set or set to `nil`. |
| `state`Type: [String: Any] | Data which should be bound to specified `uuid` on `channels` / `channelGroups`. |
| `channels`Type: [String] | List of the channel names which will store provided `state` information for `uuid`. Not required if `channelGroups` is set. |
| `channelGroups`Type: [String] | List of channel group names which will store provided `state` information for `uuid`. Not required if `channels` is set. |
| `completion`Type: PNSetStateCompletionBlock | State modification for user on channel / channel group completion closure which pass only one argument - request status reports state change was successful or not (`errorData` contains error information in case of failure). |

:::note Optional arguments
This method uses the builder pattern, you can remove the arguments which are optional.
:::

#### Get state

```swift
state().audit()
    .uuid(String)
    .channels([String])
    .channelGroups([String])
    .performWithCompletion(PNGetStateCompletionBlock)
```

| Parameter | Description |
| --- | --- |
| `uuid`Type: String | Unique user identifier for which state should be retrieved. Current `PubNub` user ID will be used by default if not set or set to `nil`. |
| `channels`Type: [String] | List of the channel names from which state information for `uuid` will be pulled out. Not required if `channelGroups` is set. |
| `channelGroups`Type: [String] | List of channel group names from which state information for `uuid` will be pulled out. Not required if `channels` is set. |
| `completion` *Type: PNGetStateCompletionBlock | State audition for user on channel / channel group completion closure which pass two arguments: result - in case of successful request processing data field will contain results of client state retrieve operation; status - in case of error occurred during request processing. |

:::note Optional arguments
This method uses the builder pattern, you can remove the arguments which are optional.
:::

### Sample code

#### Set state

```swift
self.client.state().set().state(["state": "test"])
    .channels(["channel1", "channel12"])
    .channelGroups(["group1", "group2"])
    .performWithCompletion({ (status) in

        if !status.isError {
            // Client state successfully modified on specified channels and groups.
        } else {
            /**
             Handle client state modification error. Check 'category' property
             to find out possible reason because of which request did fail.
             Review 'errorData' property (which has PNErrorData data type) of status
             object to get additional information about issue.

             Request can be resent using: status.retry()
            */
        }
    });
```

#### Get state

```swift
self.client.state().audit().uuid("PubNub")
    .channels(["channel1", "channel12"])
    .channelGroups(["group1", "group2"])
    .performWithCompletion({ (result, status) in

        if status == nil {
            // Handle downloaded state information using: result.data.channels
        } else {
            /**
             Handle client state audit error. Check 'category' property
             to find out possible reason because of which request did fail.
             Review 'errorData' property (which has PNErrorData data type) of status
             object to get additional information about issue.

             Request can be resent using: status.retry()
            */
        }
    });
```