---
source_url: https://www.pubnub.com/docs/sdks/objective-c/api-reference/objects
title: App Context API for Objective- SDK
updated_at: 2026-05-22T11:07:09.161Z
sdk_name: PubNub Objective-C SDK
sdk_version: 7.0.2
---

> 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


# App Context API for Objective- SDK

PubNub Objective-C SDK, use the latest version: 7.0.2

Install:

```bash
pod install PubNub@7.0.2
```

This page describes App Context (formerly Objects v2). To upgrade from Objects v1, refer to the [migration guide](https://www.pubnub.com/docs/general/resources/migration-guides/objects-v2-migration).

App Context provides easy-to-use, serverless storage for user and channel data you need to build innovative, reliable, scalable applications. Use App Context to store metadata about your application users and channels, and their membership associations, without running your own databases.

PubNub also triggers events when object data changes: set, update, or removal. Setting the same data again doesn't trigger an event. Clients can receive these events in real time and update their front-end application accordingly.

## User

### Get metadata for all users

Returns a paginated list of UUID Metadata objects, optionally including the custom data object for each.

:::warning Required keyset configuration
To get all channel and user metadata, you must uncheck the
Disallow Get All Channel Metadata
and
Disallow Get All User Metadata
checkboxes in the App Context section of your keyset configuration in the
[Admin Portal](https://admin.pubnub.com)
.
:::

#### Method(s)

To `Get All UUID Metadata` you can use the following method(s) in the Objective-C SDK:

```objectivec
- (void)allUUIDMetadataWithRequest:(PNFetchAllUUIDMetadataRequest *)request 
                        completion:(PNFetchAllUUIDMetadataCompletionBlock)block;
```

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| request | PNFetchAllUUIDMetadataRequest | Yes |  | Request object for fetching all UUID metadata. |
| block | PNFetchAllUUIDMetadataCompletionBlock | Yes |  | Completion block. |

#### PNFetchAllUUIDMetadataRequest

| Parameter | Description |
| --- | --- |
| `sort`Type: NSArray`<NSString *>` | Sort by id, name, updated with asc/desc for sort direction (for example, `{name: 'asc'}`). |
| `includeFields`Type: PNUUIDFields | Bitfield of response fields. Supported: `PNUUIDTotalCountField` (total count), `PNUUIDCustomField` (UUID custom), `PNUUIDStatusField` (UUID status), `PNUUIDTypeField` (UUID type). Default is `PNUUIDTotalCountField` (set 0 to reset). |
| `filter`Type: NSString | Filter expression. Only matching objects are returned. See [filtering](https://www.pubnub.com/docs/general/metadata/filtering). |
| `start`Type: NSString | Cursor-based pagination. |
| `end`Type: NSString | Cursor-based pagination. Ignored if the `start` parameter is supplied. |
| `limit`Type: NSUInteger | Number of objects to return. Default/Max: 100. |

#### Sample code

```objectivec
#import <Foundation/Foundation.h>
#import <PubNub/PubNub.h>

// Basic configuration
PNConfiguration *config = [PNConfiguration configurationWithPublishKey:@"demo"
                                                          subscribeKey:@"demo"
                                                                userID:@"metadataUser"];

// Create a PubNub client instance
PubNub *client = [PubNub clientWithConfiguration:config];

// Example 1: Basic UUID metadata fetch
NSLog(@"Fetching all UUID metadata...");

// Create a basic request
PNFetchAllUUIDMetadataRequest *request = [PNFetchAllUUIDMetadataRequest new];

// Include custom fields and total count in the response
request.includeFields = PNUUIDCustomField | PNUUIDTotalCountField;

// Limit the number of results
request.limit = 25;

// Make the request
[client allUUIDMetadataWithRequest:request
                        completion:^(PNFetchAllUUIDMetadataResult *result, PNErrorStatus *status) {
    if (!status.isError) {
        NSLog(@"✅ Successfully fetched UUID metadata!");
        
        // Log the total count
        NSLog(@"Total UUID metadata count: %@", @(result.data.totalCount));
        
        // Log each metadata object
        for (PNUUIDMetadata *metadata in result.data.metadata) {
            NSLog(@"UUID: %@, Name: %@", metadata.uuid, metadata.name);
            
            if (metadata.custom) {
                NSLog(@"Custom data: %@", metadata.custom);
            }
            
            NSLog(@"Updated: %@", metadata.updated);
            NSLog(@"----------------");
        }
        
        // Log pagination tokens
        if (result.data.next) {
            NSLog(@"Next page token: %@", result.data.next);
        }
        
        if (result.data.prev) {
            NSLog(@"Previous page token: %@", result.data.prev);
        }
    } else {
        NSLog(@"❌ Error fetching UUID metadata: %@", status.errorData.information);
        NSLog(@"Error category: %@", @(status.category));
    }
}];

// Example 2: UUID metadata fetch with pagination
NSLog(@"Fetching UUID metadata with pagination...");

// Create a paginated request
PNFetchAllUUIDMetadataRequest *paginatedRequest = [PNFetchAllUUIDMetadataRequest new];

// Use this token from a previous request to get the next page
// In a real app, you would store this value from previous responses
paginatedRequest.start = @"dGhpc19pc19hX3NhbXBsZV90b2tlbg=="; // Sample token, replace with actual token

paginatedRequest.includeFields = PNUUIDCustomField | PNUUIDTotalCountField;
paginatedRequest.limit = 10; // Smaller limit to demonstrate pagination

// Sort by name in ascending order
paginatedRequest.sort = @[@"name:asc"];

[client allUUIDMetadataWithRequest:paginatedRequest
                        completion:^(PNFetchAllUUIDMetadataResult *result, PNErrorStatus *status) {
    if (!status.isError) {
        /**
         * UUID metadata successfully fetched.
         * Result object has following information:
         *   result.data.metadata - List of fetched UUID metadata.
         *   result.data.next - Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off.
         *   result.data.prev - Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data.
         *   result.data.totalCount - Total number of created UUID metadata.
         */
        
        NSLog(@"✅ Successfully fetched paginated UUID metadata!");
        NSLog(@"Page size: %lu", (unsigned long)result.data.metadata.count);
        
        // Store the next token for future pagination
        if (result.data.next) {
            NSLog(@"Next page token (save this for next request): %@", result.data.next);
        }
    } else {
        /**
         * Handle UUID metadata fetch error. Check 'category' property to find out possible
         * issue because of which request did fail.
         *
         * Request can be resent using: [status retry]
         */
        NSLog(@"❌ Error fetching paginated UUID metadata: %@", status.errorData.information);
    }
}];

// Example 3: UUID metadata fetch with filtering
NSLog(@"Fetching UUID metadata with filtering...");

PNFetchAllUUIDMetadataRequest *filteredRequest = [PNFetchAllUUIDMetadataRequest new];

// Filter for UUIDs with names containing "admin"
filteredRequest.filter = @"name LIKE '*admin*'";

// Include all available fields
filteredRequest.includeFields = PNUUIDCustomField | PNUUIDTotalCountField | PNUUIDStatusField | PNUUIDTypeField;

[client allUUIDMetadataWithRequest:filteredRequest
                        completion:^(PNFetchAllUUIDMetadataResult *result, PNErrorStatus *status) {
    if (!status.isError) {
        NSLog(@"✅ Successfully fetched filtered UUID metadata!");
        NSLog(@"Found %lu UUIDs matching filter criteria", (unsigned long)result.data.metadata.count);
        
        // Process the filtered results
        for (PNUUIDMetadata *metadata in result.data.metadata) {
            NSLog(@"UUID: %@, Name: %@", metadata.uuid, metadata.name);
            
            if (metadata.type) {
                NSLog(@"Type: %@", metadata.type);
            }
            
            if (metadata.status) {
                NSLog(@"Status: %@", metadata.status);
            }
        }
    } else {
        NSLog(@"❌ Error fetching filtered UUID metadata: %@", status.errorData.information);
    }
}];
```

#### Response

Response returned by the client for `fetch all UUID metadata`:

```objectivec
@interface PNFetchAllUUIDMetadataData : PNServiceData

// List of UUID metadata objects created for current subscribe key.
@property (nonatomic, readonly, strong) NSArray<PNUUIDMetadata *> *metadata;

// Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off.
@property (nonatomic, nullable, readonly, strong) NSString *next;

// Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data.
@property (nonatomic, nullable, readonly, strong) NSString *prev;

/**
 * Total number of objects created for current subscribe key.
 *
 * Value will be 0 in case if PNUUIDTotalCountField not added to 'includeFields'
 * of PNFetchAllUUIDMetadataRequest.
 */
@property (nonatomic, readonly, assign) NSUInteger totalCount;

@end

@interface PNFetchAllUUIDMetadataResult : PNResult

// Fetch all UUID metadata request processed information.
@property (nonatomic, readonly, strong) PNFetchAllUUIDMetadataData *data;

@end
```

Error response which is used in case of App Context API call failure:

```objectivec
@interface PNErrorData : PNServiceData

// Stringified error information.
@property (nonatomic, readonly, strong) NSString *information;

@end

@interface PNErrorStatus : PNStatus

// Whether status object represent error or not.
@property (nonatomic, readonly, assign, getter = isError) BOOL error;

// Additional information related to error status object.
@property (nonatomic, readonly, strong) PNErrorData *errorData;

@end
```

### Get metadata for all users (builder pattern)

:::warning Required keyset configuration
To get all channel and user metadata, you must uncheck the
Disallow Get All Channel Metadata
and
Disallow Get All User Metadata
checkboxes in the App Context section of your keyset configuration in the
[Admin Portal](https://admin.pubnub.com)
.
:::

#### Method(s)

```objectivec
objects()
    .allUUIDMetadata()
    .includeFields(PNUUIDFields)
    .includeCount(BOOL)
    .filter(NSString *)
    .sort(NSArray<NSString *> *)
    .limit(NSUInteger)
    .start(NSString *)
    .end(NSString *)
    .performWithCompletion(PNFetchAllUUIDMetadataCompletionBlock);
```

| Parameter | Description |
| --- | --- |
| `includeFields`Type: PNUUIDFields | Bitfield of response fields. Supported: `PNUUIDTotalCountField` (number of UUID metadata records), `PNUUIDCustomField` (custom set during UUID metadata set), `PNUUIDStatusField` (status set during UUID metadata set), `PNUUIDTypeField` (type set during UUID metadata set). Default is `PNUUIDTotalCountField` (set 0 to reset). |
| `includeCount`Type: BOOL | Whether to include the total count in the paginated response. Default: `YES` |
| `filter`Type: NSString | Filter expression. Only matching objects are returned. See [filtering](https://www.pubnub.com/docs/general/metadata/filtering). |
| `sort`Type: NSArray | Sort by id, name, updated with asc/desc for sort direction (for example, `{name: 'asc'}`). |
| `limit`Type: NSUInteger | Number of objects to return. Default/Max: 100. |
| `start`Type: NSString | Cursor-based pagination. |
| `end`Type: NSString | Cursor-based pagination. Ignored if the `start` parameter is supplied. |
| `block` *Type: PNFetchAllUUIDMetadataCompletionBlock | Associated `metadata fetch` completion handler block. |

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

#### Sample code

```objectivec
self.client.objects().allUUIDMetadata()
    .start(@"<next from previous request>")
    .includeFields(PNUUIDCustomField)
    .includeCount(YES)
    .limit(40)
    .performWithCompletion(^(PNFetchAllUUIDMetadataResult *result, PNErrorStatus *status) {
        if (!status.isError) {
            /**
             * UUID metadata successfully fetched.
             * Result object has following information:
             *   result.data.metadata - List of fetched UUID metadata.
             *   result.data.next - Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off.
             *   result.data.prev - Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data.
             *   result.data.totalCount - Total number of created UUID metadata.
             */
        } else {
            /**
             * Handle UUID metadata fetch error. Check 'category' property to find out possible
             * issue because of which request did fail.
             *
             * Request can be resent using: [status retry]
             */
        }
    });
```

#### Response

Response returned by the client for `fetch all UUID metadata`:

```objectivec
@interface PNFetchAllUUIDMetadataData : PNServiceData

// List of UUID metadata objects created for current subscribe key.
@property (nonatomic, readonly, strong) NSArray<PNUUIDMetadata *> *metadata;

// Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off.
@property (nonatomic, nullable, readonly, strong) NSString *next;

// Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data.
@property (nonatomic, nullable, readonly, strong) NSString *prev;

/**
 * Total number of objects created for current subscribe key.
 *
 * Value will be 0 in case if PNUUIDTotalCountField not added to 'includeFields'
 * of PNFetchAllUUIDMetadataRequest.
 */
@property (nonatomic, readonly, assign) NSUInteger totalCount;

@end

@interface PNFetchAllUUIDMetadataResult : PNResult

// Fetch all UUID metadata request processed information.
@property (nonatomic, readonly, strong) PNFetchAllUUIDMetadataData *data;

@end
```

Error response which is used in case of App Context API call failure:

```objectivec
@interface PNErrorData : PNServiceData

// Stringified error information.
@property (nonatomic, readonly, strong) NSString *information;

@end

@interface PNErrorStatus : PNStatus

// Whether status object represent error or not.
@property (nonatomic, readonly, assign, getter = isError) BOOL error;

// Additional information related to error status object.
@property (nonatomic, readonly, strong) PNErrorData *errorData;

@end
```

### Get user metadata

Returns metadata for the specified UUID, optionally including the custom data object for each.

#### Method(s)

To `Get UUID Metadata` you can use the following method(s) in the Objective-C SDK:

```objectivec
- (void)uuidMetadataWithRequest:(PNFetchUUIDMetadataRequest *)request 
                     completion:(PNFetchUUIDMetadataCompletionBlock)block;
```

| Parameter | Description |
| --- | --- |
| `request` *Type: [PNFetchUUIDMetadataRequest](#pnfetchuuidmetadatarequest) | Request object for fetching UUID metadata. |
| `block` *Type: PNFetchUUIDMetadataCompletionBlock | Completion block. |

#### PNFetchUUIDMetadataRequest

| Parameter | Description |
| --- | --- |
| `includeFields`Type: PNUUIDFields | Bitfield of response fields. Supported: `PNUUIDCustomField` (custom set during UUID metadata set), `PNUUIDStatusField` (status set during UUID metadata set), `PNUUIDTypeField` (type set during UUID metadata set). |
| `uuid`Type: NSString | Create and configure fetch `UUID` metadata request. `uuid` - Identifier for metadata should be fetched. Will be set to current PubNub configuration uuid if nil is set. |

#### Sample code

```objectivec
PNFetchUUIDMetadataRequest *request = [PNFetchUUIDMetadataRequest requestWithUUID:@"uuid"];
// Add this request option, if returned metadata model should have value which has been set to
// 'custom' property.
request.includeFields = PNUUIDCustomField;

[self.client uuidMetadataWithRequest:request
                          completion:^(PNFetchUUIDMetadataResult *result, PNErrorStatus *status) {

    if (!status.isError) {
        /**
         * UUID metadata successfully fetched.
         * Fetched UUID metadata information available here: result.data.metadata
         */
    } else {
        /**
         * Handle UUID metadata fetch error. Check 'category' property to find out possible issue
         * because of which request did fail.
         *
         * Request can be resent using: [status retry]
         */
    }
}];
```

#### Response

Response returned by the client for `fetch UUID metadata`:

```objectivec
@interface PNFetchUUIDMetadataData : PNServiceData

// Requested UUID metadata object.
@property (nonatomic, nullable, readonly, strong) PNUUIDMetadata *metadata;

@end

@interface PNFetchUUIDMetadataResult : PNResult

// Fetch UUID metadata request processed information.
@property (nonatomic, readonly, strong) PNFetchUUIDMetadataData *data;

@end
```

Error response which is used in case of App Context API call failure:

```objectivec
@interface PNErrorData : PNServiceData

// Stringified error information.
@property (nonatomic, readonly, strong) NSString *information;

@end

@interface PNErrorStatus : PNStatus

// Whether status object represent error or not.
@property (nonatomic, readonly, assign, getter = isError) BOOL error;

// Additional information related to error status object.
@property (nonatomic, readonly, strong) PNErrorData *errorData;

@end
```

### Get user metadata (builder pattern)

#### Method(s)

```objectivec
objects()
    .uuidMetadata()
    .uuid(NSString *)
    .includeFields(PNUUIDFields)
    .performWithCompletion(PNFetchUUIDMetadataCompletionBlock);
```

| Parameter | Description |
| --- | --- |
| `uuid`Type: NSString | Identifier for which associated `metadata` should be fetched. Default: configured PubNub client `uuid` |
| `includeFields`Type: PNUUIDFields | Bitfield of response fields. Supported: `PNUUIDCustomField` (custom set during UUID metadata set), `PNUUIDStatusField` (status set during UUID metadata set), `PNUUIDTypeField` (type set during UUID metadata set). |
| `block` *Type: PNFetchUUIDMetadataCompletionBlock | `Fetch UUID metadata` request completion `block`. |

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

#### Sample code

```objectivec
self.client.objects().uuidMetadata()
    .uuid(@"uuid")
    .includeFields(PNUUIDCustomField)
    .performWithCompletion(^(PNFetchUUIDMetadataResult *result, PNErrorStatus *status) {
      if (!status.isError) {
          /**
           * UUID metadata successfully fetched.
           * Fetched UUID metadata information available here: result.data.metadata
           */
      } else {
          /**
           * Handle UUID metadata fetch error. Check 'category' property to find out possible issue
           * because of which request did fail.
           *
           * Request can be resent using: [status retry]
           */
      }
    });
```

#### Response

Response returned by the client for `fetch UUID metadata`:

```objectivec
@interface PNFetchUUIDMetadataData : PNServiceData

// Requested UUID metadata object.
@property (nonatomic, nullable, readonly, strong) PNUUIDMetadata *metadata;

@end

@interface PNFetchUUIDMetadataResult : PNResult

// Fetch UUID metadata request processed information.
@property (nonatomic, readonly, strong) PNFetchUUIDMetadataData *data;

@end
```

Error response which is used in case of App Context API call failure:

```objectivec
@interface PNErrorData : PNServiceData

// Stringified error information.
@property (nonatomic, readonly, strong) NSString *information;

@end

@interface PNErrorStatus : PNStatus

// Whether status object represent error or not.
@property (nonatomic, readonly, assign, getter = isError) BOOL error;

// Additional information related to error status object.
@property (nonatomic, readonly, strong) PNErrorData *errorData;

@end
```

### Set user metadata

:::warning Unsupported partial updates of custom metadata
The value of the custom metadata parameter sent in this method always overwrites the value stored on PubNub servers. If you want to add new custom data to an existing one, you must:
1. Get the existing metadata and store it locally.
2. Append the new custom metadata to the existing one.
3. Set the entire updated custom object.
:::

Set metadata for a UUID in the database, optionally including the custom data object for each.

#### Method(s)

To `Set UUID Metadata` you can use the following method(s) in the Objective-C SDK:

```objectivec
- (void)setUUIDMetadataWithRequest:(PNSetUUIDMetadataRequest *)request 
                        completion:(nullable PNSetUUIDMetadataCompletionBlock)block;
```

| Parameter | Description |
| --- | --- |
| `request` *Type: [PNSetUUIDMetadataRequest](#pnsetuuidmetadatarequest) | Request object for setting UUID metadata. |
| `block`Type: PNSetUUIDMetadataCompletionBlock | `Set UUID metadata` request completion `block`. |

#### PNSetUUIDMetadataRequest

| Parameter | Description |
| --- | --- |
| `custom`Type: NSDictionary | Additional / complex attributes which should be associated with metadata. [App Context filtering language](https://www.pubnub.com/docs/general/metadata/filtering) doesn't support filtering by custom properties. |
| `externalId`Type: NSString | Identifier from external service (database, auth service). |
| `profileUrl`Type: NSString | URL at which profile available. |
| `includeFields`Type: PNUUIDFields | Bitfield of response fields. Supported: `PNUUIDCustomField` (custom set during UUID metadata set), `PNUUIDStatusField` (status set during UUID metadata set), `PNUUIDTypeField` (type set during UUID metadata set). |
| `email`Type: NSString | Email address. |
| `name`Type: NSString | Name which should be stored in metadata associated with specified identifier. |
| `uuid`Type: NSString | Create and configure set UUID metadata request. `uuid` - Identifier with which \c metadata is linked. Will be set to current PubNub configuration uuid if nil is set. |
| `status`Type: NSString | The custom status of the user. |
| `type`Type: NSString | The custom type of the user. |
| `ifMatchesEtag`Type: NSString | The entity tag to be used to ensure updates only happen if the object hasn't been modified since it was read. Use the eTag you received from an applicable get metadata method to check against the server entity tag. If the eTags don't match, an HTTP 412 error is thrown. |

:::tip API limits
To learn about the maximum length of parameters used to set user metadata, refer to [REST API docs](https://www.pubnub.com/docs/sdks/rest-api/set-user-metadata).
:::

#### Sample code

```objectivec
PNSetUUIDMetadataRequest *request = [PNSetUUIDMetadataRequest requestWithUUID:@"uuid"];
// With this option on, returned metadata model will have value which has been set to 'custom'
// property.
request.includeFields = PNUUIDCustomField;
request.custom = @{ @"age": @(39), @"status": @"Checking some stuff..." };
request.email = @"support@pubnub.com";
request.name = @"David";

[self.client setUUIDMetadataWithRequest:request completion:^(PNSetUUIDMetadataStatus *status) {
    if (!status.isError) {
        /**
         * UUID metadata successfully has been set.
         * UUID metadata information available here: status.data.metadata
         */
    } else {
        /**
         * Handle UUID metadata set error. Check 'category' property to find out possible issue
         * because of which request did fail.
         *
         * Request can be resent using: [status retry]
         */
    }
}];
```

#### Response

Response returned by the client for `set UUID metadata`:

```objectivec
@interface PNSetUUIDMetadataData : PNServiceData

// Updated UUID metadata object.
@property (nonatomic, nullable, readonly, strong) PNUUIDMetadata *metadata;

@end

@interface PNSetUUIDMetadataStatus : PNAcknowledgmentStatus

// Set UUID metadata request processed information.
@property (nonatomic, readonly, strong) PNSetUUIDMetadataData *data;

@end
```

### Set user metadata (builder pattern)

#### Method(s)

```objectivec
objects()
    .setUUIDMetadata()
    .uuid(NSString *)
    .name(NSString *)
    .externalId(NSString *)
    .profileUrl(NSString *)
    .custom(NSDictionary *)
    .email(NSString *)
    .includeFields(PNUUIDFields)
    .performWithCompletion(nullable PNSetUUIDMetadataCompletionBlock);
```

:::tip API limits
To learn about the maximum length of parameters used to set user metadata, refer to [REST API docs](https://www.pubnub.com/docs/sdks/rest-api/set-user-metadata).
:::

| Parameter | Description |
| --- | --- |
| `uuid`Type: NSString | Identifier with which new `metadata` should be associated. Default: configured PubNub client `uuid` |
| `name`Type: NSString | Name which should stored in `metadata` associated with specified `UUID`. |
| `externalId`Type: NSString | External identifier (database, auth service) associated with specified `UUID`. |
| `profileUrl`Type: NSString | External URL with information for specified `UUID` representation. |
| `custom`Type: NSDictionary | Additional information which should be stored in `metadata` associated with specified `UUID`. [App Context filtering language](https://www.pubnub.com/docs/general/metadata/filtering) doesn't support filtering by custom properties. |
| `email`Type: NSString | Email address which should be stored in `metadata` associated with specified `UUID`. |
| `includeFields`Type: PNUUIDFields | Bitfield of response fields. Supported: `PNUUIDCustomField` (custom set during UUID metadata set), `PNUUIDStatusField` (status set during UUID metadata set), `PNUUIDTypeField` (type set during UUID metadata set). |
| `block`Type: PNSetUUIDMetadataCompletionBlock | `Set UUID metadata` request completion `block`. |

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

#### Sample code

```objectivec
self.client.objects().setUUIDMetadata()
    .uuid(@"uuid")
    .name(@"Serhii")
    .externalId(@"93FVfHUAf4RLu79J7Q3ejLVu")
    .profileUrl(@"https://pubnub.com")
    .custom(@{ @"age": @(36) })
    .email(@"support@pubnub.com")
    .includeFields(PNUUIDCustomField)
    .performWithCompletion(^(PNSetUUIDMetadataStatus *status) {
        if (!status.isError) {
            /**
             * UUID metadata successfully has been set.
             * UUID metadata information available here: status.data.metadata
             */
        } else {
            /**
             * Handle UUID metadata set error. Check 'category' property to find out possible issue
             * because of which request did fail.
             *
             * Request can be resent using: [status retry]
             */
        }
    });
```

#### Response

Response returned by the client for `set UUID metadata`:

```objectivec
@interface PNSetUUIDMetadataData : PNServiceData

// Updated UUID metadata object.
@property (nonatomic, nullable, readonly, strong) PNUUIDMetadata *metadata;

@end

@interface PNSetUUIDMetadataStatus : PNAcknowledgmentStatus

// Set UUID metadata request processed information.
@property (nonatomic, readonly, strong) PNSetUUIDMetadataData *data;

@end
```

### Remove user metadata

Removes the metadata from a specified UUID.

#### Method(s)

To `Remove UUID Metadata` you can use the following method(s) in the Objective-C SDK:

```objectivec
- (void)removeUUIDMetadataWithRequest:(PNRemoveUUIDMetadataRequest *)request 
                           completion:(nullable PNRemoveUUIDMetadataCompletionBlock)block;
```

| Parameter | Description |
| --- | --- |
| `request` *Type: [PNRemoveUUIDMetadataRequest](#pnremoveuuidmetadatarequest) | Request object for removing UUID metadata. |
| `block`Type: PNRemoveUUIDMetadataCompletionBlock | `Remove UUID metadata` request completion `block`. |

#### PNRemoveUUIDMetadataRequest

| Parameter | Description |
| --- | --- |
| `uuid`Type: NSString | Create and configure delete user request. `identifier` - Create and configure remove `UUID` metadata request. Will be set to current PubNub configuration uuid if nil is set. |

#### Sample code

```objectivec
PNRemoveUUIDMetadataRequest *request = [PNRemoveUUIDMetadataRequest requestWithUUID:@"uuid"];

[self.client removeUUIDMetadataWithRequest:request completion:^(PNAcknowledgmentStatus *status) {
    if (!status.isError) {
        // UUID metadata successfully removed.
    } else {
        /**
         * Handle UUID metadata remove error. Check 'category' property to find out possible
         * issue because of which request did fail.
         *
         * Request can be resent using: [status retry]
         */
    }
}];
```

#### Response

Response returned by the client for `remove UUID metadata`:

```objectivec
@interface PNErrorData : PNServiceData

// Stringified error information.
@property (nonatomic, readonly, strong) NSString *information;

@end

@interface PNAcknowledgmentStatus : PNErrorStatus

// Whether status object represent error or not.
@property (nonatomic, readonly, assign, getter = isError) BOOL error;

// Additional information related to error status object.
@property (nonatomic, readonly, strong) PNErrorData *errorData;

@end
```

### Remove user metadata (builder pattern)

#### Method(s)

```objectivec
objects()
    .removeUUIDMetadata()
    .uuid(NSString *)
    .performWithCompletion(PNFetchUUIDMetadataCompletionBlock);
```

| Parameter | Description |
| --- | --- |
| `uuid`Type: NSString | Identifier for which associated `metadata` should be removed. Default: configured PubNub client `uuid` |
| `block`Type: PNRemoveUUIDMetadataCompletionBlock | `Remove UUID metadata` request completion `block`. |

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

#### Sample code

```objectivec
self.client.objects().removeUUIDMetadata()
    .uuid(@"uuid")
    .performWithCompletion(^(PNAcknowledgmentStatus *status) {
        if (!status.isError) {
             // User successfully deleted.
        } else {
            /**
             * Handle user delete error. Check 'category' property to find out possible issue
             * because of which request did fail.
             *
             * Request can be resent using: [status retry]
             */
        }
    });
```

#### Response

Response returned by the client for `remove UUID metadata`:

```objectivec
@interface PNErrorData : PNServiceData

// Stringified error information.
@property (nonatomic, readonly, strong) NSString *information;

@end

@interface PNAcknowledgmentStatus : PNErrorStatus

// Whether status object represent error or not.
@property (nonatomic, readonly, assign, getter = isError) BOOL error;

// Additional information related to error status object.
@property (nonatomic, readonly, strong) PNErrorData *errorData;

@end
```

## Channel

### Get metadata for all channels

Returns a paginated list of Channel Metadata objects, optionally including the custom data object for each.

:::warning Required keyset configuration
To get all channel and user metadata, you must uncheck the
Disallow Get All Channel Metadata
and
Disallow Get All User Metadata
checkboxes in the App Context section of your keyset configuration in the
[Admin Portal](https://admin.pubnub.com)
.
:::

#### Method(s)

To `Get All Channel Metadata` you can use the following method(s) in the Objective-C SDK:

```objectivec
- (void)allChannelsMetadataWithRequest:(PNFetchAllChannelsMetadataRequest *)request 
                            completion:(PNFetchAllChannelsMetadataCompletionBlock)block;
```

| Parameter | Description |
| --- | --- |
| `request` *Type: [PNFetchAllChannelsMetadataRequest](#pnfetchallchannelsmetadatarequest) | Request object for fetching all channel metadata. |
| `block` *Type: PNFetchAllChannelsMetadataCompletionBlock | Completion block. |

#### PNFetchAllChannelsMetadataRequest

| Parameter | Description |
| --- | --- |
| `includeFields`Type: PNChannelFields | Bitfield of response fields. Supported: `PNChannelTotalCountField` (number of channel metadata records), `PNChannelCustomField` (custom set during channel metadata set), `PNChannelStatusField` (status set during channel metadata set), `PNChannelTypeField` (type set during channel metadata set). Default is `PNChannelTotalCountField` (set 0 to reset). |
| `sort`Type: NSArray`<NSString *>` | List of criteria (name of field) which should be used for sorting in ascending order. Available options are `id`, `name`, and `updated`. Use `asc` or `desc` to specify sort direction. For example: `{name: 'asc'}` |
| `filter`Type: NSString | Filter expression. Only matching objects are returned. See [filtering](https://www.pubnub.com/docs/general/metadata/filtering). |
| `start`Type: NSString | Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off. |
| `end`Type: NSString | Cursor-based pagination. Ignored if the `start` parameter is supplied. |
| `limit`Type: NSUInteger | Number of objects to return. Default/Max: 100. |

#### Sample code

```objectivec
PNFetchAllChannelsMetadataRequest *request = [PNFetchAllChannelsMetadataRequest new];
request.start = @"<next from previous request>";
// Add this request option, if returned metadata models should have value which has been set to
// 'custom' property.
request.includeFields = PNUUIDCustomField | PNUUIDTotalCountField;
request.limit = 40;

[self.client allChannelsMetadataWithRequest:request
                                 completion:^(PNFetchAllChannelsMetadataResult *result, PNErrorStatus *status) {
    if (!status.isError) {
        /**
         * Channels metadata successfully fetched.
         * Result object has following information:
         *   result.data.metadata - List of fetched channels metadata.
         *   result.data.next - Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off.
         *   result.data.prev - Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data.
         *   result.data.totalCount - Total number of associated channel metadata.
    } else {
        /**
         * Handle channels metadata fetch error. Check 'category' property to find out possible
         * issue because of which request did fail.
         *
         * Request can be resent using: [status retry]
         */
    }
}];
```

#### Response

Response returned by the client for `fetch all UUID metadata`:

```objectivec
@interface PNFetchAllChannelsMetadataData : PNServiceData

// List of channels metadata objects created for current subscribe key.
@property (nonatomic, readonly, strong) NSArray<PNChannelMetadata *> *metadata;

// Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off.
@property (nonatomic, nullable, readonly, strong) NSString *next;

// Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data.
@property (nonatomic, nullable, readonly, strong) NSString *prev;

/**
 * Total number of objects created for current subscribe key.
 *
 * Value will be 0 in case if PNChannelTotalCountField not added to 'includeFields'
 * of PNFetchAllChannelsMetadataRequest.
 */
@property (nonatomic, readonly, assign) NSUInteger totalCount;

@end

@interface PNFetchAllChannelsMetadataResult : PNResult

// Fetch all channels metadata request processed information.
@property (nonatomic, readonly, strong) PNFetchAllChannelsMetadataData *data;

@end
```

Error response which is used in case of App Context API call failure:

```objectivec
@interface PNErrorData : PNServiceData

// Stringified error information.
@property (nonatomic, readonly, strong) NSString *information;

@end

@interface PNErrorStatus : PNStatus

// Whether status object represent error or not.
@property (nonatomic, readonly, assign, getter = isError) BOOL error;

// Additional information related to error status object.
@property (nonatomic, readonly, strong) PNErrorData *errorData;

@end
```

### Get metadata for all channels (builder pattern)

#### Method(s)

```objectivec
objects()
    .allChannelsMetadata()
    .includeFields(PNChannelFields)
    .includeCount(BOOL)
    .filter(NSString)
    .sort(NSArray)
    .limit(NSUInteger)
    .start(NSString)
    .end(NSString)
    .performWithCompletion(PNFetchChannelMetadataCompletionBlock);
```

| Parameter | Description |
| --- | --- |
| `includeFields`Type: PNChannelFields | Bitfield of response fields. Supported: `PNChannelTotalCountField` (number of channel metadata records), `PNChannelCustomField` (custom set during channel metadata set), `PNChannelStatusField` (status set during channel metadata set), `PNChannelTypeField` (type set during channel metadata set). Default is `PNChannelTotalCountField` (set 0 to reset). |
| `includeCount`Type: BOOL | Whether to include the total count in the paginated response. Default: `YES` |
| `filter`Type: NSString | Filter expression. Only matching objects are returned. See [filtering](https://www.pubnub.com/docs/general/metadata/filtering). |
| `sort`Type: NSArray | Sort by id, name, updated with asc/desc for sort direction (for example, `{name: 'asc'}`). |
| `limit`Type: NSUInteger | Number of objects to return. Default/Max: 100. |
| `start`Type: NSString | Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off. |
| `end`Type: NSString | Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data. Ignored if the `start` parameter is supplied. |
| `block` *Type: PNFetchAllChannelsMetadataCompletionBlock | `Fetch all UUID metadata` request completion `block`. |

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

#### Sample code

```objectivec
self.client.objects().allChannelsMetadata()
    .start(@"<next from previous request>")
    .includeFields(PNChannelCustomField)
    .includeCount(YES)
    .limit(40)
    .performWithCompletion(^(PNFetchAllChannelsMetadataResult *result, PNErrorStatus *status) {
        if (!status.isError) {
            /**
             * Channels metadata successfully fetched.
             * Result object has following information:
             *   result.data.metadata - List of fetched channels metadata.
             *   result.data.next - Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off.
             *   result.data.prev - Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data.
             *   result.data.totalCount - Total number of associated channel metadata.
        } else {
            /**
             * Handle channels metadata fetch error. Check 'category' property to find out possible
             * issue because of which request did fail.
             *
             * Request can be resent using: [status retry]
             */
        }
    });
```

#### Response

Response returned by the client for `fetch all UUID metadata`:

```objectivec
@interface PNFetchAllChannelsMetadataData : PNServiceData

// List of channels metadata objects created for current subscribe key.
@property (nonatomic, readonly, strong) NSArray<PNChannelMetadata *> *metadata;

// Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off.
@property (nonatomic, nullable, readonly, strong) NSString *next;

// Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data.
@property (nonatomic, nullable, readonly, strong) NSString *prev;

/**
 * Total number of objects created for current subscribe key.
 *
 * Value will be 0 in case if PNChannelTotalCountField not added to 'includeFields'
 * of PNFetchAllChannelsMetadataRequest.
 */
@property (nonatomic, readonly, assign) NSUInteger totalCount;

@end

@interface PNFetchAllChannelsMetadataResult : PNResult

// Fetch all channels metadata request processed information.
@property (nonatomic, readonly, strong) PNFetchAllChannelsMetadataData *data;

@end
```

Error response which is used in case of App Context API call failure:

```objectivec
@interface PNErrorData : PNServiceData

// Stringified error information.
@property (nonatomic, readonly, strong) NSString *information;

@end

@interface PNErrorStatus : PNStatus

// Whether status object represent error or not.
@property (nonatomic, readonly, assign, getter = isError) BOOL error;

// Additional information related to error status object.
@property (nonatomic, readonly, strong) PNErrorData *errorData;

@end
```

### Get channel metadata

Returns metadata for the specified Channel, optionally including the custom data object for each.

#### Method(s)

To `Get Channel Metadata` you can use the following method(s) in the Objective-C SDK:

```objectivec
- (void)channelMetadataWithRequest:(PNFetchChannelMetadataRequest *)request 
                        completion:(PNFetchChannelMetadataCompletionBlock)block;
```

| Parameter | Description |
| --- | --- |
| `request` *Type: [PNFetchChannelMetadataRequest](#pnfetchchannelmetadatarequest) | Request object for fetching channel metadata. |
| `block` *Type: PNFetchChannelMetadataCompletionBlock | Completion block. |

#### PNFetchChannelMetadataRequest

| Parameter | Description |
| --- | --- |
| `includeFields`Type: PNChannelFields | Bitfield of response fields. Supported: `PNChannelCustomField` (custom set during channel metadata set), `PNChannelStatusField` (status set during channel metadata set), `PNChannelTypeField` (type set during channel metadata set). |
| `channel`Type: NSString | Create and configure fetch channel metadata request. `channel` - Name of channel for which metadata should be fetched. |

#### Sample code

```objectivec
PNFetchChannelMetadataRequest *request = [PNFetchChannelMetadataRequest requestWithChannel:@"channel"];
// Add this request option, if returned metadata model should have value which has been set to
// 'custom' property.
request.includeFields = PNChannelCustomField;

[self.client channelMetadataWithRequest:request
                             completion:^(PNFetchChannelsMetadataResult *result, PNErrorStatus *status) {

    if (!status.isError) {
        /**
         * Channel metadata successfully fetched.
         * Channel metadata information available here: result.data.metadata
         */
    } else {
        /**
         * Handle channel metadata fetch error. Check 'category' property to find out possible
         * issue because of which request did fail.
         *
         * Request can be resent using: [status retry]
         */
    }
}];
```

#### Response

Response returned by the client for `fetch channel metadata`:

```objectivec
@interface PNFetchChannelMetadataData : PNServiceData

// Requested channel metadata object.
@property (nonatomic, nullable, readonly, strong) PNChannelMetadata *metadata;

@end

@interface PNFetchChannelsMetadataResult : PNResult

// Fetch channel metadata request processed information.
@property (nonatomic, readonly, strong) PNFetchChannelMetadataData *data;

@end
```

Error response which is used in case of App Context API call failure:

```objectivec
@interface PNErrorData : PNServiceData

// Stringified error information.
@property (nonatomic, readonly, strong) NSString *information;

@end

@interface PNErrorStatus : PNStatus

// Whether status object represent error or not.
@property (nonatomic, readonly, assign, getter = isError) BOOL error;

// Additional information related to error status object.
@property (nonatomic, readonly, strong) PNErrorData *errorData;

@end
```

### Get channel metadata (builder pattern)

#### Method(s)

```objectivec
objects()
    .channelMetadata(NSString *)
    .includeFields(PNChannelFields)
    .performWithCompletion(PNFetchChannelMetadataCompletionBlock);
```

| Parameter | Description |
| --- | --- |
| `channel` *Type: NSString | Name of channel for which associated `metadata` should be fetched. |
| `includeFields`Type: NSString | Bitfield set to fields which should be returned with response. **Supported fields:** PNChannelCustomField - include field with additional information from metadata which has been used during channel metadata set requests., PNChannelStatusField - include field with metadata status which has been used during channel metadata set requests, PNChannelTypeField - Include field with metadata type which has been used during channel metadata set requests. |
| `block` *Type: PNFetchChannelMetadataCompletionBlock | `Fetch channel metadata` request completion `block`. |

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

#### Sample code

```objectivec
self.client.objects().channelMetadata(@"channel")
    .includeFields(PNChannelCustomField)
    .performWithCompletion(^(PNFetchChannelsMetadataResult *result, PNErrorStatus *status) {
        if (!status.isError) {
            /**
             * Channel metadata successfully fetched.
             * Channel metadata information available here: result.data.metadata
             */
        } else {
            /**
             * Handle channel metadata fetch error. Check 'category' property to find out possible
             * issue because of which request did fail.
             *
             * Request can be resent using: [status retry]
             */
        }
    });
```

#### Response

Response returned by the client for `fetch channel metadata`:

```objectivec
@interface PNFetchChannelMetadataData : PNServiceData

// Requested channel metadata object.
@property (nonatomic, nullable, readonly, strong) PNChannelMetadata *metadata;

@end

@interface PNFetchChannelsMetadataResult : PNResult

// Fetch channel metadata request processed information.
@property (nonatomic, readonly, strong) PNFetchChannelMetadataData *data;

@end
```

Error response which is used in case of App Context API call failure:

```objectivec
@interface PNErrorData : PNServiceData

// Stringified error information.
@property (nonatomic, readonly, strong) NSString *information;

@end

@interface PNErrorStatus : PNStatus

// Whether status object represent error or not.
@property (nonatomic, readonly, assign, getter = isError) BOOL error;

// Additional information related to error status object.
@property (nonatomic, readonly, strong) PNErrorData *errorData;

@end
```

### Set channel metadata

:::warning Unsupported partial updates of custom metadata
The value of the custom metadata parameter sent in this method always overwrites the value stored on PubNub servers. If you want to add new custom data to an existing one, you must:
1. Get the existing metadata and store it locally.
2. Append the new custom metadata to the existing one.
3. Set the entire updated custom object.
:::

Set metadata for a Channel in the database, optionally including the custom data object for each.

#### Method(s)

To `Set Channel Metadata` you can use the following method(s) in the Objective-C SDK:

```objectivec
- (void)setChannelMetadataWithRequest:(PNSetChannelMetadataRequest *)request 
                           completion:(nullable PNSetChannelMetadataCompletionBlock)block;
```

| Parameter | Description |
| --- | --- |
| `request` *Type: [PNSetChannelMetadataRequest](#pnsetchannelmetadatarequest) | Request object for setting channel metadata. |
| `block`Type: PNSetChannelMetadataCompletionBlock | `Set channel metadata` request completion `block`. |

#### PNSetChannelMetadataRequest

| Parameter | Description |
| --- | --- |
| `custom`Type: NSDictionary | Additional / complex attributes which should be stored in metadata associated with specified channel. [App Context filtering language](https://www.pubnub.com/docs/general/metadata/filtering) doesn't support filtering by custom properties. |
| `information`Type: NSString | Description which should be stored in metadata associated with specified channel. |
| `includeFields`Type: PNChannelFields | Bitfield of response fields. Supported: `PNChannelCustomField` (custom set during channel metadata set), `PNChannelStatusField` (status set during channel metadata set), `PNChannelTypeField` (type set during channel metadata set). |
| `name`Type: NSString | Name which should be stored in metadata associated with specified channel. |
| `channel`Type: NSString | Create and configure set channel metadata request. `channel` - Name of channel for which metadata should be set. |
| `status`Type: NSString | The custom status of the channel. |
| `type`Type: NSString | The custom type of the channel. |
| `ifMatchesEtag`Type: NSString | The entity tag to be used to ensure updates only happen if the object hasn't been modified since it was read. Use the eTag you received from an applicable get metadata method to check against the server entity tag. If the eTags don't match, an HTTP 412 error is thrown. |

:::tip API limits
To learn about the maximum length of parameters used to set channel metadata, refer to [REST API docs](https://www.pubnub.com/docs/sdks/rest-api/set-channel-metadata).
:::

#### Sample code

```objectivec
PNSetChannelMetadataRequest *request = [PNSetChannelMetadataRequest requestWithChannel:@"channel"];
// Add this request option, if returned metadata model should have value which has been set to
// 'custom' property.
request.includeFields = PNChannelCustomField;
request.custom = @{ @"responsibilities": @"Manage tests", @"status": @"offline" };
request.name = @"Updated channel name";

[self.client setChannelMetadataWithRequest:request completion:^(PNSetChannelMetadataStatus *status) {
    if (!status.isError) {
        /**
         * Channel metadata successfully has been set.
         * Channel metadata information available here: status.data.metadata
         */
    } else {
        /**
         * Handle channel metadata update error. Check 'category' property to find out possible
         * issue because of which request did fail.
         *
         * Request can be resent using: [status retry]
         */
    }
}];
```

#### Response

Response returned by the client for `set channel metadata`:

```objectivec
@interface PNSetChannelMetadataData : PNServiceData

// Associated channel's metadata object.
@property (nonatomic, nullable, readonly, strong) PNChannelMetadata *metadata;

@end

@interface PNSetChannelMetadataStatus : PNAcknowledgmentStatus

// Set channel metadata request processed information.
@property (nonatomic, readonly, strong) PNSetChannelMetadataData *data;

@end
```

#### Other examples

##### Iteratively update existing metadata

```objectivec
#import <Foundation/Foundation.h>
#import <PubNub/PubNub.h>

// Assume 'client' is an initialized PubNub instance as shown in previous examples.
// PubNub *client = [PubNub clientWithConfiguration:config];

NSString *channel = @"demo_example";
NSString *initialName = @"Initial Channel Name";
NSString *initialDescription = @"Initial channel description.";
NSDictionary *initialCustom = @{ @"location": @"default_location" };

// First, set some initial metadata for the channel
PNSetChannelMetadataRequest *initialSetRequest = [PNSetChannelMetadataRequest requestWithChannel:channel];
initialSetRequest.name = initialName;
initialSetRequest.information = initialDescription;
initialSetRequest.custom = initialCustom;
initialSetRequest.includeFields = PNChannelCustomField; // To see custom fields in the response

NSLog(@"Setting initial metadata for channel: %@", channel);
[client setChannelMetadataWithRequest:initialSetRequest completion:^(PNSetChannelMetadataStatus *setStatus) {
    if (!setStatus.isError) {
        NSLog(@"✅ Successfully set initial metadata for channel '%@'.", channel);
        NSLog(@"Initial custom data: %@", setStatus.data.metadata.custom);

        // Now, let's fetch and update this metadata.
        // In a real application, you might get the eTag from this setStatus.data.metadata.eTag
        // or perform a separate fetch operation if needed.

        // For this example, we'll simulate updating a custom field.
        NSString *fieldName = @"location";
        NSString *fieldValue = @"new_york_office";

        // Create a mutable copy of the existing custom data or a new dictionary
        NSMutableDictionary *updatedCustom = [initialCustom mutableCopy] ?: [NSMutableDictionary new];
        updatedCustom[fieldName] = fieldValue;
        
        // Prepare the request to update the channel metadata
        PNSetChannelMetadataRequest *updateRequest = [PNSetChannelMetadataRequest requestWithChannel:channel];
        updateRequest.name = initialName; // Or a new name if you want to change it
        updateRequest.information = initialDescription; // Or a new description
        updateRequest.custom = updatedCustom;
        // Optionally, use eTag for optimistic locking if you have it from a previous get/set operation
        // updateRequest.ifMatchesEtag = @"<eTag_from_previous_operation>";

        NSLog(@"Updating custom field '%@' to '%@' for channel: %@", fieldName, fieldValue, channel);
        [client setChannelMetadataWithRequest:updateRequest completion:^(PNSetChannelMetadataStatus *updateStatus) {
            if (!updateStatus.isError) {
                NSLog(@"✅ Successfully updated metadata for channel '%@'.", channel);
                NSLog(@"Updated custom data: %@", updateStatus.data.metadata.custom);
            } else {
                NSLog(@"❌ Error updating channel metadata: %@. Category: %@", updateStatus.errorData.information, @(updateStatus.category));
                // Request can be resent using: [updateStatus retry]
            }
        }];
    } else {
        NSLog(@"❌ Error setting initial channel metadata: %@. Category: %@", setStatus.errorData.information, @(setStatus.category));
        // Request can be resent using: [setStatus retry]
    }
}];

// Note: The PubNub client operations are asynchronous.
// In a command-line tool or a script, you might need to keep the program running
// until the callbacks are executed, for example, by using a dispatch group or run loop.
// For typical application (e.g. iOS/macOS app) this is handled by the app's main run loop.
```

### Set channel metadata (builder pattern)

#### Method(s)

```objectivec
objects()
    .setChannelMetadata(NSString *)
    .includeFields(PNChannelFields)
    .channel(NSString)
    .name(NSString)
    .information(NSString)
    .custom(NSDictionary)
    .performWithCompletion(PNFetchChannelMetadataCompletionBlock);
```

:::tip API limits
To learn about the maximum length of parameters used to set channel metadata, refer to [REST API docs](https://www.pubnub.com/docs/sdks/rest-api/set-channel-metadata).
:::

| Parameter | Description |
| --- | --- |
| `channel` *Type: NSString | Name of channel with which new `metadata` should be associated. |
| `name`Type: NSString | Name which should stored in `metadata` associated with specified `channel`. |
| `information`Type: NSString | Description which should be stored in `metadata` associated with specified `channel`. |
| `custom`Type: NSDictionary | Additional information which should be stored in `metadata` associated with specified `channel`. [App Context filtering language](https://www.pubnub.com/docs/general/metadata/filtering) doesn't support filtering by custom properties. |
| `includeFields`Type: PNChannelFields | Bitfield of response fields. Supported: `PNChannelCustomField` (custom set during channel metadata set), `PNChannelStatusField` (status set during channel metadata set), `PNChannelTypeField` (type set during channel metadata set). |
| `block`Type: PNSetChannelMetadataCompletionBlock | `Set channel metadata` request completion `block`. |

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

#### Sample code

```objectivec
self.client.objects().setChannelMetadata(@"channel")
    .name(@"Admin")
    .information(@"Administrative channel")
    .custom(@{ @"responsibilities": @"Manage access to protected resources" })
    .includeFields(PNChannelCustomField)
    .performWithCompletion(^(PNSetChannelMetadataStatus *status) {
      if (!status.isError) {
          /**
           * Channel metadata successfully has been set.
           * Channel metadata information available here: status.data.metadata
           */
      } else {
          /**
           * Handle channel metadata update error. Check 'category' property to find out possible
           * issue because of which request did fail.
           *
           * Request can be resent using: [status retry]
           */
      }
    });
```

#### Response

Response returned by the client for `set channel metadata`:

```objectivec
@interface PNSetChannelMetadataData : PNServiceData

// Associated channel's metadata object.
@property (nonatomic, nullable, readonly, strong) PNChannelMetadata *metadata;

@end

@interface PNSetChannelMetadataStatus : PNAcknowledgmentStatus

// Set channel metadata request processed information.
@property (nonatomic, readonly, strong) PNSetChannelMetadataData *data;

@end
```

### Remove channel metadata

Removes the metadata from a specified channel.

#### Method(s)

To `Remove Channel Metadata` you can use the following method(s) in the Objective-C SDK:

```objectivec
- (void)removeChannelMetadataWithRequest:(PNRemoveChannelMetadataRequest *)request 
                              completion:(nullable PNRemoveChannelMetadataCompletionBlock)block;
```

| Parameter | Description |
| --- | --- |
| `request` *Type: [PNRemoveChannelMetadataRequest](#pnremovechannelmetadatarequest) | Request object for removing channel metadata. |
| `block`Type: PNRemoveChannelMetadataCompletionBlock | `Remove channel metadata` request completion `block`. |

#### PNRemoveChannelMetadataRequest

| Parameter | Description |
| --- | --- |
| `channel`Type: NSString | Create and configure remove channel metadata request. `channel` - Name of channel for which metadata should be removed. |

#### Sample code

```objectivec
PNRemoveChannelMetadataRequest *request = [PNRemoveChannelMetadataRequest requestWithChannel:@"channel"];

[self.client removeChannelMetadataWithRequest:request completion:^(PNAcknowledgmentStatus *status) {
    if (!status.isError) {
        // Channel metadata successfully removed.
    } else {
        /**
         * Handle channel metadata remove error. Check 'category' property to find out possible
         * issue because of which request did fail.
         *
         * Request can be resent using: [status retry]
         */
    }
}];
```

#### Response

Response returned by the client for `remove channel metadata`:

```objectivec
@interface PNErrorData : PNServiceData

// Stringified error information.
@property (nonatomic, readonly, strong) NSString *information;

@end

@interface PNAcknowledgmentStatus : PNErrorStatus

// Whether status object represent error or not.
@property (nonatomic, readonly, assign, getter = isError) BOOL error;

// Additional information related to error status object.
@property (nonatomic, readonly, strong) PNErrorData *errorData;

@end
```

### Remove channel metadata (builder pattern)

#### Method(s)

```objectivec
objects()
    .removeChannelMetadata(NSString *)
    .performWithCompletion(nullable PNRemoveChannelMetadataCompletionBlock);
```

| Parameter | Description |
| --- | --- |
| `channel` *Type: NSString | Name of channel for which associated `metadata` should be removed. |
| `block`Type: PNRemoveChannelMetadataCompletionBlock | `Remove channel metadata` request completion `block`. |

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

#### Sample code

```objectivec
self.client.objects().removeChannelMetadata(@"channel")
    .performWithCompletion(^(PNAcknowledgmentStatus *status) {
        if (!status.isError) {
            // Channel metadata successfully removed.
        } else {
            /**
             * Handle channel metadata remove error. Check 'category' property to find out possible
             * issue because of which request did fail.
             *
             * Request can be resent using: [status retry]
             */
        }
    });
```

#### Response

Response returned by the client for `remove channel metadata`:

```objectivec
@interface PNErrorData : PNServiceData

// Stringified error information.
@property (nonatomic, readonly, strong) NSString *information;

@end

@interface PNAcknowledgmentStatus : PNErrorStatus

// Whether status object represent error or not.
@property (nonatomic, readonly, assign, getter = isError) BOOL error;

// Additional information related to error status object.
@property (nonatomic, readonly, strong) PNErrorData *errorData;

@end
```

## Channel memberships

### Get channel memberships

The method returns a list of channel memberships for a user. This method doesn't return a user's subscriptions.

#### Method(s)

To `Get Memberships` you can use the following method(s) in the Objective-C SDK:

```objectivec
- (void)membershipsWithRequest:(PNFetchMembershipsRequest *)request 
                    completion:(PNFetchMembershipsCompletionBlock)block;
```

| Parameter | Description |
| --- | --- |
| `request` *Type: [PNFetchMembershipsRequest](#pnfetchmembershipsrequest) | Request object for fetching UUID memberships. |
| `block` *Type: PNFetchMembershipsCompletionBlock | Completion block. |

#### PNFetchMembershipsRequest

| Parameter | Description |
| --- | --- |
| `sort`Type: NSArray`<NSString *>` | Sort by id, name, updated with asc/desc for sort direction (for example, `{name: 'asc'}`). |
| `includeFields`Type: PNMembershipFields | Bitfield of response fields. Supported: `PNMembershipsTotalCountField` (number of memberships), `PNMembershipCustomField` (custom set during membership set), `PNMembershipStatusField` (status set during membership set), `PNMembershipTypeField` (type set during membership set), `PNMembershipChannelField` (include channel metadata), `PNMembershipChannelCustomField` (channel custom set during channel metadata set), `PNMembershipChannelStatusField` (channel status set during channel metadata set), `PNMembershipChannelTypeField` (channel type set during channel metadata set). Default is `PNMembershipsTotalCountField` (set 0 to reset). |
| `filter`Type: NSString | Filter expression. Only matching objects are returned. See [filtering](https://www.pubnub.com/docs/general/metadata/filtering). |
| `start`Type: NSString | Cursor-based pagination. |
| `end`Type: NSString | Cursor-based pagination. Ignored if the `start` parameter is supplied. |
| `limit`Type: NSUInteger | Number of objects to return. Default/Max: 100. |

#### Sample code

```objectivec
PNFetchMembershipsRequest *request = [PNFetchMembershipsRequest requestWithUUID:@"uuid"];
request.start = @"<next from previous request>";
// Add this request option, if returned membership models should have value which has been set to
// 'custom' and 'channel' properties.
request.includeFields = PNMembershipCustomField | PNMembershipChannelField | PNMembershipsTotalCountField;
request.limit = 40;

[self.client membershipsWithRequest:request
                         completion:^(PNFetchMembershipsResult *result, PNErrorStatus *status) {

    if (!status.isError) {
        /**
         * UUID's memberships successfully fetched.
         * Result object has following information:
         *   result.data.memberships - List of UUID's memberships.
         *   result.data.next - Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off.
         *   result.data.prev - Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data.
         *   result.data.totalCount - Total number of UUID's memberships.
         */
    } else {
        /**
         * Handle UUID's memberships fetch error. Check 'category' property to find out possible
         * issue because of which request did fail.
         *
         * Request can be resent using: [status retry]
         */
    }
}];
```

#### Response

Response returned by the client for `fetch memberships`:

```objectivec
@interface PNFetchMembershipsData : PNServiceData

// List of fetched memberships.
@property (nonatomic, readonly, strong) NSArray<PNMembership *> *memberships;

// Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off.
@property (nonatomic, nullable, readonly, strong) NSString *next;

// Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data.
@property (nonatomic, nullable, readonly, strong) NSString *prev;

/**
 * Total number of members created for current subscribe key.
 *
 * Value will be 0 in case if PNMembershipsTotalCountField not added to 'includeFields'
 * of PNSetMembershipsRequest / PNRemoveMembershipsRequest / PNManageMembershipsRequest or
 * PNFetchMembershipsRequest.
 */
@property (nonatomic, readonly, assign) NSUInteger totalCount;

@end

@interface PNFetchMembershipsResult : PNAcknowledgmentStatus

// Fetch memberships request processed information.
@property (nonatomic, readonly, strong) PNFetchMembershipsData *data;

@end
```

Error response which is used in case of App Context API call failure:

```objectivec
@interface PNErrorData : PNServiceData

// Stringified error information.
@property (nonatomic, readonly, strong) NSString *information;

@end

@interface PNErrorStatus : PNStatus

// Whether status object represent error or not.
@property (nonatomic, readonly, assign, getter = isError) BOOL error;

// Additional information related to error status object.
@property (nonatomic, readonly, strong) PNErrorData *errorData;

@end
```

### Get channel memberships (builder pattern)

#### Method(s)

```objectivec
objects()
    .memberships()
    .uuid(NSString *)
    .includeFields(PNMembershipFields)
    .includeCount(BOOL)
    .filter(NSString *)
    .sort(NSArray<NSString *> *)
    .limit(NSUInteger)
    .start(NSString *)
    .end(NSString *)
    .performWithCompletion(PNFetchMembershipsCompletionBlock);
```

| Parameter | Description |
| --- | --- |
| `uuid`Type: NSString | Name of channel from which members should be fetched. |
| `includeFields`Type: PNMembershipFields | Bitfield of response fields. Supported: `PNMembershipsTotalCountField` (number of memberships), `PNMembershipCustomField` (custom set during membership set), `PNMembershipStatusField` (status set during membership set), `PNMembershipTypeField` (type set during membership set), `PNMembershipChannelField` (include channel metadata), `PNMembershipChannelCustomField` (channel custom set during channel metadata set), `PNMembershipChannelStatusField` (channel status set during channel metadata set), `PNMembershipChannelTypeField` (channel type set during channel metadata set). Default is `PNMembershipsTotalCountField` (set 0 to reset). |
| `includeCount`Type: BOOL | Whether to include the total count in the paginated response. Default: `YES` |
| `filter`Type: NSString | Filter expression. Only matching objects are returned. See [filtering](https://www.pubnub.com/docs/general/metadata/filtering). |
| `sort`Type: NSArray | List of criteria (name of field) which should be used for sorting in ascending order. Available options are `id`, `name`, and `updated`. Use `asc` or `desc` to specify sort direction. For example: `{name: 'asc'}` |
| `limit`Type: NSUInteger | Number of objects to return. Default/Max: 100. |
| `start`Type: NSString | Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off. |
| `end`Type: NSString | Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data. Ignored if the `start` parameter is supplied. |
| `block` *Type: PNFetchMembershipsCompletionBlock | `Fetch UUID's memberships` request completion `block`. |

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

#### Sample code

```objectivec
self.client.objects().memberships()
    .uuid(@"uuid")
    .includeCount(YES)
    .limit(40)
    .includeFields(PNMembershipCustomField | PNMembershipChannelField)
    .performWithCompletion(^(PNFetchMembershipsResult *result, PNErrorStatus *status) {
        if (!status.isError) {
            /**
             * UUID's memberships successfully fetched.
             * Result object has following information:
             *   result.data.memberships - List of UUID's memberships.
             *   result.data.next - Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off.
             *   result.data.prev - Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data.
             *   result.data.totalCount - Total number of UUID's memberships.
             */
        } else {
            /**
             * Handle UUID's memberships fetch error. Check 'category' property to find out possible
             * issue because of which request did fail.
             *
             * Request can be resent using: [status retry]
             */
        }
    });
```

#### Response

Response returned by the client for `fetch memberships`:

```objectivec
@interface PNFetchMembershipsData : PNServiceData

// List of fetched memberships.
@property (nonatomic, readonly, strong) NSArray<PNMembership *> *memberships;

// Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off.
@property (nonatomic, nullable, readonly, strong) NSString *next;

// Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data.
@property (nonatomic, nullable, readonly, strong) NSString *prev;

/**
 * Total number of members created for current subscribe key.
 *
 * Value will be 0 in case if PNMembershipsTotalCountField not added to 'includeFields'
 * of PNSetMembershipsRequest / PNRemoveMembershipsRequest / PNManageMembershipsRequest or
 * PNFetchMembershipsRequest.
 */
@property (nonatomic, readonly, assign) NSUInteger totalCount;

@end

@interface PNFetchMembershipsResult : PNAcknowledgmentStatus

// Fetch memberships request processed information.
@property (nonatomic, readonly, strong) PNFetchMembershipsData *data;

@end
```

Error response which is used in case of App Context API call failure:

```objectivec
@interface PNErrorData : PNServiceData

// Stringified error information.
@property (nonatomic, readonly, strong) NSString *information;

@end

@interface PNErrorStatus : PNStatus

// Whether status object represent error or not.
@property (nonatomic, readonly, assign, getter = isError) BOOL error;

// Additional information related to error status object.
@property (nonatomic, readonly, strong) PNErrorData *errorData;

@end
```

### Set channel memberships

Set channel memberships for a UUID.

#### Method(s)

To `Set Memberships` you can use the following method(s) in the Objective-C SDK:

```objectivec
- (void)setMembershipsWithRequest:(PNSetMembershipsRequest *)request 
                       completion:(nullable PNManageMembershipsCompletionBlock)block;
```

| Parameter | Description |
| --- | --- |
| `request` *Type: [PNSetMembershipsRequest](#pnsetmembershipsrequest) | Request object for setting UUID memberships. |
| `block`Type: PNManageMembershipsCompletionBlock | `Set UUID's memberships` request completion `block`. |

#### PNSetMembershipsRequest

| Parameter | Description |
| --- | --- |
| `sort`Type: NSArray`<NSString *>` | List of criteria (name of field) which should be used for sorting in ascending order. Available options are `id`, `name`, and `updated`. Use `asc` or `desc` to specify sort direction. For example: `{name: 'asc'}` |
| `includeFields`Type: PNMembershipFields | Bitfield set to fields which should be returned with response. **Supported fields:** PNMembershipsTotalCountField - include how many memberships UUID has., PNMembershipCustomField - include field with additional information from metadata which has been associated with UUID during membership set requests., PNMembershipStatusField - include field with metadata status which has been associated with UUID during membership set requests., PNMembershipTypeField - include field with metadata type which has been associated with UUID during membership set requests., PNMembershipChannelField - include channel's metadata into response (not only name)., PNMembershipChannelCustomField - include channel's additional information which has been used during channel metadata set requests., PNMembershipChannelStatusField - include channel's status which has been used during channel metadata set requests., PNMembershipChannelTypeField - include channel's type which has been used during channel metadata set requests. |
| `filter`Type: NSString | Filter expression. Only matching objects are returned. See [filtering](https://www.pubnub.com/docs/general/metadata/filtering). |
| `start`Type: NSString | Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off. |
| `end`Type: NSString | Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data. Ignored if the `start` parameter is supplied. |
| `limit`Type: NSUInteger | Number of objects to return. Default/Max: 100. |

:::tip API limits
To learn about the maximum length of parameters used to set channel membership metadata, refer to [REST API docs](https://www.pubnub.com/docs/sdks/rest-api/set-membership-metadata).
:::

#### Sample code

```objectivec
NSArray<NSDictionary *> *channels = @[
  @{ 
    @"channel": @"channel1", 
    @"status": @"active",
    @"type": @"public", 
    @"custom": @{ @"role": @"moderator" } 
  }
];

PNSetMembershipsRequest *request = [PNSetMembershipsRequest requestWithUUID:@"uuid"
                                                                   channels:channels];
// Add this request option, if returned membership models should have value which has been set to
// 'custom' and 'channel' properties.
request.includeFields = PNMembershipCustomField | PNMembershipChannelField | PNMembershipsTotalCountField;
request.limit = 40;

[self.client setMembershipsWithRequest:request completion:^(PNManageMembershipsStatus *status) {
    if (!status.isError) {
        /**
         * UUID's memberships successfully set.
         * Result object has following information:
         *   status.data.memberships - List of UUID's existing memberships.
         *   status.data.next - Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off.
         *   status.data.prev - Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data.
         *   status.data.totalCount - Total number of UUID's memberships.
         */
    } else {
        /**
         * Handle UUID's memberships set error. Check 'category' property to find out possible
         * issue because of which request did fail.
         *
         * Request can be resent using: [status retry]
         */
    }
}];
```

#### Response

Response returned by the client for `set memberships`:

```objectivec
@interface PNManageMembershipsData : PNServiceData

// List of existing memberships.
@property (nonatomic, readonly, strong) NSArray<PNMembership *> *memberships;

// Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off.
@property (nonatomic, nullable, readonly, strong) NSString *next;

// Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data.
@property (nonatomic, nullable, readonly, strong) NSString *prev;

/**
 * Total number of existing objects.
 *
 * Value will be 0 in case if PNMembershipsTotalCountField not added to 'includeFields'
 * of PNSetMembershipsRequest / PNRemoveMembershipsRequest / PNManageMembershipsRequest or
 * PNFetchMembershipsRequest.
 */
@property (nonatomic, readonly, assign) NSUInteger totalCount;

@end

@interface PNManageMembershipsStatus : PNAcknowledgmentStatus

// Memberships set / remove / manage request processed information.
@property (nonatomic, readonly, strong) PNManageMembershipsData *data;

@end
```

### Set channel memberships (builder pattern)

#### Method(s)

```objectivec
objects()
    .setMemberships()
    .uuid(NSString *)
    .channels(NSArray<NSDictionary *> *)
    .includeFields(PNMembershipFields)
    .includeCount(BOOL)
    .filter(NSString *)
    .sort(NSArray<NSString *> *)
    .limit(NSUInteger)
    .start(NSString *)
    .end(NSString *)
    .performWithCompletion(nullable PNManageMembershipsCompletionBlock);
```

:::tip API limits
To learn about the maximum length of parameters used to set channel membership metadata, refer to [REST API docs](https://www.pubnub.com/docs/sdks/rest-api/set-membership-metadata).
:::

| Parameter | Description |
| --- | --- |
| `uuid`Type: NSString | Identifier for which memberships should be set. Default: configured PubNub client `uuid` |
| `channels`Type: NSArray | List of `channels` for which `metadata` associated with each of them in context of `UUID` should be set. Each entry is dictionary with `channel` and `optional` `custom` fields. `custom` should be dictionary with simple objects: `NSString` and `NSNumber`. |
| `includeFields`Type: PNMembershipFields | Bitfield set to fields which should be returned with response. **Supported fields:** PNMembershipsTotalCountField - include how many memberships UUID has., PNMembershipCustomField - include field with additional information from metadata which has been associated with UUID during membership set requests., PNMembershipStatusField - include field with metadata status which has been associated with UUID during membership set requests., PNMembershipTypeField - include field with metadata type which has been associated with UUID during membership set requests., PNMembershipChannelField - include channel's metadata into response (not only name)., PNMembershipChannelCustomField - include channel's additional information which has been used during channel metadata set requests., PNMembershipChannelStatusField - include channel's status which has been used during channel metadata set requests., PNMembershipChannelTypeField - include channel's type which has been used during channel metadata set requests. |
| `includeCount`Type: BOOL | Whether to include the total count in the paginated response. Default: `YES` |
| `filter`Type: NSString | Filter expression. Only matching objects are returned. See [filtering](https://www.pubnub.com/docs/general/metadata/filtering). |
| `sort`Type: NSArray | List of criteria (name of field) which should be used for sorting in ascending order. Available options are `id`, `name`, and `updated`. Use `asc` or `desc` to specify sort direction. For example: `{name: 'asc'}` |
| `limit`Type: NSUInteger | Number of objects to return. Default/Max: 100. |
| `start`Type: NSString | Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off. |
| `end`Type: NSString | Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data. Ignored if the `start` parameter is supplied. |
| `block`Type: PNManageMembershipsCompletionBlock | `Set UUID's memberships` request completion `block`. |

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

#### Sample code

```objectivec
NSArray<NSDictionary *> *channels = @[
  @{ 
    @"channel": @"channel1", 
    @"status": @"active",
    @"type": @"public", 
    @"custom": @{ @"role": @"moderator" } 
  }
];

self.client.objects().setMemberships()
    .uuid(@"uuid")
    .channels(channels)
    .includeCount(YES)
    .limit(40)
    .includeFields(NMembershipCustomField | PNMembershipChannelField)
    .performWithCompletion(^(PNManageMembershipsStatus *status) {
        if (!status.isError) {
            /**
             * UUID's memberships successfully set.
             * Result object has following information:
             *   status.data.memberships - List of UUID's existing memberships.
             *   status.data.next - Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off.
             *   status.data.prev - Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data.
             *   status.data.totalCount - Total number of UUID's memberships.
             */
        } else {
            /**
             * Handle UUID's memberships set error. Check 'category' property to find out possible
             * issue because of which request did fail.
             *
             * Request can be resent using: [status retry]
             */
        }
    });
```

#### Response

Response returned by the client for `set memberships`:

```objectivec
@interface PNManageMembershipsData : PNServiceData

// List of existing memberships.
@property (nonatomic, readonly, strong) NSArray<PNMembership *> *memberships;

// Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off.
@property (nonatomic, nullable, readonly, strong) NSString *next;

// Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data.
@property (nonatomic, nullable, readonly, strong) NSString *prev;

/**
 * Total number of existing objects.
 *
 * Value will be 0 in case if PNMembershipsTotalCountField not added to 'includeFields'
 * of PNSetMembershipsRequest / PNRemoveMembershipsRequest / PNManageMembershipsRequest or
 * PNFetchMembershipsRequest.
 */
@property (nonatomic, readonly, assign) NSUInteger totalCount;

@end

@interface PNManageMembershipsStatus : PNAcknowledgmentStatus

// Memberships set / remove / manage request processed information.
@property (nonatomic, readonly, strong) PNManageMembershipsData *data;

@end
```

### Remove channel memberships

Remove channel memberships for a UUID.

#### Method(s)

To `Remove Memberships` you can use the following method(s) in the Objective-C SDK:

```objectivec
- (void)removeMembershipsWithRequest:(PNRemoveMembershipsRequest *)request 
                          completion:(nullable PNManageMembershipsCompletionBlock)block;
```

| Parameter | Description |
| --- | --- |
| `request` *Type: [PNRemoveMembershipsRequest](#pnremovemembershipsrequest) | Request object for removing UUID memberships. |
| `block`Type: PNManageMembershipsCompletionBlock | `Remove UUID's memberships` request completion block. |

#### PNRemoveMembershipsRequest

| Parameter | Description |
| --- | --- |
| `sort`Type: NSArray`<NSString *>` | List of criteria (name of field) which should be used for sorting in ascending order. Available options are `id`, `name`, and `updated`. Use `asc` or `desc` to specify sort direction. For example: `{name: 'asc'}` |
| `includeFields`Type: PNMembershipFields | Bitfield set to fields which should be returned with response. **Supported fields:** PNMembershipsTotalCountField - include how many memberships UUID has., PNMembershipCustomField - include field with additional information from metadata which has been associated with UUID during membership set requests., PNMembershipStatusField - include field with metadata status which has been associated with UUID during membership set requests., PNMembershipTypeField - include field with metadata type which has been associated with UUID during membership set requests., PNMembershipChannelField - include channel's metadata into response (not only name)., PNMembershipChannelCustomField - include channel's additional information which has been used during channel metadata set requests., PNMembershipChannelStatusField - include channel's status which has been used during channel metadata set requests., PNMembershipChannelTypeField - include channel's type which has been used during channel metadata set requests. |
| `filter`Type: NSString | Filter expression. Only matching objects are returned. See [filtering](https://www.pubnub.com/docs/general/metadata/filtering). |
| `start`Type: NSString | Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off. |
| `end`Type: NSString | Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data. Ignored if the `start` parameter is supplied. |
| `limit`Type: NSUInteger | Number of objects to return. Default/Max: 100. |

#### Sample code

```objectivec
NSArray<NSString *> *channels = @[@"channel1", @"channel2"];
PNRemoveMembershipsRequest *request = [PNRemoveMembershipsRequest requestWithUUID:@"uuid"
                                                                         channels:channels];
// Add this request option, if returned membership models should have value which has been set to
// 'custom' and 'channel' properties.
request.includeFields = PNMembershipCustomField | PNMembershipChannelField | PNMembershipsTotalCountField;
request.limit = 40;

[self.client removeMembershipsWithRequest:request
                               completion:^(PNManageMembershipsStatus *status) {

    if (!status.isError) {
        /**
         * UUID's memberships successfully removed.
         * Result object has following information:
         *   status.data.memberships - List of UUID's existing memberships.
         *   status.data.next - Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off.
         *   status.data.prev - Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data.
         *   status.data.totalCount - Total number of UUID's memberships.
         */
    } else {
        /**
         * Handle UUID's memberships remove error. Check 'category' property to find out possible
         * issue because of which request did fail.
         *
         * Request can be resent using: [status retry]
         */
    }
}];
```

#### Response

Response returned by the client for `remove memberships`:

```objectivec
@interface PNManageMembershipsData : PNServiceData

// List of existing memberships.
@property (nonatomic, readonly, strong) NSArray<PNMembership *> *memberships;

// Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off.
@property (nonatomic, nullable, readonly, strong) NSString *next;

// Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data.
@property (nonatomic, nullable, readonly, strong) NSString *prev;

/**
 * Total number of existing objects.
 *
 * Value will be 0 in case if PNMembershipsTotalCountField not added to 'includeFields'
 * of PNSetMembershipsRequest / PNRemoveMembershipsRequest / PNManageMembershipsRequest or
 * PNFetchMembershipsRequest.
 */
@property (nonatomic, readonly, assign) NSUInteger totalCount;

@end

@interface PNManageMembershipsStatus : PNAcknowledgmentStatus

// Memberships set / remove / manage request processed information.
@property (nonatomic, readonly, strong) PNManageMembershipsData *data;

@end
```

### Remove channel memberships (builder pattern)

#### Method(s)

```objectivec
objects()
    .removeMemberships()
    .uuid(NSString *)
    .channels(NSArray<NSString *> *)
    .includeFields(PNMemberFields)
    .includeCount(BOOL)
    .filter(NSString *)
    .sort(NSArray<NSString *> *)
    .limit(NSUInteger)
    .start(NSString *)
    .end(NSString *)
    .performWithCompletion(nullable PNManageMembershipsCompletionBlock);
```

| Parameter | Description |
| --- | --- |
| `uuid`Type: NSString | Identifier for which memberships should be removed. Default: configured PubNub client `uuid` |
| `channels`Type: NSArray | List of `channels` from which `UUID` should be removed as `member`. |
| `includeFields`Type: PNMembershipFields | Bitfield set to fields which should be returned with response. **Supported fields:** PNMembershipsTotalCountField - include how many memberships UUID has., PNMembershipCustomField - include field with additional information from metadata which has been associated with UUID during membership set requests., PNMembershipStatusField - include field with metadata status which has been associated with UUID during membership set requests., PNMembershipTypeField - include field with metadata type which has been associated with UUID during membership set requests., PNMembershipChannelField - include channel's metadata into response (not only name)., PNMembershipChannelCustomField - include channel's additional information which has been used during channel metadata set requests., PNMembershipChannelStatusField - include channel's status which has been used during channel metadata set requests., PNMembershipChannelTypeField - include channel's type which has been used during channel metadata set requests. |
| `includeCount`Type: BOOL | Whether to include the total count in the paginated response. Default: `YES` |
| `filter`Type: NSString | Filter expression. Only matching objects are returned. See [filtering](https://www.pubnub.com/docs/general/metadata/filtering). |
| `sort`Type: NSArray | List of criteria (name of field) which should be used for sorting in ascending order. Available options are `id`, `name`, and `updated`. Use `asc` or `desc` to specify sort direction. For example: `{name: 'asc'}` |
| `limit`Type: NSUInteger | Number of objects to return. Default/Max: 100. |
| `start`Type: NSString | Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off. |
| `end`Type: NSString | Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data. Ignored if the `start` parameter is supplied. |
| `block`Type: PNManageMembershipsCompletionBlock | `Remove UUID's memberships` request completion block. |

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

#### Sample code

```objectivec
self.client.objects().removeMemberships()
    .uuid(@"uuid")
    .channels(@[@"channel1", @"channel2"])
    .includeCount(YES)
    .limit(40)
    .includeFields(PNMembershipCustomField | PNMembershipChannelField)
    .performWithCompletion(^(PNManageMembershipsStatus *status) {
        if (!status.isError) {
            /**
             * UUID's memberships successfully removed.
             * Result object has following information:
             *   status.data.memberships - List of UUID's existing memberships.
             *   status.data.next - Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off.
             *   status.data.prev - Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data.
             *   status.data.totalCount - Total number of UUID's memberships.
             */
        } else {
            /**
             * Handle UUID's memberships remove error. Check 'category' property to find out possible
             * issue because of which request did fail.
             *
             * Request can be resent using: [status retry]
             */
        }
    });
```

#### Response

Response returned by the client for `remove memberships`:

```objectivec
@interface PNManageMembershipsData : PNServiceData

// List of existing memberships.
@property (nonatomic, readonly, strong) NSArray<PNMembership *> *memberships;

// Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off.
@property (nonatomic, nullable, readonly, strong) NSString *next;

// Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data.
@property (nonatomic, nullable, readonly, strong) NSString *prev;

/**
 * Total number of existing objects.
 *
 * Value will be 0 in case if PNMembershipsTotalCountField not added to 'includeFields'
 * of PNSetMembershipsRequest / PNRemoveMembershipsRequest / PNManageMembershipsRequest or
 * PNFetchMembershipsRequest.
 */
@property (nonatomic, readonly, assign) NSUInteger totalCount;

@end

@interface PNManageMembershipsStatus : PNAcknowledgmentStatus

// Memberships set / remove / manage request processed information.
@property (nonatomic, readonly, strong) PNManageMembershipsData *data;

@end
```

### Manage channel memberships

The method Set and Remove channel memberships for a user.

#### Method(s)

To `Manage Memberships` you can use the following method(s) in the Objective-C SDK:

```objectivec
- (void)manageMembershipsWithRequest:(PNManageMembershipsRequest *)request 
                          completion:(nullable PNManageMembershipsCompletionBlock)block;
```

| Parameter | Description |
| --- | --- |
| `request` *Type: [PNManageMembershipsRequest](#pnmanagemembershipsrequest) | Request object for managing UUID memberships. |
| `block`Type: PNManageMembershipsCompletionBlock | `Manage UUID's memberships` request completion `block`. |

#### PNManageMembershipsRequest

| Parameter | Description |
| --- | --- |
| `setChannels`Type: NSArray`<NSDictionary *>` | List of channels within which UUID should be set as member. Each entry is dictionary with channel and optional `custom` fields. `custom` should be dictionary with simple objects: NSString and NSNumber. |
| `removeChannels`Type: NSArray`<NSString *>` | List of channels from which UUID should be removed as member. |
| `sort`Type: NSArray`<NSString *>` | List of criteria (name of field) which should be used for sorting in ascending order. Available options are `id`, `name`, and `updated`. Use `asc` or `desc` to specify sort direction. For example: `{name: 'asc'}` |
| `includeFields`Type: PNMembershipFields | Bitfield set to fields which should be returned with response. **Supported fields:** PNMembershipsTotalCountField - include how many memberships UUID has., PNMembershipCustomField - include field with additional information from metadata which has been associated with UUID during membership set requests., PNMembershipStatusField - include field with metadata status which has been associated with UUID during membership set requests., PNMembershipTypeField - include field with metadata type which has been associated with UUID during membership set requests., PNMembershipChannelField - include channel's metadata into response (not only name)., PNMembershipChannelCustomField - include channel's additional information which has been used during channel metadata set requests., PNMembershipChannelStatusField - include channel's status which has been used during channel metadata set requests., PNMembershipChannelTypeField - include channel's type which has been used during channel metadata set requests. |
| `filter`Type: NSString | Filter expression. Only matching objects are returned. See [filtering](https://www.pubnub.com/docs/general/metadata/filtering). |
| `start`Type: NSString | Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off. |
| `end`Type: NSString | Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data. Ignored if the `start` parameter is supplied. |
| `limit`Type: NSUInteger | Number of objects to return. Default/Max: 100. |

#### Sample code

```objectivec
PNManageMembershipsRequest *request = [PNManageMembershipsRequest requestWithUUID:@"uuid"];
request.setChannels = @[
    @{ @"channel": @"channel1", @"custom": @{ @"role": @"moderator" } }
];
request.removeChannels = @[@"channel3", @"channel4"];
// Add this request option, if returned membership models should have value which has been set to
// 'custom' and 'channel' properties.
request.includeFields = PNMembershipCustomField | PNMembershipChannelField | PNMembershipsTotalCountField;
request.limit = 40;

[self.client manageMembershipsWithRequest:request
                               completion:^(PNManageMembershipsStatus *status) {

    if (!status.isError) {
        /**
         * UUID's memberships successfully set.
         * Result object has following information:
         *   status.data.memberships - List of UUID's existing memberships.
         *   status.data.next - Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off.
         *   status.data.prev - Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data.
         *   status.data.totalCount - Total number of UUID's memberships.
         */
    } else {
        /**
         * Handle UUID's memberships set error. Check 'category' property to find out possible
         * issue because of which request did fail.
         *
         * Request can be resent using: [status retry]
         */
    }
}];
```

#### Response

Response returned by the client for `manage memberships`:

```objectivec
@interface PNManageMembershipsData : PNServiceData

// List of existing memberships.
@property (nonatomic, readonly, strong) NSArray<PNMembership *> *memberships;

// Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off.
@property (nonatomic, nullable, readonly, strong) NSString *next;

// Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data.
@property (nonatomic, nullable, readonly, strong) NSString *prev;

/**
 * Total number of existing objects.
 *
 * Value will be 0 in case if PNMembershipsTotalCountField not added to 'includeFields'
 * of PNSetMembershipsRequest / PNRemoveMembershipsRequest / PNManageMembershipsRequest or
 * PNFetchMembershipsRequest.
 */
@property (nonatomic, readonly, assign) NSUInteger totalCount;

@end

@interface PNManageMembershipsStatus : PNAcknowledgmentStatus

// Memberships set / remove / manage request processed information.
@property (nonatomic, readonly, strong) PNManageMembershipsData *data;

@end
```

### Manage channel memberships (builder pattern)

#### Method(s)

```objectivec
objects()
    .manageMemberships()
    .uuid(NSString *)
    .set(NSArray<NSDictionary *> *)
    .remove(NSArray<NSString *> *)
    .includeFields(PNMemberFields)
    .includeCount(BOOL)
    .filter(NSString *)
    .sort(NSArray<NSString *> *)
    .limit(NSUInteger)
    .start(NSString *)
    .end(NSString *)
    .performWithCompletion(nullable PNManageMembershipsCompletionBlock);
```

| Parameter | Description |
| --- | --- |
| `uuid`Type: NSString | Identifier for which memberships should be set. Default: configured PubNub client `uuid` |
| `set`Type: NSArray | List of `channels` for which `metadata` associated with each of them in context of `UUID` should be set. Each entry is dictionary with `channel` and `optional` `custom` fields. `custom` should be dictionary with simple objects: `NSString` and `NSNumber`. |
| `remove`Type: NSArray | List of `channels` from which `UUID` should be removed as `member`. |
| `includeFields`Type: PNMembershipFields | Bitfield set to fields which should be returned with response. **Supported fields:** PNMembershipsTotalCountField - include how many memberships UUID has., PNMembershipCustomField - include field with additional information from metadata which has been associated with UUID during membership set requests., PNMembershipStatusField - include field with metadata status which has been associated with UUID during membership set requests., PNMembershipTypeField - include field with metadata type which has been associated with UUID during membership set requests., PNMembershipChannelField - include channel's metadata into response (not only name)., PNMembershipChannelCustomField - include channel's additional information which has been used during channel metadata set requests., PNMembershipChannelStatusField - include channel's status which has been used during channel metadata set requests., PNMembershipChannelTypeField - include channel's type which has been used during channel metadata set requests. |
| `includeCount`Type: BOOL | Whether to include the total count in the paginated response. Default: `YES` |
| `filter`Type: NSString | Filter expression. Only matching objects are returned. See [filtering](https://www.pubnub.com/docs/general/metadata/filtering). |
| `sort`Type: NSArray | List of criteria (name of field) which should be used for sorting in ascending order. Available options are `id`, `name`, and `updated`. Use `asc` or `desc` to specify sort direction. For example: `{name: 'asc'}` |
| `limit`Type: NSUInteger | Number of objects to return. Default/Max: 100. |
| `start`Type: NSString | Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off. |
| `end`Type: NSString | Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data. Ignored if the `start` parameter is supplied. |
| `block`Type: PNManageMembershipsCompletionBlock | `Manage UUID's memberships` request completion `block`. |

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

#### Sample code

```objectivec
NSArray<NSDictionary *> *setChannels = @[
    @{ @"channel": @"channel1", @"custom": @{ @"role": @"moderator" } }
];
NSArray<NSString *> *removeChannels = @[@"channel3", @"channel4"];

self.client.objects().manageMemberships()
    .uuid(@"uuid")
    .set(setChannels)
    .remove(removeChannels)
    .includeCount(YES)
    .limit(40)
    .includeFields(PNMembershipCustomField | PNMembershipChannelField)
    .performWithCompletion(^(PNManageMembershipsStatus *status) {
        if (!status.isError) {
            /**
             * UUID's memberships successfully set.
             * Result object has following information:
             *   status.data.memberships - List of UUID's existing memberships.
             *   status.data.next - Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off.
             *   status.data.prev - Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data.
             *   status.data.totalCount - Total number of UUID's memberships.
             */
        } else {
            /**
             * Handle UUID's memberships set error. Check 'category' property to find out possible
             * issue because of which request did fail.
             *
             * Request can be resent using: [status retry]
             */
        }
    });
```

#### Response

Response returned by the client for `manage memberships`:

```objectivec
@interface PNManageMembershipsData : PNServiceData

// List of existing memberships.
@property (nonatomic, readonly, strong) NSArray<PNMembership *> *memberships;

// Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off.
@property (nonatomic, nullable, readonly, strong) NSString *next;

// Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data.
@property (nonatomic, nullable, readonly, strong) NSString *prev;

/**
 * Total number of existing objects.
 *
 * Value will be 0 in case if PNMembershipsTotalCountField not added to 'includeFields'
 * of PNSetMembershipsRequest / PNRemoveMembershipsRequest / PNManageMembershipsRequest or
 * PNFetchMembershipsRequest.
 */
@property (nonatomic, readonly, assign) NSUInteger totalCount;

@end

@interface PNManageMembershipsStatus : PNAcknowledgmentStatus

// Memberships set / remove / manage request processed information.
@property (nonatomic, readonly, strong) PNManageMembershipsData *data;

@end
```

## Channel members

### Get channel members

The method returns a list of members in a channel. The list will include user metadata for members that have additional metadata stored in the database.

#### Method(s)

To `Get Channel Members` you can use the following method(s) in the Objective-C SDK:

```objectivec
- (void)channelMembersWithRequest:(PNFetchChannelMembersRequest *)request 
                       completion:(PNFetchChannelMembersCompletionBlock)block;
```

| Parameter | Description |
| --- | --- |
| `request` *Type: [PNFetchChannelMembersRequest](#pnfetchchannelmembersrequest) | Request object for fetching channel members. |
| `block` *Type: PNFetchChannelMembersCompletionBlock | Completion block. |

#### PNFetchChannelMembersRequest

| Parameter | Description |
| --- | --- |
| `sort`Type: NSArray`<NSString *>` | List of criteria (name of field) which should be used for sorting in ascending order. Available options are `id`, `name`, and `updated`. Use `asc` or `desc` to specify sort direction. For example: `{name: 'asc'}` |
| `includeFields`Type: PNChannelMemberFields | Bitfield set to fields that should be returned with the response. **Supported fields:** PNChannelMembersTotalCountField - include how many members the channel has., PNChannelMemberCustomField - include field with additional information from metadata associated with UUID during channel member set requests., PNChannelMemberStatusField - include field with metadata status associated with UUID during channel member set requests., PNChannelMemberTypeField - include field with metadata type associated with UUID during channel member set requests., PNChannelMemberUUIDField - include UUID's metadata in the response (not only the identifier)., PNChannelMemberUUIDCustomField - include UUID's additional information used during UUID metadata set requests., PNChannelMemberUUIDStatusField - include UUID's status used during UUID metadata set requests., PNChannelMemberUUIDTypeField - include UUID's type used during UUID metadata set requests. The default value (`PNChannelMembersTotalCountField`) can be reset by setting it to 0. |
| `filter`Type: NSString | Filter expression. Only matching objects are returned. See [filtering](https://www.pubnub.com/docs/general/metadata/filtering). |
| `start`Type: NSString | Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off. |
| `end`Type: NSString | Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data. Ignored if the `start` parameter is supplied. |
| `limit`Type: NSUInteger | Number of objects to return. Default/Max: 100. |

#### Sample code

```objectivec
PNFetchChannelMembersRequest *request = [PNFetchChannelMembersRequest requestWithChannel:@"channel"];
request.start = @"<next from previous request>";
// Add this request option, if returned member models should have value which has been set to
// 'custom' and 'uuid' properties.
request.includeFields = PNChannelMemberCustomField | PNChannelMemberUUIDField | PNChannelMembersTotalCountField;
request.limit = 40;

[self.client channelMembersWithRequest:request
                            completion:^(PNFetchChannelMembersResult *result, PNErrorStatus *status) {

    if (!status.isError) {
        /**
         * Channel's members successfully fetched.
         * Result object has following information:
         *   result.data.members - List of channel's members.
         *   result.data.next - Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off.
         *   result.data.prev - Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data.
         *   result.data.totalCount - Total number of channel's members.
         */
    } else {
        /**
         * Handle channel's members fetch error. Check 'category' property to find out possible
         * issue because of which request did fail.
         *
         * Request can be resent using: [status retry]
         */
    }
}];
```

#### Response

Response returned by the client for `fetch members`:

```objectivec
@interface PNFetchChannelMembersData : PNServiceData

// List of fetched members.
@property (nonatomic, readonly, strong) NSArray<PNChannelMember *> *members;

// Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off.
@property (nonatomic, nullable, readonly, strong) NSString *next;

// Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data.
@property (nonatomic, nullable, readonly, strong) NSString *prev;

/**
 * Total number of members created for current subscribe key.
 *
 * Value will be 0 in case if PNChannelMembersTotalCountField not added to 'includeFields'
 * of PNSetChannelMembersRequest / PNRemoveChannelMembersRequest /
 * PNManageChannelMembersRequest or PNFetchChannelMembersRequest.
 */
@property (nonatomic, readonly, assign) NSUInteger totalCount;

@end

@interface PNFetchChannelMembersResult : PNAcknowledgmentStatus

// Fetch members request processed information.
@property (nonatomic, readonly, strong) PNFetchChannelMembersData *data;

@end
```

Error response which is used in case of App Context API call failure:

```objectivec
@interface PNErrorData : PNServiceData

// Stringified error information.
@property (nonatomic, readonly, strong) NSString *information;

@end

@interface PNErrorStatus : PNStatus

// Whether status object represent error or not.
@property (nonatomic, readonly, assign, getter = isError) BOOL error;

// Additional information related to error status object.
@property (nonatomic, readonly, strong) PNErrorData *errorData;

@end
```

### Get channel members (builder pattern)

#### Method(s)

```objectivec
objects()
    .channelMembers(NSString *)
    .includeFields(PNChannelMemberFields)
    .includeCount(BOOL)
    .filter(NSString *)
    .sort(NSArray<NSString *> *)
    .limit(NSUInteger)
    .start(NSString *)
    .end(NSString *)
    .performWithCompletion(PNFetchChannelMembersCompletionBlock);
```

| Parameter | Description |
| --- | --- |
| `channel` *Type: NSString | Name of channel from which members should be fetched. |
| `includeFields`Type: PNChannelMemberFields | Bitfield set to fields that should be returned with the response. **Supported fields:** PNChannelMembersTotalCountField - include how many members the channel has., PNChannelMemberCustomField - include field with additional information from metadata associated with UUID during channel member set requests., PNChannelMemberStatusField - include field with metadata status associated with UUID during channel member set requests., PNChannelMemberTypeField - include field with metadata type associated with UUID during channel member set requests., PNChannelMemberUUIDField - include UUID's metadata in the response (not only the identifier)., PNChannelMemberUUIDCustomField - include UUID's additional information used during UUID metadata set requests., PNChannelMemberUUIDStatusField - include UUID's status used during UUID metadata set requests., PNChannelMemberUUIDTypeField - include UUID's type used during UUID metadata set requests. The default value (`PNChannelMembersTotalCountField`) can be reset by setting it to 0. |
| `includeCount`Type: BOOL | Whether to include the total count in the paginated response. Default: `YES` |
| `filter`Type: NSString | Expression to filter out results basing on specified criteria. For more details on the supported grammar, check [this](https://www.pubnub.com/docs/general/metadata/filtering) |
| `sort`Type: NSArray | List of criteria (name of field) which should be used for sorting in ascending order. Available options are `id`, `name`, and `updated`. Use `asc` or `desc` to specify sort direction. For example: `{name: 'asc'}` |
| `limit`Type: NSUInteger | Number of objects to return. Default/Max: 100. |
| `start`Type: NSString | Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off. |
| `end`Type: NSString | Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data. Ignored if the `start` parameter is supplied. |
| `block` *Type: PNFetchChannelMembersCompletionBlock | `Fetch channel's members` request completion block. |

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

#### Sample code

```objectivec
self.client.objects().channelMembers(@"channel")
    .includeCount(YES)
    .limit(40)
    .includeFields(PNChannelMemberCustomField | PNChannelMemberUUIDField)
    .performWithCompletion(^(PNFetchChannelMembersResult *result, PNErrorStatus *status) {
        if (!status.isError) {
            /**
             * Channel's members successfully fetched.
             * Result object has following information:
             *   result.data.members - List of channel's members.
             *   result.data.next - Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off.
             *   result.data.prev - Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data.
             *   result.data.totalCount - Total number of channel's members.
             */
        } else {
            /**
             * Handle channel's members fetch error. Check 'category' property to find out possible
             * issue because of which request did fail.
             *
             * Request can be resent using: [status retry]
             */
        }
    });
```

#### Response

Response returned by the client for `fetch members`:

```objectivec
@interface PNFetchChannelMembersData : PNServiceData

// List of fetched members.
@property (nonatomic, readonly, strong) NSArray<PNChannelMember *> *members;

// Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off.
@property (nonatomic, nullable, readonly, strong) NSString *next;

// Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data.
@property (nonatomic, nullable, readonly, strong) NSString *prev;

/**
 * Total number of members created for current subscribe key.
 *
 * Value will be 0 in case if PNChannelMembersTotalCountField not added to 'includeFields'
 * of PNSetChannelMembersRequest / PNRemoveChannelMembersRequest /
 * PNManageChannelMembersRequest or PNFetchChannelMembersRequest.
 */
@property (nonatomic, readonly, assign) NSUInteger totalCount;

@end

@interface PNFetchChannelMembersResult : PNAcknowledgmentStatus

// Fetch members request processed information.
@property (nonatomic, readonly, strong) PNFetchChannelMembersData *data;

@end
```

Error response which is used in case of App Context API call failure:

```objectivec
@interface PNErrorData : PNServiceData

// Stringified error information.
@property (nonatomic, readonly, strong) NSString *information;

@end

@interface PNErrorStatus : PNStatus

// Whether status object represent error or not.
@property (nonatomic, readonly, assign, getter = isError) BOOL error;

// Additional information related to error status object.
@property (nonatomic, readonly, strong) PNErrorData *errorData;

@end
```

### Set channel members

This method sets members in a channel.

#### Method(s)

To `Set Channel Members` you can use the following method(s) in the Objective-C SDK:

```objectivec
- (void)setChannelMembersWithRequest:(PNSetChannelMembersRequest *)request 
                          completion:(nullable PNManageChannelMembersCompletionBlock)block;
```

| Parameter | Description |
| --- | --- |
| `request` *Type: [PNSetChannelMembersRequest](#pnsetmembersrequest) | Request object for setting channel members. |
| `block`Type: PNManageChannelMembersCompletionBlock | `Set channel's members` list request completion `block`. |

#### PNSetMembersRequest

| Parameter | Description |
| --- | --- |
| `sort`Type: NSArray`<NSString *>` | List of criteria (name of field) which should be used for sorting in ascending order. Available options are `id`, `name`, and `updated`. Use `asc` or `desc` to specify sort direction. For example: `{name: 'asc'}` |
| `includeFields`Type: PNChannelMemberFields | Bitfield set to fields that should be returned with the response. **Supported fields:** PNChannelMembersTotalCountField - include how many members the channel has., PNChannelMemberCustomField - include field with additional information from metadata associated with UUID during channel member set requests., PNChannelMemberStatusField - include field with metadata status associated with UUID during channel member set requests., PNChannelMemberTypeField - include field with metadata type associated with UUID during channel member set requests., PNChannelMemberUUIDField - include UUID's metadata in the response (not only the identifier)., PNChannelMemberUUIDCustomField - include UUID's additional information used during UUID metadata set requests., PNChannelMemberUUIDStatusField - include UUID's status used during UUID metadata set requests., PNChannelMemberUUIDTypeField - include UUID's type used during UUID metadata set requests. The default value (`PNChannelMembersTotalCountField`) can be reset by setting it to 0. |
| `filter`Type: NSString | Expression to filter out results basing on specified criteria. For more details on the supported grammar, check [this](https://www.pubnub.com/docs/general/metadata/filtering) |
| `start`Type: NSString | Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off. |
| `end`Type: NSString | Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data. Ignored if the `start` parameter is supplied. |
| `limit`Type: NSUInteger | Number of objects to return. Default/Max: 100. |

:::tip API limits
To learn about the maximum length of parameters used to set channel members metadata, refer to [REST API docs](https://www.pubnub.com/docs/sdks/rest-api/set-channel-members-metadata).
:::

#### Sample code

```objectivec
NSArray<NSDictionary *> *uuids = @[
  @{ 
    @"uuid": @"uuid2"
    @"status": @"active",
    @"type": @"admin",
    @"custom": @{ @"role": @"moderator" } 
  }
];

PNSetChannelMembersRequest *request = [PNSetChannelMembersRequest requestWithChannel:@"channel" uuids:uuids];
// Add this request option, if returned member models should have value which has been set to
// 'custom' and 'uuid' properties.
request.includeFields = PNChannelMemberCustomField | PNChannelMemberUUIDField | PNChannelMembersTotalCountField;
request.limit = 40;

[self.client setChannelMembersWithRequest:request completion:^(PNManageChannelMembersStatus *status) {
    if (!status.isError) {
        /**
         * Channel's members successfully set.
         * Result object has following information:
         *   result.data.members - List of existing channel's members.
         *   result.data.next - Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off.
         *   result.data.prev - Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data.
         *   result.data.totalCount - Total number of channel's members.
         */
    } else {
        /**
         * Handle channel's members set error. Check 'category' property to find out possible
         * issue because of which request did fail.
         *
         * Request can be resent using: [status retry]
         */
    }
}];
```

#### Response

Response returned by the client for `set members`:

```objectivec
@interface PNManageChannelMembersData : PNServiceData

// List of existing members.
@property (nonatomic, readonly, strong) NSArray<PNChannelMember *> *members;

// Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off.
@property (nonatomic, nullable, readonly, strong) NSString *next;

// Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data.
@property (nonatomic, nullable, readonly, strong) NSString *prev;

/**
 * Total number of existing objects.
 *
 * Value will be 0 in case if PNChannelMembersTotalCountField not added to 'includeFields'
 * of PNSetChannelMembersRequest / PNRemoveChannelMembersRequest /
 * PNManageChannelMembersRequest or PNFetchChannelMembersRequest.
 */
@property (nonatomic, readonly, assign) NSUInteger totalCount;

@end

@interface PNManageChannelMembersStatus : PNAcknowledgmentStatus

// Members set / remove / manage request processed information.
@property (nonatomic, readonly, strong) PNManageChannelMembersData *data;

@end
```

### Set channel members (builder pattern)

#### Method(s)

```objectivec
objects()
    .setChannelMembers(NSString *)
    .uuids(NSArray<NSDictionary *> *)
    .includeFields(PNChannelMemberFields)
    .includeCount(BOOL)
    .filter(NSString *)
    .sort(NSArray<NSString *> *)
    .limit(NSUInteger)
    .start(NSString *)
    .end(NSString *)
    .performWithCompletion(nullable PNManageChannelMembersCompletionBlock);
```

:::tip API limits
To learn about the maximum length of parameters used to set channel members metadata, refer to [REST API docs](https://www.pubnub.com/docs/sdks/rest-api/set-channel-members-metadata).
:::

| Parameter | Description |
| --- | --- |
| `channel` *Type: NSString | Name of channel from which members should be set. |
| `uuids`Type: NSArray | List of `UUIDs` for which `metadata` associated with each of them in context of `channel` should be set. Each entry is dictionary with `UUID` and `optional` `custom` fields. `custom` should be dictionary with simple objects: `NSString` and `NSNumber`. |
| `includeFields`Type: PNChannelMemberFields | Bitfield set to fields that should be returned with the response. **Supported fields:** PNChannelMembersTotalCountField - include how many members the channel has., PNChannelMemberCustomField - include field with additional information from metadata associated with UUID during channel member set requests., PNChannelMemberStatusField - include field with metadata status associated with UUID during channel member set requests., PNChannelMemberTypeField - include field with metadata type associated with UUID during channel member set requests., PNChannelMemberUUIDField - include UUID's metadata in the response (not only the identifier)., PNChannelMemberUUIDCustomField - include UUID's additional information used during UUID metadata set requests., PNChannelMemberUUIDStatusField - include UUID's status used during UUID metadata set requests., PNChannelMemberUUIDTypeField - include UUID's type used during UUID metadata set requests. The default value (`PNChannelMembersTotalCountField`) can be reset by setting it to 0. |
| `includeCount`Type: BOOL | Whether to include the total count in the paginated response. Default: `YES` |
| `filter`Type: NSString | Filter expression. Only matching objects are returned. See [filtering](https://www.pubnub.com/docs/general/metadata/filtering). |
| `sort`Type: NSArray | List of criteria (name of field) which should be used for sorting in ascending order. Available options are `id`, `name`, and `updated`. Use `asc` or `desc` to specify sort direction. For example: `{name: 'asc'}` |
| `limit`Type: NSUInteger | Number of objects to return. Default/Max: 100. |
| `start`Type: NSString | Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off. |
| `end`Type: NSString | Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data. Ignored if the `start` parameter is supplied. |
| `block`Type: PNManageChannelMembersCompletionBlock | `Set channel's members` list request completion `block`. |

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

#### Sample code

```objectivec
NSArray<NSDictionary *> *uuids = @[
  @{ 
    @"uuid": @"uuid2"
    @"status": @"active",
    @"type": @"admin",
    @"custom": @{ @"role": @"moderator" } 
  }
];

self.client.objects().setChannelMembers(@"channel")
    .uuids(uuids)
    .includeCount(YES)
    .limit(40)
    .includeFields(PNChannelMemberCustomField | PNChannelMemberUserField)
    .performWithCompletion(^(PNManageChannelMembersStatus *status) {
        if (!status.isError) {
            /**
             * Channel's members successfully set.
             * Result object has following information:
             *   result.data.members - List of existing channel's members.
             *   result.data.next - Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off.
             *   result.data.prev - Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data.
             *   result.data.totalCount - Total number of channel's members.
             */
        } else {
            /**
             * Handle channel's members set error. Check 'category' property to find out possible
             * issue because of which request did fail.
             *
             * Request can be resent using: [status retry]
             */
        }
    });
```

#### Response

Response returned by the client for `set members`:

```objectivec
@interface PNManageChannelMembersData : PNServiceData

// List of existing members.
@property (nonatomic, readonly, strong) NSArray<PNChannelMember *> *members;

// Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off.
@property (nonatomic, nullable, readonly, strong) NSString *next;

// Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data.
@property (nonatomic, nullable, readonly, strong) NSString *prev;

/**
 * Total number of existing objects.
 *
 * Value will be 0 in case if PNChannelMembersTotalCountField not added to 'includeFields'
 * of PNSetChannelMembersRequest / PNRemoveChannelMembersRequest /
 * PNManageChannelMembersRequest or PNFetchChannelMembersRequest.
 */
@property (nonatomic, readonly, assign) NSUInteger totalCount;

@end

@interface PNManageChannelMembersStatus : PNAcknowledgmentStatus

// Members set / remove / manage request processed information.
@property (nonatomic, readonly, strong) PNManageChannelMembersData *data;

@end
```

### Remove channel members

Remove members from a Channel.

#### Method(s)

To `Remove Channel Members` you can use the following method(s) in the Objective-C SDK:

```objectivec
- (void)removeChannelMembersWithRequest:(PNRemoveChannelMembersRequest *)request 
                             completion:(nullable PNManageChannelMembersCompletionBlock)block;
```

| Parameter | Description |
| --- | --- |
| `request` *Type: [PNRemoveChannelMembersRequest](#pnremovechannelmembersrequest) | Request object for removing channel members. |
| `block`Type: PNManageChannelMembersCompletionBlock | `Remove channel's members` request completion `block`. |

#### PNRemoveChannelMembersRequest

| Parameter | Description |
| --- | --- |
| `sort`Type: NSArray`<NSString *>` | List of criteria (name of field) which should be used for sorting in ascending order. Available options are `id`, `name`, and `updated`. Use `asc` or `desc` to specify sort direction. For example: `{name: 'asc'}` |
| `includeFields`Type: PNChannelMemberFields | Bitfield set to fields that should be returned with the response. **Supported fields:** PNChannelMembersTotalCountField - include how many members the channel has., PNChannelMemberCustomField - include field with additional information from metadata associated with UUID during channel member set requests., PNChannelMemberStatusField - include field with metadata status associated with UUID during channel member set requests., PNChannelMemberTypeField - include field with metadata type associated with UUID during channel member set requests., PNChannelMemberUUIDField - include UUID's metadata in the response (not only the identifier)., PNChannelMemberUUIDCustomField - include UUID's additional information used during UUID metadata set requests., PNChannelMemberUUIDStatusField - include UUID's status used during UUID metadata set requests., PNChannelMemberUUIDTypeField - include UUID's type used during UUID metadata set requests. The default value (`PNChannelMembersTotalCountField`) can be reset by setting it to 0. |
| `filter`Type: NSString | Expression to filter out results basing on specified criteria. For more details on the supported grammar, check [this](https://www.pubnub.com/docs/general/metadata/filtering) |
| `start`Type: NSString | Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off. |
| `end`Type: NSString | Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data. Ignored if the `start` parameter is supplied. |
| `limit`Type: NSUInteger | Number of objects to return. Default/Max: 100. |

#### Sample code

```objectivec
NSArray<NSString *> *uuids = @[@"uuid3", @"uuid4"];
PNRemoveChannelMembersRequest *request = [PNRemoveChannelMembersRequest requestWithChannel:@"channel"
                                                                                     uuids:uuids];
// Add this request option, if returned member models should have value which has been set to
// 'custom' and 'uuid' properties.
request.includeFields = PNChannelMemberCustomField | PNChannelMemberUUIDField | PNChannelMembersTotalCountField;
request.limit = 40;

[self.client removeChannelMembersWithRequest:request completion:^(PNManageChannelMembersStatus *status) {
    if (!status.isError) {
        /**
         * Channel's members successfully removed.
         * Result object has following information:
         *   result.data.members - List of channel's existing members.
         *   result.data.next - Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off.
         *   result.data.prev - Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data.
         *   result.data.totalCount - Total number of channel's members.
         */
    } else {
        /**
         * Handle channel's members remove error. Check 'category' property to find out possible
         * issue because of which request did fail.
         *
         * Request can be resent using: [status retry]
         */
    }
}];
```

#### Response

Response returned by the client for `remove members`:

```objectivec
@interface PNManageChannelMembersData : PNServiceData

// List of existing members.
@property (nonatomic, readonly, strong) NSArray<PNChannelMember *> *members;

// Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off.
@property (nonatomic, nullable, readonly, strong) NSString *next;

// Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data.
@property (nonatomic, nullable, readonly, strong) NSString *prev;

/**
 * Total number of existing objects.
 *
 * Value will be 0 in case if PNChannelMembersTotalCountField not added to 'includeFields'
 * of PNSetChannelMembersRequest / PNRemoveChannelMembersRequest /
 * PNManageChannelMembersRequest or PNFetchChannelMembersRequest.
 */
@property (nonatomic, readonly, assign) NSUInteger totalCount;

@end

@interface PNManageChannelMembersStatus : PNAcknowledgmentStatus

// Members set / remove / manage request processed information.
@property (nonatomic, readonly, strong) PNManageChannelMembersData *data;

@end
```

### Remove channel members (builder pattern)

#### Method(s)

```objectivec
objects()
    .removeChannelMembers(NSString *)
    .uuids(NSArray<NSString *> *)
    .includeFields(PNChannelMemberFields)
    .includeCount(BOOL)
    .filter(NSString *)
    .sort(NSArray<NSString *> *)
    .limit(NSUInteger)
    .start(NSString *)
    .end(NSString *)
    .performWithCompletion(nullable PNManageChannelMembersCompletionBlock);
```

| Parameter | Description |
| --- | --- |
| `channel` *Type: NSString | Name of channel from which members should be removed. |
| `uuids`Type: NSArray | List of `UUIDs` which should be removed from `channel's` list. |
| `includeFields`Type: PNChannelMemberFields | Bitfield set to fields that should be returned with the response. **Supported fields:** PNChannelMembersTotalCountField - include how many members the channel has., PNChannelMemberCustomField - include field with additional information from metadata associated with UUID during channel member set requests., PNChannelMemberStatusField - include field with metadata status associated with UUID during channel member set requests., PNChannelMemberTypeField - include field with metadata type associated with UUID during channel member set requests., PNChannelMemberUUIDField - include UUID's metadata in the response (not only the identifier)., PNChannelMemberUUIDCustomField - include UUID's additional information used during UUID metadata set requests., PNChannelMemberUUIDStatusField - include UUID's status used during UUID metadata set requests., PNChannelMemberUUIDTypeField - include UUID's type used during UUID metadata set requests. The default value (`PNChannelMembersTotalCountField`) can be reset by setting it to 0. |
| `includeCount`Type: BOOL | Whether to include the total count in the paginated response. Default: `YES` |
| `filter`Type: NSString | Expression to filter out results basing on specified criteria. For more details on the supported grammar, check [this](https://www.pubnub.com/docs/general/metadata/filtering) |
| `sort`Type: NSArray | List of criteria (name of field) which should be used for sorting in ascending order. Available options are `id`, `name`, and `updated`. Use `asc` or `desc` to specify sort direction. For example: `{name: 'asc'}` |
| `limit`Type: NSUInteger | Number of objects to return. Default/Max: 100. |
| `start`Type: NSString | Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off. |
| `end`Type: NSString | Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data. Ignored if the `start` parameter is supplied. |
| `block`Type: PNManageChannelMembersCompletionBlock | `Remove channel's members` request completion `block`. |

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

#### Sample code

```objectivec
self.client.objects().removeChannelMembers(@"channel")
    .uuids(@[@"uuid3", @"uuid4"])
    .includeCount(YES)
    .limit(40)
    .includeFields(PNChannelMemberCustomField | PNChannelMemberUserField)
    .performWithCompletion(^(PNManageChannelMembersStatus *status) {
        if (!status.isError) {
            /**
             * Channel's members successfully removed.
             * Result object has following information:
             *   result.data.members - List of channel's existing members.
             *   result.data.next - Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off.
             *   result.data.prev - Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data.
             *   result.data.totalCount - Total number of channel's members.
             */
        } else {
            /**
             * Handle channel's members remove error. Check 'category' property to find out possible
             * issue because of which request did fail.
             *
             * Request can be resent using: [status retry]
             */
        }
    });
```

#### Response

Response returned by the client for `remove members`:

```objectivec
@interface PNManageChannelMembersData : PNServiceData

// List of existing members.
@property (nonatomic, readonly, strong) NSArray<PNChannelMember *> *members;

// Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off.
@property (nonatomic, nullable, readonly, strong) NSString *next;

// Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data.
@property (nonatomic, nullable, readonly, strong) NSString *prev;

/**
 * Total number of existing objects.
 *
 * Value will be 0 in case if PNChannelMembersTotalCountField not added to 'includeFields'
 * of PNSetChannelMembersRequest / PNRemoveChannelMembersRequest /
 * PNManageChannelMembersRequest or PNFetchChannelMembersRequest.
 */
@property (nonatomic, readonly, assign) NSUInteger totalCount;

@end

@interface PNManageChannelMembersStatus : PNAcknowledgmentStatus

// Members set / remove / manage request processed information.
@property (nonatomic, readonly, strong) PNManageChannelMembersData *data;

@end
```

### Manage channel members

The method Set and Remove channel memberships for a user.

#### Method(s)

To `Manage Channel Members` you can use the following method(s) in the Objective-C SDK:

```objectivec
- (void)manageChannelMembersWithRequest:(PNManageChannelMembersRequest *)request 
                             completion:(nullable PNManageChannelMembersCompletionBlock)block;
```

| Parameter | Description |
| --- | --- |
| `request` *Type: [PNManageChannelMembersRequest](#pnmanagechannelmembersrequest) | Request object for managing channel members. |
| `block`Type: PNManageChannelMembersCompletionBlock | `Manage channel's members` list request completion `block`. |

#### PNManageChannelMembersRequest

| Parameter | Description |
| --- | --- |
| `setMembers`Type: NSArray`<NSDictionary *`> | List of UUIDs which should be added to channel's members list. Each entry is dictionary with uuid and optional `custom` fields. `custom` should be dictionary with simple objects: NSString and NSNumber. |
| `removeMembers`Type: NSArray`<NSString *>` | BList of UUIDs which should be removed from channel's list. |
| `sort`Type: NSArray`<NSString *>` | List of criteria (name of field) which should be used for sorting in ascending order. Available options are `id`, `name`, and `updated`. Use `asc` or `desc` to specify sort direction. For example: `{name: 'asc'}` |
| `includeFields`Type: PNChannelMemberFields | Bitfield set to fields that should be returned with the response. **Supported fields:** PNChannelMembersTotalCountField - include how many members the channel has., PNChannelMemberCustomField - include field with additional information from metadata associated with UUID during channel member set requests., PNChannelMemberStatusField - include field with metadata status associated with UUID during channel member set requests., PNChannelMemberTypeField - include field with metadata type associated with UUID during channel member set requests., PNChannelMemberUUIDField - include UUID's metadata in the response (not only the identifier)., PNChannelMemberUUIDCustomField - include UUID's additional information used during UUID metadata set requests., PNChannelMemberUUIDStatusField - include UUID's status used during UUID metadata set requests., PNChannelMemberUUIDTypeField - include UUID's type used during UUID metadata set requests. The default value (`PNChannelMembersTotalCountField`) can be reset by setting it to 0. |
| `filter`Type: NSString | Expression to filter out results basing on specified criteria. For more details on the supported grammar, check [this](https://www.pubnub.com/docs/general/metadata/filtering) |
| `start`Type: NSString | Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off. |
| `end`Type: NSString | Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data. Ignored if the `start` parameter is supplied. |
| `limit`Type: NSUInteger | Number of objects to return. Default/Max: 100. |

#### Sample code

```objectivec
PNManageChannelMembersRequest *request = [PNManageChannelMembersRequest requestWithChannel:@"channel"];
request.setMembers = @[
    @{ @"uuid": @"uuid2", @"custom": @{ @"role": @"moderator" } }
];
request.removeMembers = @[@"uuid3", @"uuid4"];
// Add this request option, if returned member models should have value which has been set to
// 'custom' and 'uuid' properties.
request.includeFields = PNChannelMemberCustomField | PNChannelMemberUUIDField | PNChannelMembersTotalCountField;
request.limit = 40;

[self.client manageChannelMembersWithRequest:request
                               completion:^(PNManageChannelMembersStatus *status) {

    if (!status.isError) {
        /**
         * Channel's members successfully set.
         * Result object has following information:
         *   result.data.members - List of existing channel's members.
         *   result.data.next - Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off.
         *   result.data.prev - Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data.
         *   result.data.totalCount - Total number of channel's members.
         */
    } else {
        /**
         * Handle channel's members manage error. Check 'category' property to find out possible
         * issue because of which request did fail.
         *
         * Request can be resent using: [status retry]
         */
    }
}];
```

#### Response

Response returned by the client for `manage members`:

```objectivec
@interface PNManageChannelMembersData : PNServiceData

// List of existing members.
@property (nonatomic, readonly, strong) NSArray<PNChannelMember *> *members;

// Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off.
@property (nonatomic, nullable, readonly, strong) NSString *next;

// Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data.
@property (nonatomic, nullable, readonly, strong) NSString *prev;

/**
 * Total number of existing objects.
 *
 * Value will be 0 in case if PNChannelMembersTotalCountField not added to 'includeFields'
 * of PNSetChannelMembersRequest / PNRemoveChannelMembersRequest /
 * PNManageChannelMembersRequest or PNFetchChannelMembersRequest.
 */
@property (nonatomic, readonly, assign) NSUInteger totalCount;

@end

@interface PNManageChannelMembersStatus : PNAcknowledgmentStatus

// Members set / remove / manage request processed information.
@property (nonatomic, readonly, strong) PNManageChannelMembersData *data;

@end
```

### Manage channel members (builder pattern)

#### Method(s)

```objectivec
objects()
    .manageChannelMembers(NSString *)
    .set(NSArray<NSDictionary *> *)
    .remove(NSArray<NSString *> *)
    .includeFields(PNChannelMemberFields)
    .includeCount(BOOL)
    .filter(NSString *)
    .sort(NSArray<NSString *> *)
    .limit(NSUInteger)
    .start(NSString *)
    .end(NSString *)
    .performWithCompletion(nullable PNManageChannelMembersCompletionBlock);
```

| Parameter | Description |
| --- | --- |
| `channel` *Type: NSString | Name of channel from which members should be managed. |
| `set`Type: NSArray | List of `UUIDs` which should be added to `channel's` members list. Each entry is dictionary with `UUID` and `optional` `custom` fields. `custom` should be dictionary with simple objects: `NSString` and `NSNumber`. |
| `remove`Type: NSArray | List of `UUIDs` which should be removed from `channel's` list. |
| `includeFields`Type: PNChannelMemberFields | Bitfield set to fields that should be returned with the response. **Supported fields:** PNChannelMembersTotalCountField - include how many members the channel has., PNChannelMemberCustomField - include field with additional information from metadata associated with UUID during channel member set requests., PNChannelMemberStatusField - include field with metadata status associated with UUID during channel member set requests., PNChannelMemberTypeField - include field with metadata type associated with UUID during channel member set requests., PNChannelMemberUUIDField - include UUID's metadata in the response (not only the identifier)., PNChannelMemberUUIDCustomField - include UUID's additional information used during UUID metadata set requests., PNChannelMemberUUIDStatusField - include UUID's status used during UUID metadata set requests., PNChannelMemberUUIDTypeField - include UUID's type used during UUID metadata set requests. The default value (`PNChannelMembersTotalCountField`) can be reset by setting it to 0. |
| `includeCount`Type: BOOL | Whether to include the total count in the paginated response. Default is false. |
| `filter`Type: NSString | Expression to filter out results basing on specified criteria. For more details on the supported grammar, check [this](https://www.pubnub.com/docs/general/metadata/filtering) |
| `sort`Type: NSArray | List of criteria (name of field) which should be used for sorting in ascending order. Available options are `id`, `name`, and `updated`. Use `asc` or `desc` to specify sort direction. For example: `{name: 'asc'}` |
| `limit`Type: NSUInteger | Number of objects to return. Default/Max: 100. |
| `start`Type: NSString | Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off. |
| `end`Type: NSString | Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data. Ignored if the `start` parameter is supplied. |
| `block`Type: PNManageChannelMembersCompletionBlock | `Set channel's members` list request completion `block`. |

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

#### Sample code

```objectivec
NSArray<NSDictionary *> *setMembers = @[
    @{ @"uuid": @"uuid2", @"custom": @{ @"role": @"moderator" } }
];
NSArray<NSDictionary *> *removeMembers = @[@"uuid3", @"uuid4"];

self.client.objects().manageChannelMembers(@"channel")
    .set(setMembers)
    .remove(removeMembers)
    .includeCount(YES)
    .limit(40)
    .includeFields(PNChannelMemberCustomField | PNChannelMemberUUIDField)
    .performWithCompletion(^(PNManageChannelMembersStatus *status) {
        if (!status.isError) {
            /**
             * Channel's members successfully changed.
             * Result object has following information:
             *   result.data.members - List of existing channel's members.
             *   result.data.next - Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off.
             *   result.data.prev - Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data.
             *   result.data.totalCount - Total number of channel's members.
             */
        } else {
            /**
             * Handle channel's members manage error. Check 'category' property to find out possible
             * issue because of which request did fail.
             *
             * Request can be resent using: [status retry]
             */
        }
    });
```

#### Response

Response returned by the client for `manage members`:

```objectivec
@interface PNManageChannelMembersData : PNServiceData

// List of existing members.
@property (nonatomic, readonly, strong) NSArray<PNChannelMember *> *members;

// Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off.
@property (nonatomic, nullable, readonly, strong) NSString *next;

// Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data.
@property (nonatomic, nullable, readonly, strong) NSString *prev;

/**
 * Total number of existing objects.
 *
 * Value will be 0 in case if PNChannelMembersTotalCountField not added to 'includeFields'
 * of PNSetChannelMembersRequest / PNRemoveChannelMembersRequest /
 * PNManageChannelMembersRequest or PNFetchChannelMembersRequest.
 */
@property (nonatomic, readonly, assign) NSUInteger totalCount;

@end

@interface PNManageChannelMembersStatus : PNAcknowledgmentStatus

// Members set / remove / manage request processed information.
@property (nonatomic, readonly, strong) PNManageChannelMembersData *data;

@end
```

## Terms in this document

* **Channel** - A pathway for sending and receiving messages between devices, created automatically when you first use it, that can handle any number of users and messages for different communication needs, like 1-1 text chats, group conversations, and other data streaming.
* **Channel pattern** - A way to group and analyze channel data to track performance metrics like message counts and user engagement over time with PubNub Insights.
* **User** - An individual or entity that interacts with a system, application, or service. In PubNub, a user typically refers to someone who sends or receives messages through the platform, identified by a unique user ID or username.
* **User ID** - UTF-8 encoded, unique string of up to 92 characters used to identify a single client (end user, device, or server) that connects to PubNub.