# SDK quickstart (/en/realtime-media/im/get-started-sdk/ios)

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

Instant messaging enhances user engagement by enabling users to connect and form a community within the app. Increased engagement can lead to increased user satisfaction and loyalty to your app. An instant messaging feature can also provide real-time support to users, allowing them to get help and answers to their questions quickly. The Chat SDK enables you to embed real-time messaging in any app, on any device, anywhere.

This page guides you through implementing peer-to-peer messaging into your app using the Chat SDK.

## Understand the tech [#understand-the-tech]

The following figure shows the workflow of sending and receiving peer-to-peer messages using Chat SDK.

<details>
  <summary>
    Chat SDK workflow
  </summary>

  ![understand](https://assets-docs.agora.io/images/im/get-started-sdk-understand.png)
</details>

1. Clients retrieve an authentication token from your app server.
2. Users log in to Chat using the App ID, their user ID, and token.
3. Clients send and receive messages through Chat as follows:
   1. Client A sends a message to Client B. The message is sent to the Agora Chat server.
   2. The server delivers the message to Client B. When Client B receives a message, the SDK triggers an event.
   3. Client B listens for the event to read and display the message.

## Prerequisites [#prerequisites]

In order to follow the procedure on this page, you must have:

* A valid [Agora account](/en/realtime-media/im/get-started/manage-agora-account#create-an-agora-account).
* An [Agora project](/en/realtime-media/im/get-started/manage-agora-account#create-an-agora-project) for which you have [enabled Chat](./enable#enable-).
* The [App ID](./enable#get-chat-project-information) for the project.
* Internet access.

  Ensure that no firewall is blocking your network communication.

      
  
      
    * Xcode. This page uses Xcode 13.0 as an example.
    * A device running iOS 10 or later.

    
  
      
  
      
  
      
  
      
  
      
  
## Project setup [#project-setup]

      
  
      
    To integrate Chat into your app, do the following:

    1. [Create a new project](https://help.apple.com/xcode/mac/current/#/dev07db0e578) for this device app using the **App** template. Select the **Storyboard** Interface and **Swift** Language.

       If you have not already added team information, click &#x2A;*Add account…**, input your Apple ID, then click **Next**.

    2. [Enable automatic signing](https://help.apple.com/xcode/mac/current/#/dev23aab79b4) for your project.
       [Set the target devices](https://help.apple.com/xcode/mac/current/#/deve69552ee5) to deploy your iOS app to an iPhone or iPad.

    3. Add project permissions for microphone and camera usage:

       1. Open **Info** in the project navigation panel, then add the following properties to the [Information Property List](https://help.apple.com/xcode/mac/current/#/dev3f399a2a6):

          | Key                          | Type   | Value                  |
          | ---------------------------- | ------ | ---------------------- |
          | NSMicrophoneUsageDescription | String | Access the microphone. |
          | NSCameraUsageDescription     | String | Access the camera.     |

    4. Integrate Agora Chat SDK into your project:

       1. In Xcode, click **File** > &#x2A;*Add Packages...**, then paste the following link in the search:

          ```
          https://github.com/AgoraIO/AgoraChat_iOS.git
          ```

          You see the available Agora packages. In **AgoraChat\_iOS**, specify the latest Chat SDK version, for example `1.0.9`. You can obtain the latest version information in the [release notes](./reference/release-notes).

       2. Click **Add Package**. In the new window, click **Add Package**.

          You see **AgoraChat** in **Package Dependencies** for your project.

    <CalloutContainer type="warning">
      <CalloutDescription>
        The [privacy updates for App Store submissions](https://developer.apple.com/news/?id=r1henawx) released by Apple, require developers to declare approved reasons for using a set of APIs in their app’s privacy manifest. Agora provides a [`PrivacyInfo.xcprivacy`](https://download.agora.io/sdk/release/AgoraChat_PrivacyInfo.xcprivacy) file that you can include in your project. If you are using Chat SDK 1.2 or earlier, refer to [Add a privacy manifest file](#add-a-privacy-manifest-file) for details.
      </CalloutDescription>
    </CalloutContainer>

    
  
      
  
      
  
      
  
      
  
      
  
## Implement peer-to-peer messaging [#implement-peer-to-peer-messaging]

This section shows how to use the Chat SDK to implement peer-to-peer messaging in your app, step by step.

      
  
      
    ### Create the UI [#create-the-ui-1]

    In the quickstart app, you create a simple UI that consists of the following elements:

    * A `UIButton` to log in or out of the Chat.
    * A `UITextField` box to specify the recipient user ID.
    * A `UITextField` box to enter a text message.
    * A `UIButton` to send the text message.
    * A `UITextView` to display sent and received messages.

    To create this user interface, in the `ViewController` class:

    1. **Add the UI elements you need**

       Add the following declarations at the top of the class.

       ```swift
       var btnJoinLeave: UIButton!
       var etRecipient: UITextField!
       var scrollView: UITextView!
       var etMessageText: UITextField!
       var btnSendMessage: UIButton!
       ```

    2. **Configure the UI elements in your interface**

       Add the following below `super.viewDidLoad()` inside the `viewDidLoad` method:

       ```swift
       btnJoinLeave = UIButton(type: .system)
       btnJoinLeave.frame = CGRect(x: 60, y: 100, width: 250, height: 30)
       btnJoinLeave.setTitle("Join", for: .normal)
       btnJoinLeave.addTarget(self, action: #selector(joinLeave), for: .touchUpInside)
       self.view.addSubview(btnJoinLeave)

       etRecipient = UITextField(frame: CGRect(x: 100, y: 150, width: 300, height: 30))
       etRecipient.placeholder = "Enter recipient user ID"
       self.view.addSubview(etRecipient)

       scrollView = UITextView(frame: CGRect(x: 130, y: 200, width: 300, height: 100))
       scrollView.isEditable = false
       self.view.addSubview(scrollView)

       etMessageText = UITextField(frame: CGRect(x: 80, y: 320, width: 200, height: 30))
       etMessageText.placeholder = "Message"
       self.view.addSubview(etMessageText)

       btnSendMessage = UIButton(type: .system)
       btnSendMessage.frame = CGRect(x: 270, y: 320, width: 80, height: 30)
       btnSendMessage.setTitle(">>", for: .normal)
       btnSendMessage.addTarget(self, action: #selector(sendMessage), for: .touchUpInside)
       self.view.addSubview(btnSendMessage)
       ```

    ### Handle the system logic [#handle-the-system-logic-1]

    Import the necessary classes, and add a method to show status updates to the user.

    1. **Import the Chat SDK class**

       In `ViewController`, add the provided code sample after `import UIKit`:

       ```swift
       import AgoraChat
       ```

    If Xcode does not recognize this import, click **File** > **Packages** > **Reset Package Caches**.

    2. **Log events and show status updates to your users**

       In `ViewController`, add the following method after the `viewDidLoad` function:

       ```swift
       func showLog(_ text: String) -> Void {
           DispatchQueue.main.async {
               let alert = UIAlertController(title: "", message: text, preferredStyle: .alert)
               self.present(alert, animated: true)
               alert.dismiss(animated: true, completion: nil)
           }
       }
       ```

    ### Send and receive messages [#send-and-receive-messages-1]

    When a user opens the app, you instantiate and initialize a `ChatClient`. When the user taps the **Join** button, the app logs in to the Chat. When a user types a message in the text box and then presses **Send**, the typed message is sent to the Chat. When the app receives a message from the server, the message is displayed in the message list. This simple workflow enables you to rapidly build a Chat client with basic functionality.

    To implement this workflow in your app, take the following steps:

    1. **Declare variables**

       In the `ViewController` class, add the following declarations at the top:

       ```swift
       var userId = "<User ID of the local user>"
       var token = "<Your authentication token>"
       var appId = "<App ID from Agora console>"

       var agoraChatClient: AgoraChatClient!
       var isJoined: Bool = false
       ```

    2. **Set up Chat when the app starts**

       When the app starts, you create an instance of the `AgoraChatClient`. To do this, add the following to `viewDidLoad`:

       ```swift
       setupChatClient()  // Initialize the ChatClient
       ```

    3. **Instantiate the `AgoraChatClient`**

       To implement peer-to-peer messaging, you use Chat SDK to initialize an `AgoraChatClient` instance. In the `ViewController` class, add the following method after the `viewDidLoad` function:

       ```swift
       func setupChatClient() {
           if (appId.isEmpty) {
               showLog("You need to set your App ID")
               return
           }
           let options = AgoraChatOptions(appId: appId)  // Create AgoraChatOptions with your App ID
           agoraChatClient = AgoraChatClient.shared()
           options.enableConsoleLog = true  // Enable printing logs on console
           agoraChatClient.initializeSDK(with: options)  // Initialize the AgoraChatClient
           agoraChatClient.chatManager?.add(self, delegateQueue: nil)  // Adds the chat delegate to receive messages
       }
       ```

    4. **Handle and respond to Chat events**

       The `AgoraChatClientDelegate` implements callbacks to receive notification of Chat events such as a connection state change, and a token expiration. The `AgoraChatManagerDelegate` implements a callback to handle the receival of messages. When you receive the `messagesDidReceive` notification, you display the message to the user.

       To handle these events, add the following extensions to the `ViewController`:

       ```swift
       // Add message event callbacks
       extension ViewController: AgoraChatManagerDelegate {
           func messagesDidReceive(_ aMessages: [AgoraChatMessage]) {
               for message in aMessages {
                   let msgBody = message.body as! AgoraChatTextMessageBody

                   DispatchQueue.main.async {
                       self.displayMessage(messageText: msgBody.text, isSentMessage: false)
                   }

                   showLog("Received a message from \(message.from)")
               }
           }
       }

       // Add connection event callbacks
       extension ViewController: AgoraChatClientDelegate {
           func connectionStateDidChange(_ aConnectionState: AgoraChatConnectionState) {
               if aConnectionState == .connected {
                   showLog("Connected to the chat server.")
               } else {
                   if isJoined {
                       showLog("Disconnected from the chat server.")
                       isJoined = false
                   }
               }
           }

           func tokenWillExpire(_ aErrorCode: AgoraChatErrorCode) {
               showLog("Token will expire (log in using new token)")
           }

           func tokenDidExpire(_ aErrorCode: AgoraChatErrorCode) {
               showLog("Token expired (log in using new token)")
           }
       }
       ```

    5. **Log in to the Chat**

       When a user presses **Join**, your app logs in to the Chat. When a user presses **Leave**, the app logs out of the Chat.

       To implement this logic, put the following method to the `ViewController`:

       ```swift
       @objc func joinLeave() {
           if (isJoined) {
               let result: AgoraChatError? = agoraChatClient.logout(true)
               guard result == nil else {
                   showLog(result!.errorDescription)
                   return
               }

               showLog("Signed out")
               DispatchQueue.main.async {
                   self.btnJoinLeave.setTitle("Join", for: .normal)
                   self.isJoined = false
               }
           } else {
               let result: AgoraChatError? = agoraChatClient.login(withUsername: userId, token: token)
               guard result == nil else {
                   if (result!.code.rawValue == 200) {  // Already joined
                       isJoined = true
                       showLog("Already signed in")
                       DispatchQueue.main.async {
                           self.btnJoinLeave.setTitle("Leave", for: .normal)
                       }
                   } else {
                       showLog(result!.errorDescription)
                   }
                   return
               }

               showLog("Signed in")
               isJoined = true

               DispatchQueue.main.async {
                   self.btnJoinLeave.setTitle("Leave", for: .normal)
               }
           }
       }
       ```

    6. **Send a message**

       To send a message to the Chat when a user presses the **Send** button, perform the following steps:

       1. Add the following method to the `ViewController` class before the `viewDidLoad` function:

          ```swift
            @objc func sendMessage() {
                // Read the recipient name from the EditText box
                let toSendName = etRecipient.text!.trimmingCharacters(in: .whitespaces)
                let content = etMessageText.text!.trimmingCharacters(in: .whitespaces)

                if (toSendName.isEmpty || content.isEmpty) {
                    showLog("Enter a recipient name and a message.")
                    return
                }

                // Create a ChatMessage
                let message = AgoraChatMessage(
                    conversationID: toSendName,
                    from: agoraChatClient.currentUsername!,
                    to: toSendName,
                    body: AgoraChatTextMessageBody(text: content),
                    ext: nil
                )

                // Send the message
                agoraChatClient.chatManager?.send(message, progress: nil) { _, err in
                    if let err = err {
                        self.showLog("Error occurred when sending the message. \(err.errorDescription)")
                    } else {
                        self.showLog("Message sent successfully.")
                        DispatchQueue.main.async {
                            self.displayMessage(messageText: content, isSentMessage: true)
                            self.etMessageText.text = ""
                        }
                    }
                }
            }
          ```

    7. **Display chat messages**

       To display the messages the current user has sent and received in your app, add the following method to the `ViewController` class:

       ```swift
       func displayMessage(messageText: String, isSentMessage: Bool) {
           DispatchQueue.main.async {
               self.scrollView.text.append(
                   DateFormatter.localizedString(from: Date.now, dateStyle: .none, timeStyle: .medium)
                   + ":  " + String(reflecting: messageText) + "\r\n"
               )
               self.scrollView.scrollRangeToVisible(NSRange(location: self.scrollView.text.count, length: 1))
           }
       }
       ```

    
  
      
  
      
  
      
  
      
  
      
  
## Test your implementation [#test-your-implementation]

To ensure that you have implemented Peer-to-Peer Messaging in your app:

      
  
      
    1. Create an app instance for the first user:

       1. [Register a user](./enable#register-a-user) in [Agora Console](https://console.agora.io/v2) and [Generate a user token](./enable#generate-a-user-token).

       2. In the `ViewController` class, update `userId`, `token`, and `appId` with values from Agora Console.  To get your App ID, see [Get Chat project information](./enable#get-chat-project-information).

       3. Connect a physical device to your development device.

       4. In Xcode, click **Run app**. A moment later you see the project installed on your device.

    2. Create an app instance for the second user:

       1. Register a second user in Agora Console and generate a user token.

       2. In the `ViewController` class, update `userId` and `token` with values for the second user. Make sure you use the same `appId` as for the first user.

       3. Run the modified app on a device emulator or a second physical device.

    3. On each device, click **Join** to log in to the Chat.

    4. Edit the recipient name on each device to show the user ID of the user logged in to the other device.

    5. Type a message in the **Message*&#x2A; box of either device and press &#x2A;*`>>`**.

       The message is sent and appears on the other device.

    6. Press **Leave** to log out of the Chat.

    
  
      
  
      
  
      
  
      
  
      
  
## Reference [#reference]

This section contains content that completes the information in this page, or points you to documentation that explains other aspects to this product.

* For more code samples, see [Samples and demos](./downloads).

      
  
      
    ### Integrate the SDK through CocoaPods [#integrate-the-sdk-through-cocoapods]

    1. Install CocoaPods. For details, see [Getting Started with CocoaPods](https://guides.cocoapods.org/using/getting-started.html#getting-started).

    2. In the Terminal, navigate to the project root directory and run the `pod init` command to create a text file `Podfile` in the project folder.

    3. Open the `Podfile` file and add the Agora Chat SDK. Remember to replace `Your project target` with the target name of your project.

       ```swift
       platform :ios, '11.0'

       target 'Your project target' do
           pod 'Agora_Chat_iOS'
       end
       ```

    4. In the project root directory, run the following command to integrate the SDK:

       ```swift
       pod install
       ```

       When the SDK is installed successfully, you can see `Pod installation complete!` in the Terminal and an `xcworkspace` file in the project folder.

    5. Open the `xcworkspace` file in Xcode.

    ### Add a privacy manifest file [#add-a-privacy-manifest-file]

    The Agora Chat SDK for device provides the `PrivacyInfo.xcprivacy` file that contains the required reasons for the APIs used by the SDK. To add the privacy manifest to your app in Xcode, follow these steps:

    1. Create a privacy manifest in your app project:

       1. Choose **File > New File**.

       2. Scroll down to the **Resource** section and select **App Privacy File** type.

       3. Click **Next**.

       4. Check your app in the **Targets** list.

       5. Click **Create**.

       The default file name is `PrivacyInfo.xcprivacy` which is also the required file name for bundled privacy manifests.

    2. Add the items in `PrivacyInfo.xcprivacy` file of the Agora Chat SDK to `PrivacyInfo.xcprivacy` of the app in either of the following ways:

       * Add the following source code:

         ```xml
         <?xml version="1.0" encoding="UTF-8"?>
         <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
         <plist version="1.0">
         <dict>
             <key>NSPrivacyAccessedAPITypes</key>
             <array>
                 <dict>
                     <key>NSPrivacyAccessedAPITypeReasons</key>
                     <array>
                         <string>CA92.1</string>
                     </array>
                     <key>NSPrivacyAccessedAPIType</key>
                     <string>NSPrivacyAccessedAPICategoryUserDefaults</string>
                 </dict>
                 <dict>
                     <key>NSPrivacyAccessedAPITypeReasons</key>
                     <array>
                         <string>C617.1</string>
                     </array>
                     <key>NSPrivacyAccessedAPIType</key>
                     <string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
                 </dict>
             </array>
             <key>NSPrivacyCollectedDataTypes</key>
             <array/>
             <key>NSPrivacyTrackingDomains</key>
             <array/>
             <key>NSPrivacyTracking</key>
             <false/>
         </dict>
         </plist>
         ```

       * Add the list of items as shown in the following figure:

         ![img](https://assets-docs.agora.io/images/common/apple_privacy_policy.png)

    ### Frequently asked questions [#frequently-asked-questions]

    * [How can I add a privacy manifest to my iOS app?](/en/api-reference/faq/other/ios_privacy_manifest)

    ### API reference [#api-reference-1]

    * [`AgoraChatClient.initializeSDKWithOptions`](https://api-ref.agora.io/en/chat-sdk/ios/1.x/interface_agora_chat_client.html#aa628257db8692884cc69e39cc6d7a58b)

    * [`AgoraChatClient.loginWithUsername:token:`](https://api-ref.agora.io/en/chat-sdk/ios/1.x/interface_agora_chat_client.html#a504a9bef378815cb0da3f35a559db4a8)

    * [`AgoraChatClient.logout`](https://api-ref.agora.io/en/chat-sdk/ios/1.x/interface_agora_chat_client.html#a71bb810fe29f67741fe820811370c809)

    * [`AgoraChatManager.sendMessage:progress:completion:`](https://api-ref.agora.io/en/chat-sdk/ios/1.x/protocol_i_agora_chat_manager-p.html#a78bad292be9cd44c08df18e557b9939a)

    * [`AgoraChatManagerDelegate`](https://api-ref.agora.io/en/chat-sdk/ios/1.x/protocol_agora_chat_manager_delegate-p.html)

    * [`AgoraChatClientDelegate`](https://api-ref.agora.io/en/chat-sdk/ios/1.x/protocol_agora_chat_client_delegate-p.html)

    * [`AgoraChatOptions`](https://api-ref.agora.io/en/chat-sdk/ios/1.x/interface_agora_chat_options.html)

    
  
      
  
      
  
      
  
      
  
      
  
### Next steps [#next-steps]

In a production environment, best practice is to deploy your own token server. Users retrieve a token from the token server to log in to Chat. To see how to implement a server that generates and serves tokens on request, see [Secure authentication with tokens](../develop/authentication).
