---
source_url: https://www.pubnub.com/docs/chat/swift-chat-sdk/build/features/messages/updates
title: Manage message updates
updated_at: 2026-06-16T12:48:54.838Z
---

> 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


# Manage message updates

Edit messages and receive real-time update events.

:::note Requires Message Persistence
Enable [Message Persistence](https://youtu.be/qLMtbINWGig) in the [Admin Portal](https://admin.pubnub.com/).
:::

## Edit messages

`editText()` replaces an existing message's content.

### Method signature

This method takes the following parameters:

```swift
message.editText(
    newText: String
) async throws -> MessageImpl
```

#### Input

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| newText | String | Yes |  | New/updated text that you want to add in place of the existing message. |

#### Output

| Parameter | Description |
| --- | --- |
| `MessageImpl` | An updated message instance with an added `edited` action type. |

### Sample code

:::tip Sample code
The code samples in Swift Chat SDK focus on asynchronous code execution.
You can also write synchronous code as the parameters are shared between the async and sync methods but we don't provide usage examples of such.
:::

Correct the number of the support ticket you sent to `78398`.

```swift
// Assumes a "ChatImpl" reference named "chat"
Task {
  if let channel = try await chat.getChannel(channelId: "support") {
    let timetoken: Timetoken = 16200000000000000
    if let message = try await channel.getMessage(timetoken: timetoken) {
      let updatedMessage = try await message.editText(newText: "Your ticket number is 78398")
      debugPrint("Message updated successfully")
      debugPrint("Updated message: \(updatedMessage)")
    } else {
      debugPrint("Message not found")
    }
  } else {
    debugPrint("Channel not found")
  }
}
```

## Get message updates

Receive real-time updates when messages or [reactions](https://www.pubnub.com/docs/chat/swift-chat-sdk/build/features/messages/reactions) change with `onUpdated()`. You can also use `message.stream.updates()` for an `AsyncStream`-based approach.

For monitoring multiple messages at once, `streamUpdatesOn()` remains available.

:::note Deprecation
`streamUpdates()` is deprecated. Use `onUpdated()` (closure-based) or `message.stream.updates()` (AsyncStream-based) instead.
:::

### Method signature

* onUpdated() — closure called when the message changes 1message.onUpdated(2 callback: @escaping (MessageImpl) -> Void3) -> AutoCloseable
* streamUpdatesOn() (static) — monitors multiple messages 1MessageImpl.streamUpdatesOn(2 messages: [MessageImpl]3) -> AsyncStream<[MessageImpl]>

#### Input

| Parameter | Description |
| --- | --- |
| `callback` (in `onUpdated`) *Type: `(MessageImpl) -> Void`Default: n/a | Closure called with the updated message whenever it changes (edits, reactions, etc.). |
| `messages` (in `streamUpdatesOn`) *Type: `[MessageImpl]`Default: n/a | A collection of [MessageImpl objects](https://www.pubnub.com/docs/chat/swift-chat-sdk/learn/chat-entities/message) for which you want to get updates on changed messages or message reactions. |

#### Output

| Parameter | Description |
| --- | --- |
| `AutoCloseable` | An object you must retain. When released or closed, the listener stops. |

### Sample code

:::tip Sample code
The code samples in Swift Chat SDK focus on asynchronous code execution.
You can also write synchronous code as the parameters are shared between the async and sync methods but we don't provide usage examples of such.
:::

Get message and message reaction-related updates for the message with the timetoken `16200000000000000` published on the `support` channel.

###### Closure

```swift
// Assumes a "MessageImpl" reference named "message"
  
// Important: Keep a strong reference to the returned "AutoCloseable" object as long as you want
// to receive updates. If the "AutoCloseable" is deallocated, the stream will be cancelled,
// and no further items will be produced. You can also stop receiving updates manually
// by calling the "close()" method on the "AutoCloseable" object.
autoCloseable = message.streamUpdates { updatedMessage in
  debugPrint("Received update for message with timetoken: \(updatedMessage.timetoken)")
}
```

###### AsyncStream

```swift
// Assumes a "ChatImpl" reference named "chat"
let timetoken: Timetoken = 16200000000000000
Task {
  if let channel = try await chat.getChannel(channelId: "support") {
    if let message = try await channel.getMessage(timetoken: timetoken) {
      for await updatedMessage in message.streamUpdates() {
        debugPrint("Received update for message with timetoken: \(updatedMessage.timetoken)")
      }
    } else {
      debugPrint("Message not found")
    }
  } else {
    debugPrint("Channel not found")
  }
}
```

#### Watch multiple messages

Get updates on multiple message objects at once.

##### Closure

```swift
// Assumes an array of "MessageImpl" objects named "messages"
  
// Important: Keep a strong reference to the returned "AutoCloseable" object as long as you want
// to receive new updates. If the "AutoCloseable" is deallocated, the stream will be cancelled,
// and no further items will be produced. You can also stop receiving updates manually
// by calling the "close()" method on the "AutoCloseable" object.
autoCloseable = MessageImpl.streamUpdatesOn(messages: messages) { updatedMessages in
  debugPrint("Received updates for messages")
  for updatedMessage in updatedMessages {
    debugPrint("Message with timetoken \(updatedMessage.timetoken) updated")
  }
}
```

##### AsyncStream

```swift
// Assumes a "ChatImpl" reference named "chat"
Task {
  if let channel = try await chat.getChannel(channelId: "support") {
    let messages = try await channel.getHistory().messages
    if !messages.isEmpty {
      for await updatedMessages in MessageImpl.streamUpdatesOn(messages: messages) {
        updatedMessages.forEach { updatedMessage in
          debugPrint("Message with timetoken \(updatedMessage.timetoken) updated")
        }
      }
    }
  } else {
    debugPrint("Channel not found")
  }
}
```