> 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/expo-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 um aplicativo 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

Você pode incluir isso no seu package.json na seção scripts:

```json
"scripts": {
    "open:ios": "xed ios"
},
```

Este script garante que o módulo Expo seja aberto corretamente no Xcode.

### 2. Crie o módulo nativo

Crie um arquivo chamado `CafSmartAuthBridgeModule.swift` no diretório `modules/caf-smart-auth-react-native/ios/`. Este arquivo conterá a classe que implementa o módulo nativo.

#### Principais funções da `CafSmartAuthBridgeModule` Classe

* **`build`**: Cria e configura uma instância de `CafSmartAuthSdk` usando os parâmetros fornecidos.
* **`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 do `CafSmartAuthBridgeModule.swift` Arquivo

```swift
import ExpoModulesCore
import CafSmartAuth

private struct CafSmartAuthBridgeConstants {
    static let moduleName: String = "CafSmartAuthBridgeModule"
    static let startSmartAuth: String = "startSmartAuth"
    
    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 isCancelled: String = "isCancelled"
    static let isLoading: String = "isLoading"
    static let isLoaded: String = "isLoaded"

    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"
}

public class CafSmartAuthBridgeModule: Module {
    // Cada classe de módulo deve implementar a função definition. A definição consiste em componentes
    // que descrevem a funcionalidade e o comportamento do módulo.
    // Veja https://docs.expo.dev/modules/module-api para mais detalhes sobre os componentes disponíveis.
    
    private var smartAuth: CafSmartAuthSdk?
    
    public func definition() -> ModuleDefinition {
        // Define o nome do módulo que o código JavaScript usará para se referir ao módulo. Recebe uma string como argumento.
        // Pode ser inferido pelo nome da classe do módulo, mas é recomendável defini-lo explicitamente para maior clareza.
        // O módulo ficará acessível a partir de `requireNativeModule('CafSmartAuthBridgeModule')` em JavaScript.
        Name(CafSmartAuthBridgeConstants.moduleName)
        
        // Define os nomes de eventos que o módulo pode enviar ao JavaScript.
        Events(
            CafSmartAuthBridgeConstants.cafSmartAuthSuccessEvent,
            CafSmartAuthBridgeConstants.cafSmartAuthPendingEvent,
            CafSmartAuthBridgeConstants.cafSmartAuthErrorEvent,
            CafSmartAuthBridgeConstants.cafSmartAuthCancelEvent,
            CafSmartAuthBridgeConstants.cafSmartAuthLoadingEvent,
            CafSmartAuthBridgeConstants.cafSmartAuthLoadedEvent
        )
        
        // Define uma função síncrona JavaScript que executa o código nativo na thread do JavaScript.
        Function(CafSmartAuthBridgeConstants.startSmartAuth) { (mfaToken: String, faceAuthToken: String, personId: String, policyId: String, settings: String?) -> Void in
            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())
            }
        }
    }
    
    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 setupListener() -> CafVerifyPolicyListener {
        return { result in
            switch result {
            case .onSuccess(let response):
                self.sendEvent(CafSmartAuthBridgeConstants.cafSmartAuthSuccessEvent, [
                    CafSmartAuthBridgeConstants.isAuthorized: response.isAuthorized,
                    CafSmartAuthBridgeConstants.attestation: response.attestation
                ])
                self.smartAuth = nil
                
            case .onPending(let response):
                self.sendEvent(CafSmartAuthBridgeConstants.cafSmartAuthPendingEvent, [
                    CafSmartAuthBridgeConstants.isAuthorized: response.isAuthorized,
                    CafSmartAuthBridgeConstants.attestation: response.attestation
                ])
                
            case .onError(let error):
                self.sendEvent(CafSmartAuthBridgeConstants.cafSmartAuthErrorEvent, [
                    CafSmartAuthBridgeConstants.errorMessage: error.error.localizedDescription
                ])
                self.smartAuth = nil
                
            case .onCanceled(_:):
                self.sendEvent(CafSmartAuthBridgeConstants.cafSmartAuthCancelEvent, [
                    CafSmartAuthBridgeConstants.isCancelled: true
                ])
                self.smartAuth = nil
                
            case .onLoading:
                self.sendEvent(CafSmartAuthBridgeConstants.cafSmartAuthLoadingEvent, [
                    CafSmartAuthBridgeConstants.isLoading: true
                ])
                
            case .onLoaded:
                self.sendEvent(CafSmartAuthBridgeConstants.cafSmartAuthLoadedEvent, [
                    CafSmartAuthBridgeConstants.isLoaded: true
                ])
            }
        }
    }
}
```

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

Este arquivo lidará com a interpretação dos dados enviados do React Native para o módulo nativo.

#### Exemplo de implementação:

```swift
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
    }
  }
}
```


---

# 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/expo-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.
