Manage the user-channel membership relationship
Requires App Context
To set up and manage channel membership, you must enable App Context for your app's keyset in the Admin Portal.
When a user joins a channel or gets invited to it, a membership relationship between that user and the channel is created (Membership entity). The membership ends when this user leaves the channel.
Read on to learn how to check and update user-channel membership.
Get members
getMembers() returns the list of all channel members.
Method signature
This method takes the following parameters:
1channel.getMembers(
2    limit: Int? = nil,
3    page: PubNubHashedPage? = nil,
4    filter: String? = nil,
5    sort: [PubNub.MembershipSortField] = []
6) async throws -> (memberships: [MembershipImpl], page: PubNubHashedPage?)
Input
| Parameter | Description | 
|---|---|
| limitType:  IntDefault: 100 | Number of objects to return in response. The default (and maximum) value is 100(set through the underlying Swift SDK). | 
| pageType:  PubNubHashedPage?Default: nil | Object used for pagination to define which previous or next result page you want to fetch. | 
| filterType:  StringDefault: nil | Expression used to filter the results. Returns only these members whose properties satisfy the given expression. The filter language is defined here. | 
| sortType:  [PubNub.MembershipSortField]Default: [] | A collection to specify the sort order. Available options are id,name, andupdated. Useascordescto specify the sorting direction, or specifynullto take the default sorting direction (ascending). For example:{name: "asc"}.  Unless specified otherwise, the items are sorted by the last updated date. Defaults to an empty list. | 
Output
| Parameter | Description | 
|---|---|
| (memberships: [MembershipImpl], page: PubNubHashedPage?) | A tuple containing a set of channel members with membership and pagination information indicating the start, end, and total count of the members. | 
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.
List all members of the support channel on the premium support plan.
1// Assuming you have a reference of type "ChatImpl" named "chat"
2Task {
3  // Fetch the metadata of the "support" channel
4  if let channel = try await chat.getChannel(channelId: "support") {
5    // Check if the channel's custom data includes the "premium" support plan
6    if let customData = channel.custom, customData["supportPlan"]?.stringOptional == "premium" {
7      // List all members of the "support" channel
8      let members = try await channel.getMembers()
9      debugPrint("Fetched members: \(members)")
10      debugPrint("Next page (if any): \(String(describing: members.page))")
11    } else {
12      debugPrint("Channel not found")
13    }
14  } else {
15    debugPrint("Channel not found")
Get membership
getMemberships() returns the list of all channel memberships of a given user.
To get a list of all existing channels, use the getChannels() method.
Method signature
This method takes the following parameters:
1user.getMemberships(
2    limit: Int? = nil,
3    page: PubNubHashedPage? = nil,
4    filter: String? = nil,
5    sort: [PubNub.MembershipSortField] = []
6) async throws -> (memberships: [MembershipImpl], page: PubNubHashedPage?)
Input
| Parameter | Description | 
|---|---|
| limitType:  IntDefault: 100 | Number of objects to return in response. The default (and maximum) value is 100(set through the underlying Swift SDK). | 
| pageType:  PubNubHashedPageDefault: n/a | Object used for pagination to define which previous or next result page you want to fetch. | 
| filterType:  StringDefault: n/a | Expression used to filter the results. Returns only these members whose properties satisfy the given expression. The filter language is defined here. | 
| sortType:  [PubNub.MembershipSortField]Default: [] | A collection to specify the sort order. Available options are id,name, andupdated. Useascordescto specify the sorting direction, or specifynullto take the default sorting direction (ascending). For example:{name: "asc"}.  Unless specified otherwise, the items are sorted by the last updated date. Defaults to an empty list. | 
Output
| Parameter | Description | 
|---|---|
| (memberships: [MembershipImpl], page: PubNubHashedPage?) | Object containing a set of memberships and pagination information indicating the start, end, and total count of the memberships. | 
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.
Find out which channels the support_agent_15 user is a member of.
1// Assuming you have a reference of type "ChatImpl" named "chat"
2Task {
3  if let user = try await chat.getUser(userId: "support_agent_15") {
4    let memberships = try await user.getMemberships()
5    let channelIds = memberships.memberships.map { $0.channel.id }
6    debugPrint("User 'support_agent_15' is a member of channels: \(channelIds)")
7    debugPrint("Next page (if any): \(String(describing: memberships.page))")
8  } else {
9    debugPrint("User not found")
10  }
11}
Get updates
You can receive updates when specific user-channel Membership object(s) are edited (status, type, custom data) using the following methods:
- streamUpdates()checks updates on a single- Membershipobject and it's tied to an instance of the- Membershipclass.
- streamUpdatesOn()checks updates on a list of- Membershipobjects and it's tied to the- Membershipclass.
Membership changes
These methods notify you about field changes (e.g., metadata, status) for existing memberships, not new membership additions or removals.
Both methods return an asynchronous stream which produces a new value whenever someone adds, changes, or removes membership data.
Underneath, these methods subscribe the current user to a channel and add an objects event listener to receive all objects events of type membership. These methods also return the unsubscribe function you can invoke to stop receiving objects events and unsubscribe from the channel.
Method signature
These methods provide asynchronous streams for real-time updates on membership changes:
- 
streamUpdates()1membership.streamUpdates() -> AsyncStream<MembershipImpl>
- 
streamUpdatesOn()(static)1MembershipImpl.streamUpdatesOn(
 2 memberships: [MembershipImpl]
 3) -> AsyncStream<MembershipImpl>
Input
| Parameter | Required in streamUpdates() | Required in streamUpdatesOn() | Description | 
|---|---|---|---|
| membershipsType:  [MembershipImpl]Default: n/a | No | Yes | A collection of MembershipImplobjects from which you want to receive updates. | 
Output
| Component | Description | 
|---|---|
| AsyncStream<MembershipImpl> | An asynchronous stream providing updates on membership changes. It allows for real-time processing as new data becomes available. | 
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 updates on the first user membership.
- streamUpdates()
- AsyncStream
- Closure
1// Assuming you have a reference of type "ChatImpl" named "chat"
2Task {
3  if let membership = try await chat.currentUser.getMemberships(limit: 1).memberships.first {
4    for await updatedMembership in membership.streamUpdates() {
5      if let updatedMembership {
6        debugPrint("Received update for membership: \(updatedMembership)")
7      }
8    }
9  } else {
10    debugPrint("Membership not found")
11  }
12}
1// Important: Keep a strong reference to the returned "AutoCloseable" object as long as you want
2// to receive new updates. If the "AutoCloseable" is deallocated, the stream will be cancelled, 
3// and no further items will be produced. You can also stop receiving updates manually
4// by calling the "close()" method on the "AutoCloseable" object.
5
6/// Assuming you have a "membership" instance of "MembershipImpl" type
7autoCloseable = membership.streamUpdates { updatedMembership in
8  if let updatedMembership = updatedMembership {
9    debugPrint("Received update for membership with ID: \(updatedMembership.user.id)")
10  } else {
11    debugPrint("Membership has been deleted")
12  }
13}
Get updates on the first page of user memberships.
- streamUpdatesOn()
- AsyncStream
- Closure
1Task {
2  let getMembershipsRes = try await chat.currentUser.getMemberships(limit: 10)
3  let memberships = getMembershipsRes.memberships
4  
5  for await updatedMembership in MembershipImpl.streamUpdatesOn(memberships: memberships) {
6    debugPrint("Received update for membership: \(updatedMembership)")
7  }
8}    
1// Important: Keep a strong reference to the returned "AutoCloseable" object as long as you want
2// to receive new updates. If the "AutoCloseable" is deallocated, the stream will be cancelled, 
3// and no further items will be produced. You can also stop receiving updates manually
4// by calling the "close()" method on the "AutoCloseable" object
5
6// Assuming you have an array of "MembershipImpl" objects named "memberships"
7autoCloseable = MembershipImpl.streamUpdatesOn(memberships: memberships) { updatedMemberships in
8  for updatedMembership in updatedMemberships {
9    debugPrint("Received update for membership with channel ID: \(updatedMembership.channel.id)")
10  }
11}
Update
update() updates the channel membership information for a given user.
Method signature
This method takes the following parameters:
1membership.update(
2    custom: [String: JSONCodableScalar]
3) async throws -> MembershipImpl
Input
| Parameter | Description | 
|---|---|
| custom*Type:  [String: JSONCodableScalar]Default: n/a | Any custom properties or metadata associated with the channel-user membership in the form of a JSON. Values must be scalar only; arrays or objects are not supported. App Context filtering language doesn’t support filtering by custom properties. | 
Output
| Parameter | Description | 
|---|---|
| MembershipImpl | Returned (modified) object containing the membership data. | 
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.
Assign the premium-support role to support_agent_15 on the high-priority-incidents channel.
1// Assuming you have a reference of type "ChatImpl" named "chat"
2Task {
3  if let user = try await chat.getUser(userId: "support_agent_15") {
4    if let membership = try await user.getMemberships(filter: "channel.id == 'high-priority-incidents'").memberships.first {
5      let updatedMembership = try await membership.update(custom: ["role": "premium-support"])
6      debugPrint("Updated membership: \(updatedMembership)")
7    } else {
8      debugPrint("No memberhips found")
9    }
10  } else {
11    debugPrint("User not found")
12  }
13}