
Compartilhar:
Abdul é um Developer Advocate da Vonage. Ele tem experiência profissional na área de produtos de consumo como engenheiro de iOS. Em seu tempo livre, ele gosta de andar de bicicleta, ouvir música e orientar quem está dando os primeiros passos na área de tecnologia
Como fazer chamadas de Video com o SwiftUI
Tempo de leitura: 5 minutos
Este artigo foi atualizado em março de 2025
Neste tutorial, você utilizará o Vonage Client SDK for Video Client from Vonage para iOS para criar um chat de vídeo individual no SwiftUI.
Pré-requisitos
Xcode 12 e Swift 5 ou versão posterior.
Criar um projeto da Video API da Vonage
Abra seu painel da API da Vonage e crie um novo aplicativo Vonage. Você pode dar a ele o nome que quiser, mas habilite a opção “Video” na seção de recursos e, em seguida, clique em “Gerar um novo aplicativo”. Assim que o aplicativo for criado, copie o ID do aplicativo. Em seguida, acesse o Vonage Video Playground e crie uma nova sessão:
Certifique-se de que a aba “Criar uma nova sessão” esteja selecionada na parte superior.
Selecione “Sim” na opção “Tem um ID de aplicativo específico?”
Cole o ID do aplicativo que você gerou anteriormente na caixa “ID do aplicativo” que aparecerá.
Deixe todo o resto como está e clique em “Criar sessão”.
Na próxima página que aparecer, anote o “ID DA SESSÃO”.
Clique no botão “Conectar”, na parte superior.
Expanda a seção “Informações sobre sessão e token” na parte superior.
Anote o “TOKEN” que foi gerado
Criação do aplicativo para iOS
O próximo passo é configurar o aplicativo para iOS. Depois de criar o aplicativo, é preciso instalar o Client SDK do Video Client e solicitar permissões para o microfone e a câmera.
Criar um projeto no Xcode
Para começar, abra o Xcode e crie um novo projeto selecionando Arquivo > Novo > Projeto. Selecione iOS como plataforma e App como modelo, e dê um nome ao projeto.

Selecione SwiftUI para a interface, SwiftUI App para o ciclo de vida e Swift para a linguagem. Por fim, escolha um local para salvar seu projeto.

