Initialization & Users

The code below creates a chat client instance for interacting with Stream APIs. Additional options, such as API base URL, can be configured when creating the instance.

// API key can be found on the dashboard: https://getstream.io/dashboard/
let config = ChatClientConfig(apiKey: .init("<# Your API Key Here #>"))

// Create an instance of ChatClient
let chatClient = ChatClient(config: config)

// Recommendation is to store it as a shared instance
extension ChatClient {
  static var shared: ChatClient!
}
ChatClient.shared = chatClient

Connecting the User

Once initialized, you must specify the current user with connectUser :

// Option A: with expiring token
// The `tokenProvider` closure will be called again when the token is expired
ChatClient.shared.connectUser(
  userInfo: .init(id: userID),
  tokenProvider: { providerResult in
    loadChatToken(completion: providerResult)
  },
  completion: { error in
    if let error = error {
      print("Connection failed with: \(error)")
    } else {
      // User successfully connected
    }
  }
)
// or alternatively, using the async-await method
let connectedUser = try await ChatClient.shared.connectUser(
  userInfo: .init(id: userID),
  tokenProvider: { providerResult in
    loadChatToken(completion: providerResult)
  }
)

// An example of a token provider
func loadChatToken(completion: @escaping (Result<Token, Error>) -> Void) {
  NetworkingLayer.getChatToken() { token in
    do {
      let token = try Token(rawValue: token)
      completion(.success(token))
    } catch {
      completion(.failure(error))
    }
  }
}

// Option B: with a non-expiring token
// You can generate the token for this user from https://getstream.io/chat/docs/ios-swift/token_generator/?language=swift
let token: Token = "{{ chat_user_token }}"

/// Connect the user using a closure based method
ChatClient.shared.connectUser(
  userInfo: .init(id: userID),
  token: token
) { error in
  if let error = error {
    print("Connection failed with: \(error)")
  } else {
    // User successfully connected
  }
}
// or alternatively, using the async-await method
let connectedUser = try await ChatClient.shared.connectUser(
  userInfo: .init(id: userID),
  token: token
)

Note how we are waiting for the connectUser API call to be completed before moving forward. You should always make sure to have the user set before making any more calls. All SDKs make this very easy and wait or queue requests until then.

Connect User Parameters

nametypedescriptiondefaultoptional
userobjectThe user object. Must have an id field. User Ids can only contain characters a-z, 0-9, and special characters @ _ and - It can have as many custom fields as you want, as long as the total size of the object is less than 5KB
userTokenstringThe user authentication token. See Tokens & Authentication for detailsdefault

WebSocket Connections

The connectUser (or SDK equivalent) function performs several operations when used. Please note that this method should never be used server-side.

  1. Creates a new user if the user_id is not already registered with the application, incrementing the monthly active users

  2. Updates the user in the application (will add/modify existing fields but will not overwrite/delete previously set fields unless the key is used)

  3. Opens a WebSocket connection and increments the Concurrent Connections for the application

The React-native, iOS, Android, and Flutter SDK’s handle WebSocket disconnection logic, but if a manual disconnect is required in your application, then there are the following options

chatClient.disconnect {
  // disconnected
}
// or
await chatClient.disconnect()

XHR Fallback

Most browsers support WebSocket connections as an efficient mode of real-time data transfer. However, sometimes the connection cannot be established due to network or a corporate firewall. In such cases, the client will establish or switch to XHR fallback mechanisms and gently poll our service to keep the client up-to-date.

The fallback mechanism can be enabled with the flag enableWSFallback

const chatClient = StreamChat.getInstance(‘apiKey’, { enableWSFallBack: true });

Privacy Settings

Additionally, when connecting the user, you can include the privacy_settings as part of the user object.

// Connect the user using a closure based method
chatClient.connectUser(
  userInfo: .init(
    id: userID,
    privacySettings: .init(
      typingIndicators: .init(enabled: true),
      readReceipts: .init(enabled: true)
    )
  ),
  token: token
) { error in
  // …
}
// or alternatively, using the async-await method
let connectedUser = try await chatClient.connectUser(
  userInfo: .init(
    id: userID,
    privacySettings: .init(
      typingIndicators: .init(enabled: true),
      readReceipts: .init(enabled: true)
    )
  ),
  token: token
)

Let’s have a closer look on the parameters:

nametypedescriptiondefaultoptional
typing_indicatorsobjectif enabled is set to false, then typing.start and typing.stop events will be ignored for this user and these events will not be sent to othersenabled: true
read_receiptsobjectIf enabled is set to false, then the read_state of this user will not be exposed to others. Additionally, read_state related events will not be delivered to others when this user reads messages.enabled: true
© Getstream.io, Inc. All Rights Reserved.