# Storage (/zh-CN/api-reference/rtm/swift/storage)

> For AI agents: see the complete documentation index at [llms.txt](/llms.txt).

RTM 的 Storage 功能提供了一套动态数据库机制，可以让开发者动态设置、存储、更新、删除 Channel Metadata 和 User Metadata 等数据。

## setChannelMetadata [#setchannelmetadata]

### 接口描述 [#接口描述]

`setChannelMetadata` 方法可以为频道（Message Channel 或 Stream Channel）设置 Channel Metadata。一个频道只能有一组 Metadata，但每组 Metadata 可以有一个或多个 Metadata Item。如果多次调用该方法，SDK 会依次检索 Metadata Item 的 `key` 值，并按如下规则处理：

- 如果设置的 Metadata Item `key` 值不同，则会根据调用顺序依次增加。
- 如果设置的 Metadata Item `key` 值相同，则最后一次设置的 Metadata Item 的 `value` 会覆盖之前的值。

成功设置 Channel Metadata 后，订阅该频道且开启事件监听的用户会收到 `channel` 类型的 `didReceiveStorageEvent` 事件通知。详见[事件监听](/zh-CN/api-reference/rtm/swift/configuration#事件监听)。

Channel Metadata 同时也引进了版本控制逻辑 CAS（Compare And Set），该方法提供两种独立的版本控制字段，你可以根据实际业务场景设置任意一种或多种：

- 通过 `AgoraRtmMetadata` 中的 `majorRevision` 属性开启整组 Channel Metadata 的版本号校验。
- 通过 `AgoraRtmMetadataItem` 中的 `revision` 属性开启某个 Metadata Item 的版本号校验。

设置 Channel Metadata 或 Metadata Item 时，配合版本属性可以控制本次调用是否开启版本号校验，逻辑如下：

- 版本属性默认为 `-1` ，本次调用不开启 CAS 验证。如果 Channel Metadata 或 Metadata Item 已存在，则该值会被最新值覆盖；如果 Channel Metadata 或 Metadata Item 不存在，则 SDK 会创建该值。
- 版本属性为正整数时，本次调用开启 CAS 验证。如果 Channel Metadata 或 Metadata Item 已存在，则 SDK 会在版本号验证成功后更新对应的值；否则 SDK 会返回错误码。

### 接口方法 [#接口方法]

你可以通过以下方式调用 `setChannelMetadata` 方法：

```swift
setChannelMetadata(
    channelName: String,
    channelType: AgoraRtmChannelType,
    data: AgoraRtmMetadata,
    options: AgoraRtmMetadataOptions?,
    lock: String?
)   async -> (AgoraRtmCommonResponse?, AgoraRtmErrorInfo?)
```

```swift
setChannelMetadata(
    channelName: String,
    channelType: AgoraRtmChannelType,
    data: AgoraRtmMetadata,
    options: AgoraRtmMetadataOptions?,
    lock: String?,
    completion completionBlock: AgoraRtmOperationBlock? = nil
)
```

| 参数 | 类型 | 必填 | 默认值 | 描述 |
| --- | --- | --- | --- | --- |
| `channelName` | String | 必填 | - | 频道名称。 |
| `channelType` | `AgoraRtmChannelType` | 必填 | - | 频道类型。详见 [`AgoraRtmChannelType`](/zh-CN/api-reference/rtm/swift/enumv#channeltype)。 |
| `data` | `AgoraRtmMetadata` | 必填 | - | Metadata Item。详见 [`AgoraRtmMetadata`](#agorartmmetadata)。 |
| `options` | `AgoraRtmMetadataOptions` | 选填 | - | Channel Metadata 配置选项。 |
| `lock` | String | 选填 | 空字符串 `''` | Lock 名称。设置后，只有调用 `acquireLock` 方法获取该锁的用户才能执行操作。 |
| `completion` | `AgoraRtmOperationBlock` | 选填 | - | [storage-swift-html-0-6-4 details](#table-slot-storage-swift-html-0-6-4) |

<a id="table-slot-storage-swift-html-0-6-4"></a>

**storage-swift-html-0-6-4 details**

调用结果回调：

- 调用成功：在 `response` 参数中返回 `AgoraRtmCommonResponse` 数据，在 `errorInfo` 参数中返回 `nil`。
- 调用失败：在 `response` 参数中返回 `nil`，在 `errorInfo` 参数中返回错误信息。

`AgoraRtmMetadataOptions` 数据类型包含以下属性：

| 属性           | 类型 | 是否必填 | 默认值  | 描述                      |
| ------------- | --- | ------- | ------ | ----------- |
| `recordTs`     | Bool | 选填     | `false` | 是否记录编辑的时间戳。    |
| `recordUserId` | Bool | 选填     | `false` | 是否记录编辑者的用户 ID。 |

### 接口方法 [#接口方法-1]

```swift tab="async-await"
// async-await
let channelName = "exampleChannel"
let channelType: AgoraRtmChannelType = .message

// Create metadata items
let metadataItem1 = AgoraRtmMetadataItem(key: "topic", value: "discussion", revision: 174298200)
let metadataItem2 = AgoraRtmMetadataItem(key: "status", value: "active", revision: 174298100)

// Create metadata
let metadata = AgoraRtmMetadata()
metadata.majorRevision = 174298270
metadata.items = [metadataItem1, metadataItem2]

// Set metadata options
let metadataOptions = AgoraRtmMetadataOptions()
metadataOptions.recordTs = true
metadataOptions.recordUserId = true

// Set channel metadata
let (response, error) = await rtmClient.setChannelMetadata(
    channelName: channelName,
    channelType: channelType,
    data: metadata,
    options: metadataOptions,
    lock: nil // or provide a lock name
)

if let errorInfo = error {
    // Handle error
    print("Failed to set channel metadata with error: \(errorInfo.reason)")
} else if let setMetadataResponse = response {
    // Handle success
    print("Channel metadata set successfully.")
} else {
    // Handle unknown error
    print("Unknown error occurred while setting channel metadata.")
}
```

```swift tab="callback"
// callback
let channelName = "exampleChannel"
let channelType: AgoraRtmChannelType = .message

// Create metadata items
let metadataItem1 = AgoraRtmMetadataItem(key: "topic", value: "discussion", revision: 174298200)
let metadataItem2 = AgoraRtmMetadataItem(key: "status", value: "active", revision: 174298100)

// Create metadata
let metadata = AgoraRtmMetadata()
metadata.majorRevision = 174298270
metadata.items = [metadataItem1, metadataItem2]

// Set metadata options
let metadataOptions = AgoraRtmMetadataOptions()
metadataOptions.recordTs = true
metadataOptions.recordUserId = true

// Set channel metadata
rtmClient.setChannelMetadata(
    channelName: channelName,
    channelType: channelType,
    data: metadata,
    options: metadataOptions,
    lock: nil, // or provide a lock name
    completion: { (response, error) in
        if let errorInfo = error {
            // Handle error
            print("Failed to set channel metadata with error: \(errorInfo.reason)")
        } else if let setMetadataResponse = response {
            // Handle success
            print("Channel metadata set successfully.")
        } else {
            // Handle unknown error
            print("Unknown error occurred while setting channel metadata.")
        }
    }
)
```

## getChannelMetadata [#getchannelmetadata]

### 接口描述 [#接口描述-1]

`getChannelMetadata` 方法可以获取指定频道的 Metadata。

### 接口方法 [#接口方法-2]

你可以通过以下方式调用 `getChannelMetadata` 方法：

```swift
getChannelMetadata(
    channelName: String,
    channelType: AgoraRtmChannelType
)   async -> (AgoraRtmGetMetadataResponse?, AgoraRtmErrorInfo?)
```

```swift
getChannelMetadata(
    channelName: String,
    channelType: AgoraRtmChannelType,
    completion completionBlock: AgoraRtmGetMetadataBlock? = nil
)
```

| 参数 | 类型 | 必填 | 默认值 | 描述 |
| --- | --- | --- | --- | --- |
| `channelName` | String | 必填 | - | 频道名称。 |
| `channelType` | `AgoraRtmChannelType` | 必填 | - | 频道类型。详见 [`AgoraRtmChannelType`](/zh-CN/api-reference/rtm/swift/enumv#channeltype)。 |
| `completion` | `AgoraRtmGetMetadataBlock` | 选填 | - | [storage-swift-html-1-3-4 details](#table-slot-storage-swift-html-1-3-4) |

<a id="table-slot-storage-swift-html-1-3-4"></a>

**storage-swift-html-1-3-4 details**

调用结果回调：

- 调用成功：在 `response` 参数中返回 `AgoraRtmGetMetadataResponse` 数据，在 `errorInfo` 参数中返回 `nil`。
- 调用失败：在 `response` 参数中返回 `nil`，在 `errorInfo` 参数中返回错误信息。

`AgoraRtmGetMetadataResponse` 数据类型包含以下属性：

|  属性  |  类型  | 描述      |
| ---- | ------ | --------- |
|     `data`     |      `AgoraRtmMetadata`     | Metadata Item。详见 [`AgoraRtmMetadata`](#agorartmmetadata)。 |

### 接口方法 [#接口方法-3]

```swift tab="async-await"
// async-await
let channelName = "exampleChannel"
let channelType: AgoraRtmChannelType = .message

// Retrieve channel metadata
let (response, error) = await rtmClient.getChannelMetadata(
    channelName: channelName,
    channelType: channelType
)
if let errorInfo = error {
    // Handle error
    print("Failed to get channel metadata with error: \(errorInfo.reason)")
} else if let getMetadataResponse = response, let metadata = getMetadataResponse.data {
    // Handle success and access the metadata
    print("Retrieved channel metadata: \(metadata)")
    for item in metadata.items ?? [] {
        print("Key: \(item.key), Value: \(item.value), Last updated by: \(item.authorUserId)")
    }
} else {
    // Handle unknown error
    print("Unknown error occurred while getting channel metadata.")
}
```

```swift tab="callback"
// callback
let channelName = "exampleChannel"
let channelType: AgoraRtmChannelType = .message

// Retrieve channel metadata
rtmClient.getChannelMetadata(
    channelName: channelName,
    channelType: channelType,
    completion: { (response, error) in
        if let errorInfo = error {
            // Handle error
            print("Failed to get channel metadata with error: \(errorInfo.reason)")
        } else if let getMetadataResponse = response, let metadata = getMetadataResponse.data {
            // Handle success and access the metadata
            print("Retrieved channel metadata: \(metadata)")
            for item in metadata.items ?? [] {
                print("Key: \(item.key), Value: \(item.value), Last updated by: \(item.authorUserId)")
            }
        } else {
            // Handle unknown error
            print("Unknown error occurred while getting channel metadata.")
        }
    }
)
```

## removeChannelMetadata [#removechannelmetadata]

### 接口描述 [#接口描述-2]

`removeChannelMetadata` 方法可以删除 Channel Metadata 或 Channel Metadata Item 数组。

删除时，配合版本属性可以控制本次调用是否开启版本号校验，逻辑如下：

- 版本属性默认为 `-1` ，本次调用不开启 CAS 验证。如果 Channel Metadata 或 Metadata Item 已存在，则 SDK 会删除该值；如果 Channel Metadata 或 Metadata Item 不存在，则 SDK 会返回错误码。
- 版本属性为正整数时，本次调用开启 CAS 验证。如果 Channel Metadata 或 Metadata Item 已存在，则 SDK 会在版本号验证成功后删除对应值；否则 SDK 会返回错误码。

成功删除 Channel Metadata 或 Metadata Item 后，订阅该频道且开启事件监听的用户会收到 `channel` 类型的 `didReceiveStorageEvent` 事件通知。详见[事件监听](/zh-CN/api-reference/rtm/swift/configuration#事件监听)。

### 接口方法 [#接口方法-4]

你可以通过以下方式调用 `removeChannelMetadata` 方法：

```swift
removeChannelMetadata(
    channelName: String,
    channelType: AgoraRtmChannelType,
    data: AgoraRtmMetadata,
    options: AgoraRtmMetadataOptions?,
    lock: String?
)   async -> (AgoraRtmCommonResponse?, AgoraRtmErrorInfo?)
```

```swift
removeChannelMetadata(
    channelName: String,
    channelType: AgoraRtmChannelType,
    data: AgoraRtmMetadata,
    options: AgoraRtmMetadataOptions?,
    lock: String?,
    completion completionBlock: AgoraRtmOperationBlock? = nil
)
```

| 参数 | 类型 | 必填 | 默认值 | 描述 |
| --- | --- | --- | --- | --- |
| `channelName` | String | 必填 | - | 频道名称。 |
| `channelType` | `AgoraRtmChannelType` | 必填 | - | 频道类型。详见 [`AgoraRtmChannelType`](/zh-CN/api-reference/rtm/swift/enumv#channeltype)。 |
| `data` | `AgoraRtmMetadata` | 必填 | - | Metadata Item。详见 [`AgoraRtmMetadata`](#agorartmmetadata)。 |
| `options` | `AgoraRtmMetadataOptions` | 选填 | - | Channel Metadata 配置选项。 |
| `lock` | String | 选填 | 空字符串 `''` | Lock 名称。设置后，只有调用 `acquireLock` 方法获取该锁的用户才能执行操作。 |
| `completion` | `AgoraRtmOperationBlock` | 选填 | - | [storage-swift-html-2-6-4 details](#table-slot-storage-swift-html-2-6-4) |

<a id="table-slot-storage-swift-html-2-6-4"></a>

**storage-swift-html-2-6-4 details**

调用结果回调：

- 调用成功：在 `response` 参数中返回 `AgoraRtmCommonResponse` 数据，在 `errorInfo` 参数中返回 `nil`。
- 调用失败：在 `response` 参数中返回 `nil`，在 `errorInfo` 参数中返回错误信息。

`AgoraRtmMetadataOptions` 数据类型包含以下属性：

| 属性           | 类型 | 是否必填 | 默认值  | 描述                      |
| ------------- | --- | ------ | ----- | ----------- |
| `recordTs`     | Bool |   选填   | `false` | 是否记录编辑的时间戳。    |
| `recordUserId` | Bool |   选填   | `false` | 是否记录编辑者的用户 ID。 |

### 基本用法 [#基本用法]

```swift tab="async-await"
// async-await
let channelName = "exampleChannel"
let channelType: AgoraRtmChannelType = .message
// Create metadata items to remove
let itemToRemove = AgoraRtmMetadataItem()
itemToRemove.key = "topic"
itemToRemove.revision = 174298200
// Create metadata object
let metadata = AgoraRtmMetadata()
metadata.majorRevision = 174298270
metadata.items = [itemToRemove]

// Call removeChannelMetadata with async/await
let (response, error) = await rtmClient.removeChannelMetadata(
    channelName: channelName,
    channelType: channelType,
    data: metadata,
    options: nil,
    lock: nil
)
if let errorInfo = error {
    // Handle error
    print("Failed to remove metadata with error: \(errorInfo.reason)")
} else if let removeMetadataResponse = response {
    // Handle success
    print("Metadata removed successfully.")
} else {
    // Handle unknown error
    print("Unknown error occurred while removing metadata.")
}
```

```swift tab="callback"
// callback
let channelName = "exampleChannel"
let channelType: AgoraRtmChannelType = .message
// Create metadata items to remove
let itemToRemove = AgoraRtmMetadataItem()
itemToRemove.key = "topic"
itemToRemove.revision = 174298200
// Create metadata object
let metadata = AgoraRtmMetadata()
metadata.majorRevision = 174298270
metadata.items = [itemToRemove]

// Call removeChannelMetadata with callback
rtmClient.removeChannelMetadata(
    channelName: channelName,
    channelType: channelType,
    data: metadata,
    options: nil,
    lock: nil
) { (response, error) in
    if let errorInfo = error {
        // Handle error
        print("Failed to remove metadata with error: \(errorInfo.reason)")
    } else if let removeMetadataResponse = response {
        // Handle success
        print("Metadata removed successfully.")
    } else {
        // Handle unknown error
        print("Unknown error occurred while removing metadata.")
    }
}
```

## updateChannelMetadata [#updatechannelmetadata]

### 接口描述 [#接口描述-3]

`updateChannelMetadata` 方法可以更新已有的 Channel Metadata。每次调用该方法，你可以更新一个 Channel Metadata，也可以更新一个或多个 Channel Metadata Item 数组。

成功更新后，订阅该频道且开启事件监听的用户会收到 `channel` 类型的 `didReceiveStorageEvent` 事件通知。详见[事件监听](/zh-CN/api-reference/rtm/swift/configuration#事件监听)。

:::info[信息]
该方法不能对不存在的 Metadata Item 进行操作。
:::

### 接口方法 [#接口方法-5]

你可以通过以下方式调用 `updateChannelMetadata` 方法：

```swift
updateChannelMetadata(
    channelName: String,
    channelType: AgoraRtmChannelType,
    data: AgoraRtmMetadata, options: AgoraRtmMetadataOptions?, lock: String?
)   async -> (AgoraRtmCommonResponse?, AgoraRtmErrorInfo?)
```

```swift
updateChannelMetadata(
    channelName: String,
    channelType: AgoraRtmChannelType,
    data: AgoraRtmMetadata,
    options: AgoraRtmMetadataOptions?,
    lock: String?,
    completion completionBlock: AgoraRtmOperationBlock? = nil
)
```

| 参数 | 类型 | 必填 | 默认值 | 描述 |
| --- | --- | --- | --- | --- |
| `channelName` | String | 必填 | - | 频道名称。 |
| `channelType` | `AgoraRtmChannelType` | 必填 | - | 频道类型。详见 [`AgoraRtmChannelType`](/zh-CN/api-reference/rtm/swift/enumv#channeltype)。 |
| `data` | `AgoraRtmMetadata` | 必填 | - | Metadata Item。详见 [`AgoraRtmMetadata`](#agorartmmetadata)。 |
| `options` | `AgoraRtmMetadataOptions` | 选填 | - | Channel Metadata 配置选项。 |
| `lock` | String | 选填 | 空字符串 `''` | Lock 名称。设置后，只有调用 `acquireLock` 方法获取该锁的用户才能执行操作。 |
| `completion` | `AgoraRtmOperationBlock` | 选填 | - | [storage-swift-html-3-6-4 details](#table-slot-storage-swift-html-3-6-4) |

<a id="table-slot-storage-swift-html-3-6-4"></a>

**storage-swift-html-3-6-4 details**

调用结果回调：

- 调用成功：在 `response` 参数中返回 `AgoraRtmCommonResponse` 数据，在 `errorInfo` 参数中返回 `nil`。
- 调用失败：在 `response` 参数中返回 `nil`，在 `errorInfo` 参数中返回错误信息。

`AgoraRtmMetadataOptions` 数据类型包含以下属性：

| 属性           | 类型 | 必填 | 默认值  | 描述                      |
| ------------- | -- | ------ | ----- | ----------- |
| `recordTs`     | Bool |   选填   | `false` | 是否记录编辑的时间戳。    |
| `recordUserId` | Bool |   选填   | `false` | 是否记录编辑者的用户 ID。 |

### 基本用法 [#基本用法-1]

```swift tab="async-await"
// async-await
let channelName = "exampleChannel"
let channelType: AgoraRtmChannelType = .message
// Create metadata items to update
let metadataItem = AgoraRtmMetadataItem()
metadataItem.key = "topic"
metadataItem.value = "New Topic"
metadataItem.revision = 174298200
// Create metadata object
let metadata = AgoraRtmMetadata()
metadata.majorRevision = 174298270
metadata.items = [metadataItem]
// Optional: Define metadata options if needed
let metadataOptions = AgoraRtmMetadataOptions()
metadataOptions.recordTs = true
metadataOptions.recordUserId = true

// Call updateChannelMetadata with async/await
let (response, error) = await rtmClient.updateChannelMetadata(
    channelName: channelName,
    channelType: channelType,
    data: metadata,
    options: metadataOptions,
    lock: nil
)
if let errorInfo = error {
    // Handle error
    print("Failed to update metadata with error: \(errorInfo.reason)")
} else if let updateMetadataResponse = response {
    // Handle success
    print("Metadata updated successfully.")
} else {
    // Handle unknown error
    print("Unknown error occurred while updating metadata.")
}
```

```swift tab="callback"
// callback
let channelName = "exampleChannel"
let channelType: AgoraRtmChannelType = .message
// Create metadata items to update
let metadataItem = AgoraRtmMetadataItem()
metadataItem.key = "topic"
metadataItem.value = "New Topic"
metadataItem.revision = 174298200
// Create metadata object
let metadata = AgoraRtmMetadata()
metadata.majorRevision = 174298270
metadata.items = [metadataItem]
// Optional: Define metadata options if needed
let metadataOptions = AgoraRtmMetadataOptions()
metadataOptions.recordTs = true
metadataOptions.recordUserId = true

// Call updateChannelMetadata with completion block (callback)
rtmClient.updateChannelMetadata(
    channelName: channelName,
    channelType: channelType,
    data: metadata,
    options: metadataOptions,
    lock: nil
) { (response, error) in
    if let errorInfo = error {
        // Handle error
        print("Failed to update metadata with error: \(errorInfo.reason)")
    } else if let updateMetadataResponse = response {
        // Handle success
        print("Metadata updated successfully.")
    } else {
        // Handle unknown error
        print("Unknown error occurred while updating metadata.")
    }
}
```

## setUserMetadata [#setusermetadata]

### 接口描述 [#接口描述-4]

`setUserMetadata` 方法可以设置 User Metadata。如果多次调用该方法时，SDK 会依次检索 User Metadata Item 的 `key` 值，并按如下规则处理：

- 如果设置的 Metadata Item key 值不同，则会根据调用顺序依次增加。
- 如果设置的 Metadata Item key 值相同，则最后一次设置的 Metadata 的 value 会覆盖之前的值。

成功设置 User Metadata 后，订阅该用户 Metadata 且开启事件监听的用户会收到 `user` 类型的 `didReceiveStorageEvent` 事件通知。详见[事件监听](/zh-CN/api-reference/rtm/swift/configuration#事件监听)。

User Metadata 同时也引进了版本控制逻辑 CAS，该方法提供两种独立的版本控制字段，你可以根据实际业务场景设置任意一种或多种：

- 通过 `AgoraRtmMetadata` 中的 `majorRevision` 属性开启整组 Channel Metadata 的版本号校验。
- 通过 `AgoraRtmMetadataItem` 中的 `revision` 属性开启某个 Metadata Item 的版本号校验。

设置 User Metadata 时，配合版本属性可以控制本次调用是否开启版本号校验，逻辑如下：

- 版本属性默认为 `-1` ，本次调用不开启 CAS 验证。如果 User Metadata 或 Metadata Item 已存在，则该值会被最新值覆盖；如果 User Metadata 或 Metadata Item 不存在，则会创建该值。
- 版本属性为正整数时，本次调用开启 CAS 验证。如果 User Metadata 或 Metadata Item 已存在，则 SDK 会在版本号验证成功后更新对应的值；否则 SDK 会返回错误码。

### 接口方法 [#接口方法-6]

你可以通过以下方式调用 `setUserMetadata` 方法：

```swift
setUserMetadata(
    userId: String,
    data: AgoraRtmMetadata,
    options: AgoraRtmMetadataOptions?
)   async -> (AgoraRtmCommonResponse?, AgoraRtmErrorInfo?)
```

```swift
setUserMetadata(
    userId: String,
    data: AgoraRtmMetadata,
    options: AgoraRtmMetadataOptions?,
    completion completionBlock: AgoraRtmOperationBlock? = nil
)
```

| 参数 | 类型 | 必填 | 默认值 | 描述 |
| --- | --- | --- | --- | --- |
| `userId` | String | 必填 | 当前用户的 `userId` | 用户 ID。 |
| `data` | `AgoraRtmMetadata` | 必填 | - | Metadata Item。详见 [`AgoraRtmMetadata`](#agorartmmetadata)。 |
| `options` | `AgoraRtmMetadataOptions` | 选填 | - | Channel Metadata 配置选项。 |
| `completion` | `AgoraRtmOperationBlock` | 选填 | - | [storage-swift-html-4-4-4 details](#table-slot-storage-swift-html-4-4-4) |

<a id="table-slot-storage-swift-html-4-4-4"></a>

**storage-swift-html-4-4-4 details**

调用结果回调：

- 调用成功：在 `response` 参数中返回 `AgoraRtmCommonResponse` 数据，在 `errorInfo` 参数中返回 `nil`。
- 调用失败：在 `response` 参数中返回 `nil`，在 `errorInfo` 参数中返回错误信息。

`AgoraRtmMetadataOptions` 数据类型包含以下属性：

| 属性           | 类型 | 是否必填 | 默认值  | 描述                      |
| ------------- | --- | ------- | ----- | ----------- |
| `recordTs`     | Bool | 选填     | `false` | 是否记录编辑的时间戳。    |
| `recordUserId` | Bool | 选填     | `false` | 是否记录编辑者的用户 ID。 |

### 基本用法 [#基本用法-2]

```swift tab="async-await"
// async-await
let userId = "exampleUser"
// Create metadata items to update
let metadataItem = AgoraRtmMetadataItem()
metadataItem.key = "status"
metadataItem.value = "active"
metadataItem.revision = 12345
// Create metadata object
let metadata = AgoraRtmMetadata()
metadata.majorRevision = 12346
metadata.items = [metadataItem]
// Optional: Define metadata options if needed
let metadataOptions = AgoraRtmMetadataOptions()
metadataOptions.recordTs = true
metadataOptions.recordUserId = true

// Call setUserMetadata with async/await
let (response, error) = await rtmClient.setUserMetadata(
    userId: userId,
    data: metadata,
    options: metadataOptions
)
if let errorInfo = error {
    // Handle error
    print("Failed to set user metadata with error: \(errorInfo.reason)")
} else if let setUserMetadataResponse = response {
    // Handle success
    print("User metadata set successfully.")
} else {
    // Handle unknown error
    print("Unknown error occurred while setting user metadata.")
}
```

```swift tab="callback"
// callback
let userId = "exampleUser"
// Create metadata items to update
let metadataItem = AgoraRtmMetadataItem()
metadataItem.key = "status"
metadataItem.value = "active"
metadataItem.revision = 12345
// Create metadata object
let metadata = AgoraRtmMetadata()
metadata.majorRevision = 12346
metadata.items = [metadataItem]
// Optional: Define metadata options if needed
let metadataOptions = AgoraRtmMetadataOptions()
metadataOptions.recordTs = true
metadataOptions.recordUserId = true

// Call setUserMetadata with a callback
rtmClient.setUserMetadata(
    userId: userId,
    data: metadata,
    options: metadataOptions
) { (response, error) in
    if let errorInfo = error {
        // Handle error
        print("Failed to set user metadata with error: \(errorInfo.reason)")
    } else if let setUserMetadataResponse = response {
        // Handle success
        print("User metadata set successfully.")
    } else {
        // Handle unknown error
        print("Unknown error occurred while setting user metadata.")
    }
}
```

## getUserMetadata [#getusermetadata]

### 接口描述 [#接口描述-5]

`getUserMetadata` 方法可以获取指定用户的 Metadata 和 User Metadata Item。

### 接口方法 [#接口方法-7]

你可以通过以下方式调用 `getUserMetadata` 方法：

```swift
getUserMetadata(userId: String) async -> (AgoraRtmGetMetadataResponse?, AgoraRtmErrorInfo?)
```

```swift
getUserMetadata(userId: String, completion completionBlock: AgoraRtmGetMetadataBlock? = nil)
```

| 参数 | 类型 | 必填 | 默认值 | 描述 |
| --- | --- | --- | --- | --- |
| `userId` | String | 必填 | 当前用户的 `userId` | 用户 ID。 |
| `completion` | `AgoraRtmGetMetadataBlock` | 选填 | - | [storage-swift-html-5-2-4 details](#table-slot-storage-swift-html-5-2-4) |

<a id="table-slot-storage-swift-html-5-2-4"></a>

**storage-swift-html-5-2-4 details**

调用结果回调：

- 调用成功：在 `response` 参数中返回 `AgoraRtmGetMetadataResponse` 数据，在 `errorInfo` 参数中返回 `nil`。
- 调用失败：在 `response` 参数中返回 `nil`，在 `errorInfo` 参数中返回错误信息。

`AgoraRtmGetMetadataResponse` 数据类型包含以下属性：

| 属性   | 类型                  | 描述   |
| ----- | ---------------- | ----- |
| `data` | `AgoraRtmMetadata` | Metadata Item。详见 [`AgoraRtmMetadata`](#agorartmmetadata)。 |

### 基本用法 [#基本用法-3]

```swift tab="async-await"
// async-await
let userId = "exampleUser"

// Call getUserMetadata with async/await
let (response, error) = await rtmClient.getUserMetadata(userId: userId)
if let errorInfo = error {
    // Handle error
    print("Failed to get user metadata with error: \(errorInfo.reason)")
} else if let getUserMetadataResponse = response {
    // Handle success and access the metadata
    if let metadata = getUserMetadataResponse.data {
        print("User metadata retrieved successfully.")
        for item in metadata.items ?? [] {
            print("Key: \(item.key), Value: \(item.value), Author: \(item.authorUserId), Revision: \(item.revision)")
        }
    }
} else {
    // Handle unknown error
    print("Unknown error occurred while getting user metadata.")
}
```

```swift tab="callback"
// callback
let userId = "exampleUser"

// Call getUserMetadata with a callback
rtmClient.getUserMetadata(userId: userId) { (response, error) in
    if let errorInfo = error {
        // Handle error
        print("Failed to get user metadata with error: \(errorInfo.reason)")
    } else if let getUserMetadataResponse = response {
        // Handle success and access the metadata
        if let metadata = getUserMetadataResponse.data {
            print("User metadata retrieved successfully.")
            for item in metadata.items ?? [] {
                print("Key: \(item.key), Value: \(item.value), Author: \(item.authorUserId), Revision: \(item.revision)")
            }
        }
    } else {
        // Handle unknown error
        print("Unknown error occurred while getting user metadata.")
    }
}
```

## removeUserMetadata [#removeusermetadata]

### 接口描述 [#接口描述-6]

`removeUserMetadata` 方法可以删除 User Metadata 或某几个 User Metadata Item。

成功删除后，订阅该用户 Metadata 且开启事件监听的用户会收到 `user` 类型的 `didReceiveStorageEvent` 事件通知。详见[事件监听](/zh-CN/api-reference/rtm/swift/configuration#事件监听)。

### 接口方法 [#接口方法-8]

你可以通过以下方式调用 `removeUserMetadata` 方法：

```swift
removeUserMetadata(
    userId: String,
    data: AgoraRtmMetadata,
    options: AgoraRtmMetadataOptions?
)   async -> (AgoraRtmCommonResponse?, AgoraRtmErrorInfo?)
```

```swift
removeUserMetadata(
    userId: String,
    data: AgoraRtmMetadata,
    options: AgoraRtmMetadataOptions?,
    completion completionBlock: AgoraRtmOperationBlock? = nil
)
```

| 参数 | 类型 | 必填 | 默认值 | 描述 |
| --- | --- | --- | --- | --- |
| `userId` | String | 必填 | 当前用户的 `userId` | 用户 ID。 |
| `data` | `AgoraRtmMetadata` | 必填 | - | Metadata Item。详见 [`AgoraRtmMetadata`](#agorartmmetadata)。 |
| `options` | `AgoraRtmMetadataOptions` | 选填 | - | Channel Metadata 配置选项。 |
| `completion` | `AgoraRtmOperationBlock` | 选填 | - | [storage-swift-html-6-4-4 details](#table-slot-storage-swift-html-6-4-4) |

<a id="table-slot-storage-swift-html-6-4-4"></a>

**storage-swift-html-6-4-4 details**

调用结果回调：

- 调用成功：在 `response` 参数中返回 `AgoraRtmCommonResponse` 数据，在 `errorInfo` 参数中返回 `nil`。
- 调用失败：在 `response` 参数中返回 `nil`，在 `errorInfo` 参数中返回错误信息。

`AgoraRtmMetadataOptions` 数据类型包含以下属性：

| 属性           | 类型 | 是否必填 | 默认值  | 描述                      |
| ------------- | --- | ------- | ------ | ----------- |
| `recordTs`     | Bool | 选填     | `false` | 是否记录编辑的时间戳。    |
| `recordUserId` | Bool | 选填     | `false` | 是否记录编辑者的用户 ID。 |

### 基本用法 [#基本用法-4]

```swift tab="async-await"
// async-await
let userId = "exampleUser"
// Create metadata items to remove
let metadataItem = AgoraRtmMetadataItem()
metadataItem.key = "status"
metadataItem.revision = 12345                   // Make sure to provide the correct revision
// Create metadata object
let metadata = AgoraRtmMetadata()
metadata.majorRevision = 12346
metadata.items = [metadataItem]
// Call removeUserMetadata with async/await
let (response, error) = await rtmClient.removeUserMetadata(
    userId: userId,
    data: metadata,
    options: nil
)

if let errorInfo = error {
    // Handle error
    print("Failed to remove user metadata with error: \(errorInfo.reason)")
} else if let removeUserMetadataResponse = response {
    // Handle success
    print("User metadata removed successfully.")
} else {
    // Handle unknown error
    print("Unknown error occurred while removing user metadata.")
}
```

```swift tab="callback"
// callback
let userId = "exampleUser"

// Create metadata items to remove
let metadataItem = AgoraRtmMetadataItem()
metadataItem.key = "status"
metadataItem.revision = 12345                 // Make sure to provide the correct revision

// Create metadata object
let metadata = AgoraRtmMetadata()
metadata.majorRevision = 12346
metadata.items = [metadataItem]

// Call removeUserMetadata with a callback
rtmClient.removeUserMetadata(userId: userId, data: metadata, options: nil) { (response, error) in
    if let errorInfo = error {
        // Handle error
        print("Failed to remove user metadata with error: \(errorInfo.reason)")
    } else if let removeUserMetadataResponse = response {
        // Handle success
        print("User metadata removed successfully.")
    } else {
        // Handle unknown error
        print("Unknown error occurred while removing user metadata.")
    }
}
```

## updateUserMetadata [#updateusermetadata]

### 接口描述 [#接口描述-7]

`updateUserMetadata` 方法可以更新已有的 User Metadata 或 Metadata Item。成功更新后，订阅该 User Metadata 且开启事件监听的用户会收到 `user` 类型的 `didReceiveStorageEvent` 事件通知。详见[事件监听](/zh-CN/api-reference/rtm/swift/configuration#事件监听)。

:::info[信息]
该方法不能对不存在的 Metadata Item 进行操作。
:::

### 接口方法 [#接口方法-9]

你可以通过以下方式调用 `updateUserMetadata` 方法：

```swift
updateUserMetadata(
    userId: String,
    data: AgoraRtmMetadata,
    options: AgoraRtmMetadataOptions?
)   async -> (AgoraRtmCommonResponse?, AgoraRtmErrorInfo?)
```

```swift
updateUserMetadata(
    userId: String,
    data: AgoraRtmMetadata,
    options: AgoraRtmMetadataOptions?,
    completion completionBlock: AgoraRtmOperationBlock? = nil
)
```

| 参数 | 类型 | 必填 | 默认值 | 描述 |
| --- | --- | --- | --- | --- |
| `userId` | String | 必填 | 当前用户的 `userId` | 用户 ID。 |
| `data` | `AgoraRtmMetadata` | 必填 | - | Metadata Item。详见 [`AgoraRtmMetadata`](#agorartmmetadata)。 |
| `options` | `AgoraRtmMetadataOptions` | 选填 | - | Channel Metadata 配置选项。 |
| `completion` | `AgoraRtmOperationBlock` | 选填 | - | [storage-swift-html-7-4-4 details](#table-slot-storage-swift-html-7-4-4) |

<a id="table-slot-storage-swift-html-7-4-4"></a>

**storage-swift-html-7-4-4 details**

调用结果回调：

- 调用成功：在 `response` 参数中返回 `AgoraRtmCommonResponse` 数据，在 `errorInfo` 参数中返回 `nil`。
- 调用失败：在 `response` 参数中返回 `nil`，在 `errorInfo` 参数中返回错误信息。

`AgoraRtmMetadataOptions` 数据类型包含以下属性：

| 属性           | 类型 | 是否必填 | 默认值  | 描述                      |
| ------------- | --- | ------ | ----- | ----------- |
| `recordTs`     | Bool |   选填   | `false` | 是否记录编辑的时间戳。    |
| `recordUserId` | Bool |   选填   | `false` | 是否记录编辑者的用户 ID。 |

### 基本用法 [#基本用法-5]

```swift tab="async-await"
// async-await
let userId = "exampleUser"
// Create metadata items to update
let metadataItem = AgoraRtmMetadataItem()
metadataItem.key = "status"
metadataItem.value = "active"        // Set the new value
metadataItem.revision = 12345        // Provide the current revision
// Create metadata object
let metadata = AgoraRtmMetadata()
metadata.majorRevision = 12346
metadata.items = [metadataItem]
// Optional: Define metadata options if needed
let metadataOptions = AgoraRtmMetadataOptions()
metadataOptions.recordTs = true
metadataOptions.recordUserId = true

// Call updateUserMetadata with async/await
let (response, error) = await rtmClient.updateUserMetadata(
    userId: userId,
    data: metadata,
    options: metadataOptions
)
if let errorInfo = error {
    // Handle error
    print("Failed to update user metadata with error: \(errorInfo.reason)")
} else if let updateUserMetadataResponse = response {
    // Handle success
    print("User metadata updated successfully.")
} else {
    // Handle unknown error
    print("Unknown error occurred while updating user metadata.")
}
```

```swift tab="callback"
// callback
let userId = "exampleUser"
// Create metadata items to update
let metadataItem = AgoraRtmMetadataItem()
metadataItem.key = "status"
metadataItem.value = "active"        // Set the new value
metadataItem.revision = 12345        // Provide the current revision
// Create metadata object
let metadata = AgoraRtmMetadata()
metadata.majorRevision = 12346
metadata.items = [metadataItem]
// Optional: Define metadata options if needed
let metadataOptions = AgoraRtmMetadataOptions()
metadataOptions.recordTs = true
metadataOptions.recordUserId = true

// Call updateUserMetadata with a callback
rtmClient.updateUserMetadata(userId: userId, data: metadata, options: metadataOptions) { (response, error) in
    if let errorInfo = error {
        // Handle error
        print("Failed to update user metadata with error: \(errorInfo.reason)")
    } else if let updateUserMetadataResponse = response {
        // Handle success
        print("User metadata updated successfully.")
    } else {
        // Handle unknown error
        print("Unknown error occurred while updating user metadata.")
    }
}
```

## subscribeUserMetadata [#subscribeusermetadata]

### 接口描述 [#接口描述-8]

`subscribeUserMetadata` 方法可以订阅指定用户的 Metadata。成功订阅且开启事件监听后，当该用户的 Metadata 发生变更时会收到 `user` 类型的 `didReceiveStorageEvent` 事件通知。详见[事件监听](/zh-CN/api-reference/rtm/swift/configuration#事件监听)。

### 接口方法 [#接口方法-10]

你可以通过以下方式调用 `subscribeUserMetadata` 方法：

```swift
subscribeUserMetadata(userId: String) async -> (AgoraRtmCommonResponse?, AgoraRtmErrorInfo?)
```

```swift
subscribeUserMetadata(userId: String, completion completionBlock: AgoraRtmOperationBlock? = nil)
```

| 参数 | 类型 | 必填 | 默认值 | 描述 |
| --- | --- | --- | --- | --- |
| `userId` | String | 必填 | 当前用户的 `userId` | 用户 ID。 |
| `completion` | `AgoraRtmOperationBlock` | 选填 | - | [storage-swift-html-8-2-4 details](#table-slot-storage-swift-html-8-2-4) |

<a id="table-slot-storage-swift-html-8-2-4"></a>

**storage-swift-html-8-2-4 details**

调用结果回调：

- 调用成功：在 `response` 参数中返回 `AgoraRtmCommonResponse` 数据，在 `errorInfo` 参数中返回 `nil`。
- 调用失败：在 `response` 参数中返回 `nil`，在 `errorInfo` 参数中返回错误信息。

### 基本用法 [#基本用法-6]

```swift tab="async-await"
// async-await
let userId = "exampleUser"

// Call subscribeUserMetadata with async/await
let (response, error) = await rtmClient.subscribeUserMetadata(userId: userId)
if let errorInfo = error {
    // Handle error
    print("Failed to subscribe to user metadata with error: \(errorInfo.reason)")
} else if let subscribeResponse = response {
    // Handle success
    print("Successfully subscribed to user metadata.")
} else {
    // Handle unknown error
    print("Unknown error occurred while subscribing to user metadata.")
}
```

```swift tab="callback"
// callback
let userId = "exampleUser"

// Call subscribeUserMetadata with a callback
rtmClient.subscribeUserMetadata(userId: userId) { (response, error) in
    if let errorInfo = error {
        // Handle error
        print("Failed to subscribe to user metadata with error: \(errorInfo.reason)")
    } else if let subscribeResponse = response {
        // Handle success
        print("Successfully subscribed to user metadata.")
    } else {
        // Handle unknown error
        print("Unknown error occurred while subscribing to user metadata.")
    }
}
```

## unsubscribeUserMetadata [#unsubscribeusermetadata]

### 接口描述 [#接口描述-9]

如果你不需要接收某个用户 User Metadata 的变更通知，调用 `unsubscribeUserMetadata` 方法取消订阅。

### 接口方法 [#接口方法-11]

你可以通过以下方式调用 `unsubscribeUserMetadata` 方法：

```swift
unsubscribeUserMetadata(userId: String) async -> (AgoraRtmCommonResponse?, AgoraRtmErrorInfo?)
```

```swift
unsubscribeUserMetadata(userId: String, completion completionBlock: AgoraRtmOperationBlock? = nil)
```

| 参数 | 类型 | 必填 | 默认值 | 描述 |
| --- | --- | --- | --- | --- |
| `userId` | String | 必填 | 当前用户的 `userId` | 用户 ID。 |
| `completion` | `AgoraRtmOperationBlock` | 选填 | - | [storage-swift-html-9-2-4 details](#table-slot-storage-swift-html-9-2-4) |

<a id="table-slot-storage-swift-html-9-2-4"></a>

**storage-swift-html-9-2-4 details**

调用结果回调：

- 调用成功：在 `response` 参数中返回 `AgoraRtmCommonResponse` 数据，在 `errorInfo` 参数中返回 `nil`。
- 调用失败：在 `response` 参数中返回 `nil`，在 `errorInfo` 参数中返回错误信息。

### 基本用法 [#基本用法-7]

```swift tab="async-await"
// async-await
let userId = "exampleUser"

// Call unsubscribeUserMetadata with async/await
let (response, error) = await rtmClient.unsubscribeUserMetadata(userId: userId)
if let errorInfo = error {
    // Handle error
    print("Failed to unsubscribe from user metadata with error: \(errorInfo.reason)")
} else if let unsubscribeResponse = response {
    // Handle success
    print("Successfully unsubscribed from user metadata.")
} else {
    // Handle unknown error
    print("Unknown error occurred while unsubscribing from user metadata.")
}
```

```swift tab="callback"
// callback
let userId = "exampleUser"

// Call unsubscribeUserMetadata with a callback
rtmClient.unsubscribeUserMetadata(userId: userId) { (response, error) in
    if let errorInfo = error {
        // Handle error
        print("Failed to unsubscribe from user metadata with error: \(errorInfo.reason)")
    } else if let unsubscribeResponse = response {
        // Handle success
        print("Successfully unsubscribed from user metadata.")
    } else {
        // Handle unknown error
        print("Unknown error occurred while unsubscribing from user metadata.")
    }
}
```

## AgoraRtmMetadata [#agorartmmetadata]

设置和管理 Metadata 的数据结构。包含以下属性：

| 方法 | 描述 |
| --- | --- |
| <code className="index-group-item-metadata index-api-metadatainit" id="metadatainit">init</code> | <span class="index-desc-metadatainit">禁止不填参数就初始化 `AgoraRtmMetadata` 实例。</span> |

| 属性 | 类型 | 是否必填 | 默认值 | 描述 |
| --- | --- | --- | --- | --- |
| `majorRevision` | Int64 | 选填 | `-1` | [storage-swift-html-11-1-4 details](#table-slot-storage-swift-html-11-1-4) |
| `items` | `[AgoraRtmMetadataItem]` | 选填 | `nil` | 设置 Metadata Item。 |

<a id="table-slot-storage-swift-html-11-1-4"></a>

**storage-swift-html-11-1-4 details**

设置版本控制开关：

- `-1`: 关闭版本校验。
- > `0`: 开启版本校验，只有目标版本号与此值相符才能执行操作。

`AgoraRtmMetadataItem` 数据类型包含以下属性：

| 属性 | 类型 | 是否必填 | 默认值 | 描述 |
| --- | --- | --- | --- | --- |
| `key` | String | 必填 | - | 键。 |
| `value` | String | 必填 | - | 值。 |
| `authorUserId` | String | 必填 | - | 编辑者的用户 ID。该值为只读，不支持写入。 |
| `revision` | Int64 | 选填 | `-1` | [storage-swift-html-12-4-4 details](#table-slot-storage-swift-html-12-4-4) |
| `updateTs` | UInt64 | 选填 | `0` | 更新时间戳。该值为只读，不支持写入。 |

<a id="table-slot-storage-swift-html-12-4-4"></a>

**storage-swift-html-12-4-4 details**

- 在读取操作时作为真实版本号返回。
- 在写入操作时作为版本控制开关：
  -  `-1`: 关闭版本校验。
  - > `0`: 开启版本校验，只有目标版本号与此值相符才执行操作。