Instale o Client SDK
Agora que você criou o projeto, pode adicionar o Video Client SDK como dependência. Feche seu projeto do Xcode, acesse no terminal o local onde salvou o projeto e execute os seguintes comandos:
Execute o comando `pod init` para criar um novo `Podfile` para o seu projeto.
Abra o Podfile no Xcode usando o comando `open -a Xcode Podfile`.
Atualize o Podfile para incluir
OTXCFrameworkcomo dependência.
# Uncomment the next line to define a global platform for your project
# platform :ios, '12.0'
target 'VideoChat' do
# Comment the next line if you don't want to use dynamic frameworks
use_frameworks!
# Pods for VideoChat
pod 'OTXCFramework'
endInstale o SDK usando
pod install.Abra o novo arquivo xcworkspace no Xcode usando
open VideoChat.xcworkspace.
Permissões
Como o aplicativo utilizará o microfone e a câmera para realizar videochamadas, é necessário adicionar descrições explicando por que essas permissões são necessárias; essas descrições serão exibidas em uma mensagem de aviso ao executar o aplicativo.
Edite o Info.plist arquivo. O Info.plist é um arquivo que contém todos os metadados necessários para o aplicativo. Adicione uma nova entrada ao arquivo passando o mouse sobre a última entrada da lista e clicando no pequeno + que aparece. Na lista suspensa, selecione Privacy - Microphone Usage Description e adicione Microphone access required to video chat como valor. Repita os passos para Privacy - Camera Usage Description.
O Client SDK do Video
O Client SDK do Vídeo utiliza as credenciais que você criou no painel da Video API para se conectar aos servidores da Vonage.
Conectando o Client SDK
Crie um novo arquivo chamado OpenTokManager.swift acessando Arquivo > Novo Arquivo (CMD + N) e adicione o seguinte, substituindo as sequências vazias pelas suas credenciais:
import OpenTok
final class OpenTokManager: NSObject, ObservableObject {
// Replace with your Vonage Application ID
private let kAppId = ""
// Replace with your generated session ID
private let kSessionId = ""
// Replace with your generated token
private let kToken = ""
private lazy var session: OTSession = {
return OTSession(apiKey: kAppId, sessionId: kSessionId, delegate: self)!
}()
private lazy var publisher: OTPublisher = {
let settings = OTPublisherSettings()
settings.name = UIDevice.current.name
return OTPublisher(delegate: self, settings: settings)!
}()
private var subscriber: OTSubscriber?
@Published var pubView: UIView?
@Published var subView: UIView?
@Published var error: OTErrorWrapper?
}Além das credenciais, há variáveis para uma sessão, editor e assinante. Conforme mencionado anteriormente, você pode pensar em uma sessão como uma sala à qual os clientes se conectam; o SDK possui a OTSession classe para isso. Os publicadores, OTPublisher, permitem que o cliente publique áudio e Video quando conectado a uma sessão. Os assinantes, OTSubscriber, permitem que o cliente assine o áudio e o Video de outros clientes na sessão. Há também variáveis que utilizam o @Published wrapper de propriedade, que é como a OpenTokManager classe se comunicará com o código da visualização mais adiante.
Agora que as propriedades estão definidas, adicione as seguintes funções à OpenTokManager classe:
import OpenTok
final class OpenTokManager: NSObject, ObservableObject {
...
public func setup() {
doConnect()
}
private func doConnect() {
var error: OTError?
defer {
processError(error)
}
session.connect(withToken: kToken, error: &error)
}
private func doPublish() {
var error: OTError?
defer {
processError(error)
}
session.publish(publisher, error: &error)
if let view = publisher.view {
DispatchQueue.main.async {
self.pubView = view
}
}
}
private func doSubscribe(_ stream: OTStream) {
var error: OTError?
defer {
processError(error)
}
subscriber = OTSubscriber(stream: stream, delegate: self)
session.subscribe(subscriber!, error: &error)
}
private func cleanupSubscriber() {
DispatchQueue.main.async {
self.subView = nil
}
}
private func cleanupPublisher() {
DispatchQueue.main.async {
self.pubView = nil
}
}
private func processError(_ error: OTError?) {
if let err = error {
DispatchQueue.main.async {
self.error = OTErrorWrapper(error: err.localizedDescription)
}
}
}
}
A doConnect função conecta o cliente à sessão e doPublish inicia a publicação, doSubscribe inicia a assinatura. Depois, há funções para liberar o assinante (cleanupSubscriber) e do editor (cleanupPublisher) quando o cliente se desconecta de qualquer um deles, seguida por uma função para lidar com erros (processError).
O OTSessionDelegate
É OTSessionDelegate é assim que o Client SDK do Video comunica as alterações da sessão de volta para você. Adicione uma extensão no mesmo arquivo:
extension OpenTokManager: OTSessionDelegate {
func sessionDidConnect(_ session: OTSession) {
print("Session connected")
doPublish()
}
func sessionDidDisconnect(_ session: OTSession) {
print("Session disconnected")
}
func session(_ session: OTSession, didFailWithError error: OTError) {
print("session Failed to connect: \(error.localizedDescription)")
}
func session(_ session: OTSession, streamCreated stream: OTStream) {
print("Session streamCreated: \(stream.streamId)")
doSubscribe(stream)
}
func session(_ session: OTSession, streamDestroyed stream: OTStream) {
print("Session streamDestroyed: \(stream.streamId)")
if let subStream = subscriber?.stream, subStream.streamId == stream.streamId {
cleanupSubscriber()
}
}
}Quando a sessão se conecta, doPublish é chamado; quando um stream é criado doSubscribe é chamado e quando o fluxo é destruído cleanupSubscriber é chamado.
O OTPublisherDelegate
É OTPublisherDelegate é assim que o Client SDK de Vídeo comunica a você as alterações relacionadas à publicação em uma sessão. Adicione uma extensão no mesmo arquivo:
extension OpenTokManager: OTPublisherDelegate {
func publisher(_ publisher: OTPublisherKit, streamCreated stream: OTStream) {
print("Publishing")
}
func publisher(_ publisher: OTPublisherKit, streamDestroyed stream: OTStream) {
cleanupPublisher()
if let subStream = subscriber?.stream, subStream.streamId == stream.streamId {
cleanupSubscriber()
}
}
func publisher(_ publisher: OTPublisherKit, didFailWithError error: OTError) {
print("Publisher failed: \(error.localizedDescription)")
}
}Da mesma forma que OTSessionDelegate quando o fluxo é destruído, cleanupPublisher é chamado, e cleanupSubscriber se houver uma assinatura ativa de um stream.
O OTSubscriberDelegate
É OTSubscriberDelegate é assim que o Client SDK do Vídeo comunica as alterações, inscrevendo-se em uma sessão para você. Adicione uma extensão no mesmo arquivo:
extension OpenTokManager: OTSubscriberDelegate {
func subscriberDidConnect(toStream subscriberKit: OTSubscriberKit) {
if let view = subscriber?.view {
DispatchQueue.main.async {
self.subView = view
}
}
}
func subscriber(_ subscriber: OTSubscriberKit, didFailWithError error: OTError) {
print("Subscriber failed: \(error.localizedDescription)")
}
}Da mesma forma que ao publicar em uma sessão, se a inscrição for bem-sucedida, é retornado um UIView objeto. No caso de subscriberDidConnect o objeto de visualização retornado for destinado ao assinante.
Criação da interface do usuário do chat por vídeo
Com a OpenTokManager classe concluída, agora você pode construir a interface do usuário. O Video Client SDK fornece UIView objetos para as visualizações do editor e do assinante que não podem ser usados diretamente no SwiftUI. O UIViewRepresentable protocolo permite fazer a ponte entre um UIView objeto para um View outro objeto para o SwiftUI. No ContentView.swift arquivo, adicione as seguintes estruturas:
struct OTErrorWrapper: Identifiable {
var id = UUID()
let error: String
}
struct OTView: UIViewRepresentable {
@State var view: UIView
func makeUIView(context: Context) -> UIView {
return view
}
func updateUIView(_ uiView: UIView, context: Context) {
DispatchQueue.main.async {
self.view = uiView
}
}
}
A OTView estrutura, que está em conformidade com UIViewRepresentable possui um UIView objeto como propriedade. Essa view é retornada quando o sistema chama makeUIView. Como o ciclo de vida das visualizações no SwiftUI é controlado pelo sistema, você também precisa implementarupdateUIViewpara lidar com isso. AOTErrorWrapperestrutura permite que `error` seja compatível comIdentifiable, o que é necessário para usar os alertas do SwiftUI.
Em seguida, substitua a ContentView estrutura pelo seguinte:
struct ContentView: View {
@ObservedObject var otManager = OpenTokManager()
var body: some View {
VStack {
otManager.pubView.flatMap { view in
OTView(view: view)
.frame(width: 200, height: 200, alignment: .center)
}.cornerRadius(5.0)
otManager.subView.flatMap { view in
OTView(view: view)
.frame(width: 200, height: 200, alignment: .center)
}.cornerRadius(5.0)
}
.alert(item: $otManager.error, content: { error -> Alert in
Alert(title: Text("OpenTok Error"), message: Text(error.error), dismissButton: .default(Text("Ok")))
})
.animation(.default)
.onAppear(perform: {
otManager.setup()
})
}
}
Este código adiciona uma propriedade a uma instância da OpenTokManager classe mencionada anteriormente. Como as visualizações que OpenTokManager estão sendo publicadas são opcionais, .flatmap é usado. Assim, quando as visualizações são nil, elas são ignoradas; e quando há um valor, elas são desembrulhadas. Se o OpenTokManager publicar um erro, o alerta será exibido automaticamente, já que ele está monitorando alterações no .error .
Se você compilar e executar o projeto, agora já deve conseguir iniciar um bate-papo por Video! Você pode usar outro dispositivo ou o Playground da Video API para se conectar à sessão a partir do seu laptop.

E agora?
O projeto concluído está disponível no GitHub, e você pode ler mais sobre a Video API da Vonage em nossa documentação.
Compartilhar:
Abdul é um Developer Advocate da Vonage. Ele tem experiência profissional na área de produtos de consumo como engenheiro de iOS. Em seu tempo livre, ele gosta de andar de bicicleta, ouvir música e orientar quem está dando os primeiros passos na área de tecnologia