Channel groups
Channel groups let you manage and subscribe to multiple channels as a single unit. Instead of subscribing to each channel individually, you can add channels to a group and receive messages from all of them with a single subscription.
This is useful when you need to:
- Subscribe to all channels a user is a member of with one call.
- Monitor presence across multiple channels simultaneously.
- Dynamically manage channel subscriptions without reconnecting.
You can't publish to a channel group. You can only subscribe to it. To publish within a channel group, you need to publish to each channel individually.
Requires Stream Controller add-on
This method requires that the Stream Controller add-on is enabled for your key in the Admin Portal. Read the support page on enabling add-on features on your keys.
Get channel group reference
Use the getChannelGroup() method on the Chat object to get a reference to a channel group. This method doesn't create the group on the server, but returns a handle you can use to manage the group.
If the group exists, the reference points to it. If the group doesn't exist, it serves as a handle to create and modify it by adding channels to it.
Method signature
This method takes the following parameters:
1chat.getChannelGroup(channelGroupId: String) -> ChannelGroupImpl
Input
| Parameter | Description |
|---|---|
channelGroupId *Type: StringDefault: n/a | Unique identifier for the channel group. |
Output
| Type | Description |
|---|---|
ChannelGroupImpl | A ChannelGroup object you can use to manage the group. |
Sample code
Sample code
The code samples in Swift Chat SDK focus on asynchronous code execution.
You can also write synchronous code as the parameters are shared between the async and sync methods but we don't provide usage examples of such.
Get a reference to a channel group named my-channel-group.
1// Assuming you have a reference of type "ChatImpl" named "chat"
2let channelGroup = chat.getChannelGroup(channelGroupId: "my-channel-group")
Remove channel group
Use the removeChannelGroup() method to delete a channel group from the server.
Method signature
This method takes the following parameters:
1chat.removeChannelGroup(id: String) async throws
Input
| Parameter | Description |
|---|---|
id *Type: StringDefault: n/a | Unique identifier of the channel group to remove. |
Output
This method doesn't return any value.
Sample code
Remove a channel group named my-channel-group.
1// Assuming you have a reference of type "ChatImpl" named "chat"
2Task {
3 try await chat.removeChannelGroup(id: "my-channel-group")
4 debugPrint("Channel group removed successfully")
5}
List channels
Use the listChannels() method to get a paginated list of all channels in a channel group.
Method signature
This method takes the following parameters:
1channelGroup.listChannels(
2 filter: String? = nil,
3 sort: [PubNub.ObjectSortField] = [],
4 limit: Int? = nil,
5 page: PubNubHashedPage? = nil
6) async throws -> (channels: [ChannelImpl], page: PubNubHashedPage?, total: Int?)
Input
| Parameter | Description |
|---|---|
filterType: StringDefault: nil | Expression used to filter the results. Returns only the channels whose properties satisfy the given expression. The filter language is defined here. |
sortType: [PubNub.ObjectSortField]Default: [] | An array to specify the sort order. Available options are id, name, and updated. Use ascending or descending to specify the sorting direction. |
limitType: IntDefault: 100 | Number of objects to return in response. The default (and maximum) value is 100. |
pageType: PubNubHashedPageDefault: nil | Object used for pagination to define which previous or next result page you want to fetch. |
Output
| Type | Description |
|---|---|
(channels: [ChannelImpl], page: PubNubHashedPage?, total: Int?) | A tuple containing a set of channels with pagination information. |
Sample code
List all channels in a channel group.
1// Assuming you have a reference of type "ChatImpl" named "chat"
2Task {
3 let channelGroup = chat.getChannelGroup(id: "my-channel-group")
4 let result = try await channelGroup.listChannels()
5
6 for channel in result.channels {
7 debugPrint("Channel: \(channel.id)")
8 }
9}
Add channels
Use the add(channels:) method to add Channel entities to a channel group.
Method signature
This method takes the following parameters:
1channelGroup.add(channels: [ChannelImpl]) async throws
Input
| Parameter | Description |
|---|---|
channels *Type: [ChannelImpl]Default: n/a | Array of Channel entities to add to the group. |
Output
This method doesn't return any value.
Sample code
Add two channels to a channel group.
1// Assuming you have a reference of type "ChatImpl" named "chat"
2Task {
3 let channelGroup = chat.getChannelGroup(id: "my-channel-group")
4 let supportChannel = try await chat.getChannel(channelId: "support-channel")
5 let generalChannel = try await chat.getChannel(channelId: "general-channel")
6
7 if let supportChannel, let generalChannel {
8 try await channelGroup.add(channels: [supportChannel, generalChannel])
9 debugPrint("Channels added successfully")
10 }
11}
Add channel identifiers
Use the addChannelIdentifiers(_:) method to add channels to a group using only their IDs. This method reduces the overhead of fetching full Channel entities when you only know the IDs.
No validation
This method doesn't validate whether channels with the given IDs exist. Make sure the channel IDs are valid before adding them.
Method signature
This method takes the following parameters:
1channelGroup.addChannelIdentifiers(_ channelIds: [String]) async throws
Input
| Parameter | Description |
|---|---|
channelIds *Type: [String]Default: n/a | Array of channel IDs to add to the group. |
Output
This method doesn't return any value.
Sample code
Add channels by their IDs.
1// Assuming you have a reference of type "ChatImpl" named "chat"
2Task {
3 let channelGroup = chat.getChannelGroup(id: "my-channel-group")
4 try await channelGroup.addChannelIdentifiers(["support-channel", "general-channel"])
5 debugPrint("Channel identifiers added successfully")
6}
Remove channels
Use the remove(channels:) method to remove Channel entities from a channel group.
Method signature
This method takes the following parameters:
1channelGroup.remove(channels: [ChannelImpl]) async throws
Input
| Parameter | Description |
|---|---|
channels *Type: [ChannelImpl]Default: n/a | Array of Channel entities to remove from the group. |
Output
This method doesn't return any value.
Sample code
Remove channels from a channel group.
1// Assuming you have a reference of type "ChatImpl" named "chat"
2Task {
3 let channelGroup = chat.getChannelGroup(id: "my-channel-group")
4 // Assuming you have Channel references to supportChannel and generalChannel
5 try await channelGroup.remove(channels: [supportChannel, generalChannel])
6 debugPrint("Channels removed successfully")
7}
Remove channel identifiers
Use the removeChannelIdentifiers(_:) method to remove channels from a group using only their IDs.
No validation
This method doesn't validate whether channels with the given IDs exist in the group. Make sure the channel IDs are valid before removing them.
Method signature
This method takes the following parameters:
1channelGroup.removeChannelIdentifiers(_ channelIds: [String]) async throws
Input
| Parameter | Description |
|---|---|
channelIds *Type: [String]Default: n/a | Array of channel IDs to remove from the group. |
Output
This method doesn't return any value.
Sample code
Remove channels by their IDs.
1// Assuming you have a reference of type "ChatImpl" named "chat"
2Task {
3 let channelGroup = chat.getChannelGroup(id: "my-channel-group")
4 try await channelGroup.removeChannelIdentifiers(["support-channel", "general-channel"])
5 debugPrint("Channel identifiers removed successfully")
6}
Watch channel group
Use the connect() method to start receiving messages from all channels in the group. This subscribes to all channels in the group and invokes your callback whenever a message is received on any channel in the group.
Method signature
connect() returns an asynchronous stream which produces a new value whenever someone sends a message on any channel in the group.
This method takes the following parameters:
1channelGroup.connect() -> AsyncStream<MessageImpl>
Input
This method doesn't take any parameters.
Output
| Type | Description |
|---|---|
AsyncStream<MessageImpl> | An asynchronous stream that emits a new value whenever a new message is published on any channel in the group. |
Sample code
Start receiving messages from all channels in a group.
- AsyncStream
- Closure
1// Assuming you have a reference of type "ChatImpl" named "chat"
2Task {
3 let channelGroup = chat.getChannelGroup(id: "my-channel-group")
4
5 for await message in channelGroup.connect() {
6 debugPrint("Received message on channel \(message.channelId): \(message.text)")
7 }
8}
1// Important: Keep a strong reference to the returned "AutoCloseable" object as long as you want
2// to receive updates. If the "AutoCloseable" is deallocated, the stream will be cancelled,
3// and no further items will be produced. You can also stop receiving messages manually
4// by calling the "close()" method on the "AutoCloseable" object.
5
6// Assuming you have a reference of type "ChannelGroupImpl" named "channelGroup"
7autoCloseable = channelGroup.connect { message in
8 debugPrint("Received message on channel \(message.channelId): \(message.text)")
9}
Get present users
Use the whoIsPresent() method to get a list of users currently present on any channel within the channel group.
Requires Presence
This method requires that Presence is enabled for your app's keyset in the Admin Portal.
Method signature
This method has the following signature:
1channelGroup.whoIsPresent() async throws -> [String: [String]]
Input
This method doesn't take any parameters.
Output
| Type | Description |
|---|---|
[String: [String]] | A dictionary where each key is a channel ID and the value is an array of user IDs present on that channel. |
Sample code
Get all users present on channels in a group.
1// Assuming you have a reference of type "ChatImpl" named "chat"
2Task {
3 let channelGroup = chat.getChannelGroup(id: "my-channel-group")
4 let presenceByChannel = try await channelGroup.whoIsPresent()
5
6 for (channelId, userIds) in presenceByChannel {
7 debugPrint("Channel \(channelId) has users: \(userIds)")
8 }
9}
Stream presence
Use the streamPresence() method to receive real-time updates when users join or leave any channel in the group.
Requires Presence
This method requires that Presence is enabled for your app's keyset in the Admin Portal.
Method signature
streamPresence() returns an asynchronous stream which produces a new value whenever presence changes on any channel in the group.
This method takes the following parameters:
1channelGroup.streamPresence() -> AsyncStream<[String: [String]]>
Input
This method doesn't take any parameters.
Output
| Type | Description |
|---|---|
AsyncStream<[String: [String]]> | An asynchronous stream that emits a dictionary where each key is a channel ID and the value is an array of user IDs present on that channel. |
Sample code
Stream presence updates for all channels in a group.
- AsyncStream
- Closure
1// Assuming you have a reference of type "ChatImpl" named "chat"
2Task {
3 let channelGroup = chat.getChannelGroup(id: "my-channel-group")
4
5 for await presenceByChannel in channelGroup.streamPresence() {
6 for (channelId, userIds) in presenceByChannel {
7 debugPrint("Channel \(channelId) now has users: \(userIds)")
8 }
9 }
10}
1// Important: Keep a strong reference to the returned "AutoCloseable" object as long as you want
2// to receive updates. If the "AutoCloseable" is deallocated, the stream will be cancelled,
3// and no further items will be produced. You can also stop receiving presence updates manually
4// by calling the "close()" method on the "AutoCloseable" object.
5
6// Assuming you have a reference of type "ChannelGroupImpl" named "channelGroup"
7autoCloseable = channelGroup.streamPresence { presenceByChannel in
8 for (channelId, userIds) in presenceByChannel {
9 debugPrint("Channel \(channelId) now has users: \(userIds)")
10 }
11}