> For the complete documentation index, see [llms.txt](https://docs.caf.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.caf.io/caf-sdk/caf-sdk-pt-br/react-native/standalone-modules/cafsmartauth/native-modules/native-modules-ios.md).

# Módulo nativo iOS

## Como criar um módulo nativo no iOS

Este guia detalhado explica como criar um módulo nativo para a plataforma iOS dentro de uma aplicação React Native. O processo segue as instruções passo a passo da [documentação oficial](https://reactnative.dev/docs/0.73/native-modules-ios).

### 1. Abra o projeto iOS no Xcode

Primeiro, abra o projeto iOS da sua aplicação React Native no Xcode. Você pode encontrar o projeto iOS na pasta: `YourApp/ios/your-app-name.xcworkspace`.

Usar o Xcode ajuda a identificar rapidamente problemas, como erros de sintaxe, e fornece ferramentas poderosas para o desenvolvimento iOS.

### 2. Crie o módulo nativo

Crie um arquivo chamado `CafSmartAuthBridgeModule.swift` no diretório `ios/`. Este arquivo conterá a classe que implementa o módulo nativo.

#### Funções principais da `CafSmartAuthBridgeModule` Classe

* **`requiresMainQueueSetup`**: Indica se o módulo precisa ser configurado na fila principal. Retorna `true`.
* **`supportedEvents`**: Retorna a lista de eventos que o módulo pode emitir para o React Native.
* **`build`**: Cria e configura uma instância do `CafSmartAuthSdk` usando os parâmetros fornecidos.
* **`emitEvent`**: Emite eventos do lado nativo para o React Native.
* **`setupListener`**: Configura um listener para monitorar o status das operações de autenticação.
* **`startSmartAuth`**: Um método exposto ao React Native para iniciar a autenticação inteligente.

#### Exemplo de implementação da `CafSmartAuthBridgeModule.swift` Arquivo

```swift
import Foundation
import React
import CafSmartAuth

private struct CafSmartAuthBridgeConstants { 
    static let cafSmartAuthSuccessEvent: String = "CafSmartAuth_Success"
    static let cafSmartAuthPendingEvent: String = "CafSmartAuth_Pending"
    static let cafSmartAuthErrorEvent: String = "CafSmartAuth_Error"
    static let cafSmartAuthCancelEvent: String = "CafSmartAuth_Cancel"
    static let cafSmartAuthLoadingEvent: String = "CafSmartAuth_Loading"
    static let cafSmartAuthLoadedEvent: String = "CafSmartAuth_Loaded"
    
    static let isAuthorized: String = "isAuthorized"
    static let attestation: String = "attestation"
    static let errorMessage: String = "message"

    static let cafFilterNaturalIndex: Int = 0

    static let backgroundColorHex: String = "#FFFFFF"
    static let textColorHex: String = "#FF000000"
    static let primaryColorHex: String = "#004AF7"
    static let boxBackgroundColorHex: String = "#0A004AF7"
}

@objc(CafSmartAuthBridgeModule)
class CafSmartAuthBridgeModule: RCTEventEmitter {
  private var smartAuth: CafSmartAuthSdk?
  
  @objc
  override static func requiresMainQueueSetup() -> Bool {
    return true
  }
  
  override func supportedEvents() -> [String]! {
    return [
      CafSmartAuthBridgeConstants.cafSmartAuthSuccessEvent,
      CafSmartAuthBridgeConstants.cafSmartAuthPendingEvent,
      CafSmartAuthBridgeConstants.cafSmartAuthErrorEvent,
      CafSmartAuthBridgeConstants.cafSmartAuthCancelEvent,
      CafSmartAuthBridgeConstants.cafSmartAuthLoadingEvent,
      CafSmartAuthBridgeConstants.cafSmartAuthLoadedEvent
    ]
  }
  
  private func build(
    mfaToken: String,
    faceAuthToken: String,
    settings: CafSmartAuthBridgeSettingsModel?
  ) -> CafSmartAuthSdk {
    let builder = CafSmartAuthSdk.CafBuilder(mobileToken: mfaToken)
    
    if let stage = settings?.stage, let cafStage = CAFStage(rawValue: stage) {
      _ = builder.setStage(cafStage)
    }

    if let emailUrl = settings?.emailUrl {
      _ = builder.setEmailURL(URL(string: emailUrl))
    }
    
    if let phoneUrl = settings?.phoneUrl {
      _ = builder.setPhoneURL(URL(string: phoneUrl))
    }
    
    let filter: CafFilterStyle = {
      if let faceSettings = settings?.faceAuthenticationSettings, faceSettings.filter == CafSmartAuthBridgeConstants.cafFilterNaturalIndex {
        return .natural
      }
      return .lineDrawing
    }()
    
    _ = builder.setLivenessSettings(
      CafFaceLivenessSettings(
        faceLivenessToken: faceAuthToken,
        useLoadingScreen: settings?.faceAuthenticationSettings?.loadingScreen ?? false,
        filter: filter
      )
    )

    let lightTheme = settings?.theme?.lightTheme
    let darkTheme = settings?.theme?.darkTheme
    
    _ = builder.setThemeConfigurator(
      CafThemeConfigurator(
        lightTheme: parseTheme(theme: lightTheme),
        darkTheme: parseTheme(theme: darkTheme)
      )
    )
    
    return builder.build()
  }

  private func parseTheme(theme: CafSmartAuthBridgeTheme?) -> CafTheme {
    if theme != nil {
      return CafTheme(
        backgroundColor: theme?.backgroundColor ?? CafSmartAuthBridgeConstants.backgroundColorHex,
        textColor: theme?.textColor ?? CafSmartAuthBridgeConstants.textColorHex,
        linkColor: theme?.linkColor ?? CafSmartAuthBridgeConstants.primaryColorHex,
        boxBorderColor: theme?.boxBorderColor ?? CafSmartAuthBridgeConstants.primaryColorHex,
        boxFilledBorderColor: theme?.boxFilledBorderColor ?? CafSmartAuthBridgeConstants.primaryColorHex,
        boxBackgroundColor: theme?.boxBackgroundColor ?? CafSmartAuthBridgeConstants.boxBackgroundColorHex,
        boxFilledBackgroundColor: theme?.boxFilledBackgroundColor ?? CafSmartAuthBridgeConstants.boxBackgroundColorHex,
        boxTextColor: theme?.boxTextColor ?? CafSmartAuthBridgeConstants.primaryColorHex,
        progressColor:  theme?.progressColor ?? CafSmartAuthBridgeConstants.primaryColorHex
      )
    } else {
      return CafTheme(
        backgroundColor: CafSmartAuthBridgeConstants.backgroundColorHex,
        textColor: CafSmartAuthBridgeConstants.textColorHex,
        linkColor: CafSmartAuthBridgeConstants.primaryColorHex,
        boxBorderColor: CafSmartAuthBridgeConstants.primaryColorHex,
        boxFilledBorderColor: CafSmartAuthBridgeConstants.primaryColorHex,
        boxBackgroundColor: CafSmartAuthBridgeConstants.boxBackgroundColorHex,
        boxFilledBackgroundColor: CafSmartAuthBridgeConstants.boxBackgroundColorHex,
        boxTextColor: CafSmartAuthBridgeConstants.primaryColorHex,
        progressColor: CafSmartAuthBridgeConstants.primaryColorHex
      )
    }
  }
  
  private func emitEvent(name: String, data: Any) {
    self.sendEvent(withName: name, body: data)
  }
  
  private func setupListener() -> CafVerifyPolicyListener {
    return { result in
      switch result {
      case .onSuccess(let response):
        self.emitEvent(
          name: CafSmartAuthBridgeConstants.cafSmartAuthSuccessEvent,
          data: [
            CafSmartAuthBridgeConstants.isAuthorized: response.isAuthorized,
            CafSmartAuthBridgeConstants.attestation: response.attestation
          ]
        )
        self.smartAuth = nil
        
      case .onPending(let response):
        self.emitEvent(
          name: CafSmartAuthBridgeConstants.cafSmartAuthPendingEvent,
          data: [
            CafSmartAuthBridgeConstants.isAuthorized: response.isAuthorized,
            CafSmartAuthBridgeConstants.attestation: response.attestation
          ]
        )
        
      case .onError(let error):
        self.emitEvent(
          name: CafSmartAuthBridgeConstants.cafSmartAuthErrorEvent,
          data: [CafSmartAuthBridgeConstants.errorMessage: error.error.localizedDescription]
        )
        self.smartAuth = nil
        
      case .onCanceled(_):
        self.emitEvent(
          name: CafSmartAuthBridgeConstants.cafSmartAuthCancelEvent,
          data: true
        )
        self.smartAuth = nil
        
      case .onLoading:
        self.emitEvent(name: CafSmartAuthBridgeConstants.cafSmartAuthLoadingEvent, data: true)
        
      case .onLoaded:
        self.emitEvent(name: CafSmartAuthBridgeConstants.cafSmartAuthLoadedEvent, data: true)
      }
    }
  }
  
  
  @objc(startSmartAuth:livenessToken:personId:policyId:settings:)
  func startSmartAuth(mfaToken: String, faceAuthToken: String, personId: String, policyId: String, settings: String?) {
    DispatchQueue.main.async {
      self.smartAuth = self.build(
        mfaToken: mfaToken, faceAuthToken: faceAuthToken, settings: CafSmartAuthBridgeSettings().parseJson(settings: settings)
      )
      
      self.smartAuth?.verifyPolicy(personID: personId, policyId: policyId, listener: self.setupListener())
    }
  }
}
```

### 3. Crie o `CafSmartAuthBridgeSettings.swift` Arquivo

Este arquivo cuidará da interpretação dos dados enviados do React Native para o módulo nativo.

#### Exemplo de implementação:

```swift
import Foundation
import CafSmartAuth

internal struct CafFaceAuthenticationSettingsModel: Decodable {
  let loadingScreen: Bool?
  let filter: Int?
}

internal struct CafSmartAuthBridgeTheme: Decodable {
  let backgroundColor: String?
  let textColor: String?
  let progressColor: String?
  let linkColor: String?
  let boxBackgroundColor: String?
  let boxFilledBackgroundColor: String?
  let boxBorderColor: String?
  let boxFilledBorderColor: String?
  let boxTextColor: String?
}

internal struct CafSmartAuthBridgeThemeConfigurator: Decodable {
  let lightTheme: CafSmartAuthBridgeTheme?
  let darkTheme: CafSmartAuthBridgeTheme?
}


internal struct CafSmartAuthBridgeSettingsModel: Decodable {
  let stage: Int?
  let faceAuthenticationSettings: CafFaceAuthenticationSettingsModel?
  let emailUrl: String?
  let phoneUrl: String?
  let theme: CafSmartAuthBridgeThemeConfigurator?
}

internal class CafSmartAuthBridgeSettings {
  internal func parseJson(settings: String?) -> CafSmartAuthBridgeSettingsModel? {
    guard let data = settings?.data(using: .utf8) else {
      return nil
    }
    
    do {
      let decoder = JSONDecoder()
      let parsedSettings = try decoder.decode(CafSmartAuthBridgeSettingsModel.self, from: data)
      
      return parsedSettings
    } catch {
      return nil
    }
  }
}
```

### 4. Registre o módulo nativo

Crie os arquivos principais de cabeçalho e implementação para o módulo nativo personalizado. Crie um novo arquivo chamado `CafSmartAuthBridge.h`.

#### Exemplo de implementação:

```h
#import <React/RCTBridgeModule.h>

@interface CafSmartAuthBridgeModule : NSObject <RCTBridgeModule>

@end
```

Para tornar o módulo nativo reconhecível pelo React Native, crie o arquivo `CafSmartAuthBridge.mm` no mesmo diretório:

#### Exemplo de implementação:

```mm
#import <Foundation/Foundation.h>
#import <React/RCTBridgeModule.h>
#import <React/RCTEventEmitter.h>

@interface RCT_EXTERN_MODULE(CafSmartAuthBridgeModule, RCTEventEmitter)
RCT_EXTERN_METHOD(startSmartAuth:(NSString *)mfaToken livenessToken:(NSString *)livenessToken personId:(NSString *)personId policyId:(NSString *)policyId settings:(NSString *)settings)
@end
```

### 5. Crie o cabeçalho de bridging para Swift e Objective-C

Sempre que você mistura Swift e Objective-C em um projeto iOS, um arquivo de cabeçalho de bridging é necessário. Esse arquivo permite que o Swift acesse funcionalidades implementadas em Objective-C, incluindo APIs do React Native.

No mesmo diretório do arquivo Swift, crie o arquivo `CafSmartAuthBridge-Bridging-Header.h`.

#### Exemplo de implementação do arquivo de cabeçalho de bridging

```h
#import <React/RCTBridgeModule.h>
#import <React/RCTEventEmitter.h>
```

#### Etapas de configuração

1. Garanta que o `CafSmartAuthBridge-Bridging-Header.h` arquivo esteja incluído no **cabeçalho de bridging do Objective-C** campo em Build Settings (`Build Settings > Swift Compiler - General > Objective-C Bridging Header`).
2. Forneça o caminho relativo para o arquivo, por exemplo,

   ```
   YourApp/ios/YourApp/CafSmartAuthBridge-Bridging-Header.h
   ```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.caf.io/caf-sdk/caf-sdk-pt-br/react-native/standalone-modules/cafsmartauth/native-modules/native-modules-ios.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
