> For the complete documentation index, see [llms.txt](https://docs.facephi.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.facephi.com/sdks/sdk-mobile/ios-sdk/ajustes-avanzados.md).

# Ajustes avanzados

En esta sección se amplía la información del apartado [Lanzamiento simplificado](/sdks/sdk-mobile/ios-sdk/inicializacion/lanzamiento-simplificado.md).

### Añadir repositorio privado

Para tener acceso a nuestro repositorio privado, se requiere haber instalado previamente **Cocoapods** en la máquina.

Por cuestiones de seguridad y mantenimiento, los nuevos componentes de la ***SDKMobile*** se almacenan en unos repositorios privados que requieren de unas credenciales específicas para poder acceder a ellos. Esas credenciales deberá obtenerlas a través del equipo de soporte de Facephi. A continuación se indica como preparar el entorno para consumir los componentes:

* Primero instalamos el comando que nos dará acceso a usar cocoapods con **Artifactory**.

```
sudo gem install cocoapods-art
```

* En un Mac con **chip M1** pueden surgir errores durante la instalación; en ese caso, use el siguiente comando:

```
sudo arch -arm64 gem install ffi; sudo arch -arm64 gem install cocoapods-art
```

En caso de tener problemas con la instalación, desinstalar completamente cocoapods y todas sus dependencias para hacer una instalación limpia.

* Necesitaremos añadir el repositorio a la lista del fichero **netrc**. Para ello, desde un Terminal, se ejecuta el siguiente comando:

```
$ nano ~/.netrc
```

Y copiamos el siguiente fragmento con los datos correspondientes al final del fichero:

```
machine facephicorp.jfrog.io
  login <USERNAME>
  password <TOKEN>
```

Es importante copiar de manera **exacta** el anterior fragmento de código. El indentado previo a las palabras **login** y **password** está formado por dos espacios.

* Finalmente se añadirá el repositorio que contiene dependencias privada:

```
pod repo-art add cocoa-pro-fphi "https://facephicorp.jfrog.io/artifactory/api/pods/cocoa-pro-fphi"
```

### Dependencias requeridas para la integración <a href="#id-22-dependencias-requeridas-para-la-integracion" id="id-22-dependencias-requeridas-para-la-integracion"></a>

Para evitar conflictos y problemas de compatibilidad, en caso de querer instalar el componente en un proyecto que contenga una versión antigua de las librerías de Facephi (*Widgets*), éstos deberán eliminarse por completo antes de la instalación de los componentes de la ***SDKMobile***.

* Actualmente las librerías FacePhi se distribuyen remotamente a través de diferentes gestores de dependencias, en este caso, ***Cocoapods***. **Dependencias obligatorias** que deben ser instaladas previamente (añadiéndolas al *Podfile*):

```ruby
plugin 'cocoapods-art', :sources => [
  'cocoa-pro-fphi'
]

source 'https://cdn.cocoapods.org/'

target 'Example' do
  pod 'FPHISDKMainComponent', '~> $VERSION'

  post_install do |installer|
    installer.pods_project.targets.each do |target|
      target.build_configurations.each do |config|
        config.build_settings['EXPANDED_CODE_SIGN_IDENTITY'] = ""
        config.build_settings['CODE_SIGNING_REQUIRED'] = "NO"
        config.build_settings['CODE_SIGNING_ALLOWED'] = "NO"
      end
    end
  end
end
```

* Cuando se quiera actualizar dependencias, antes de ejecutar **`pod install`** use el siguiente comando para actualizar el repositorio local:

```sh
pod repo-art update cocoa-pro-fphi
```

### Posibles incidencias <a href="#id-23-posibles-incidencias" id="id-23-posibles-incidencias"></a>

En el caso de que el integrador utilice un Macbook con Chip **M1**, cabe la posibilidad de que la instalación de cocoapods-art no se realice correctamente. Por ello, se debe tener en cuenta los siguientes puntos:

* Si cocoapods se ha instalado mediante Homebrew puede haber problemas.
* Se recomienda instalar cocoapods y cocoapods-art usando gem.

A continuación incluimos un script que permite realizar todos los pasos necesarios para dejar el entorno preparado para poder funcionar correctamente:

```
 #! /bin/zsh

install_cocoapods () {
    echo "Installing cocoapods with gem"
    # Creating new gems home if it doesnt't exist
    if [ ! -d "$HOME/.gem" ]; then
        mkdir "$HOME/.gem"
    fi
    # Adding to current session
    export GEM_HOME="$HOME/.gem"
    export PATH="$GEM_HOME/bin:$PATH"

    # Adding for future sessions
    if test -f "$HOME/.zshrc"; then
        echo 'Adding $GEM_HOME env var and then adding it to your $PATH'
        echo '' >> "$HOME/.zshrc"
        echo 'export GEM_HOME="$HOME/.gem"' >> "$HOME/.zshrc"
        echo 'export PATH="$GEM_HOME/bin:$PATH"' >> "$HOME/.zshrc"
        echo 'alias pod="arch -x86_64 pod"' >> "$HOME/.zshrc"
    fi

    # Installing cocoapods
    gem install cocoapods
    sudo arch -x86_64 gem install ffi
    which pod
    pod --version
    gem install cocoapods-art
}

uninstall_cocoapods_homebrew () {
    which -s brew
    if [[ $? != 0 ]] ; then
        echo "Homebrew not installed, skipping uninstalling cocoapods from homebrew"
    else
        brew uninstall cocoapods
    fi
}

if ! type "pod" > /dev/null; then
    echo "You don't have cocoapods installed..."
else
    echo "Trying to uninstall it from homebrew first"
    uninstall_cocoapods_homebrew
fi

install_cocoapods
```

En caso de usar ***xCode15*** se deberá realizar la siguiente configuración:

<figure><img src="/files/z1D0rrwoMZxS5Tr3ffrU" alt=""><figcaption></figcaption></figure>

Se deberá añadir ***-ld\_classic*** en Other Linker Flags, en el Build Settings de la aplicación.

### SDK initialization <a href="#id-3-sdk-initialization" id="id-3-sdk-initialization"></a>

**Debe evitarse inicializar un controlador que no vaya a usarse.**

Cada uno de los componentes tiene un controlador (*Controller*) que permitirá acceder a su propia funcionalidad. Antes de poder utilizarse, deberán inicializarse correctamente. Los pasos a seguir en la inicialización son:

1. Inicializar los controladores que se van a utilizar.
2. Decidir si la licencia se incluirá como `String` o mediante un servicio de licenciamiento remoto (consultar [Inyección de licencias](#id-31-inyeccion-de-licencias)) e invocar la inicialización del SDK.
3. Si la inicialización devuelve `FinishStatus.STATUS_OK`, el SDK quedará listo para su uso.

```swift
let trackingController = TrackingController(trackingError: { trackingError in
    self.log("TRACKING ERROR: \(trackingError)")
})

// MANUAL License
SDKController.shared.initSdk(license: SdkConfigurationManager.LICENSE, output: { sdkResult in
    if sdkResult.finishStatus == .STATUS_OK {
        self.log("Licencia manual seteada correctamente")
    } else {
        self.log("La licencia manual no es correcta")
    }
}, trackingController: trackingController)

// AUTO License
SDKController.shared.initSdk(
    licensingUrl: SdkConfigurationManager.LICENSING_URL,
    apiKey: SdkConfigurationManager.APIKEY_LICENSING,
    output: { sdkResult in
        if sdkResult.finishStatus == .STATUS_OK {
            self.log("Licencia automática seteada correctamente")
        } else {
            self.log("Ha ocurrido un error al intentar obtener la licencia: \(sdkResult.errorType)")
        }
    },
    trackingController: trackingController)
```

#### Inyección de licencias <a href="#id-31-inyeccion-de-licencias" id="id-31-inyeccion-de-licencias"></a>

Como se ha comentado previamente, actualmente existen dos formas de inyectar la licencia:

**a. Obteniendo la licencia a través de un servicio**

A través de un servicio que simplemente requerirá una URL y un API-KEY como identificador. Esto evitaría problemas a la hora de manipular la licencia, así como la constante sustitución de dichas licencias a la hora de surgir algún problema con ella (malformación o modificación indebida, expiración de la licencia...)

```swift
// AUTO License
SDKController.shared.initSdk(licensingUrl: SdkConfigurationManager.LICENSING_URL, apiKey: SdkConfigurationManager.APIKEY_LICENSING, output: { sdkResult in
    if sdkResult.finishStatus == .STATUS_OK {
        self.log("Licencia automática seteada correctamente")
    } else {
        self.log("Ha ocurrido un error al intentar obtener la licencia: \(sdkResult.errorType)")
    }
}, trackingController: trackingController)
```

**b. Inyectando la licencia como String**

Se puede asignar la licencia directamente como un String, de la siguiente manera:

```swift
// MANUAL License
SDKController.shared.initSdk(license: SdkConfigurationManager.LICENSE, output: { sdkResult in
    if sdkResult.finishStatus == .STATUS_OK {
        self.log("Licencia manual seteada correctamente")
    } else {
        self.log("La licencia manual no es correcta")
    }
}, trackingController: trackingController)
```

### Iniciar nueva operación <a href="#id-4-iniciar-nueva-operacion" id="id-4-iniciar-nueva-operacion"></a>

Cada vez que se desee iniciar el flujo de alguna operación nueva (ejemplos de operaciones serían: onboarding, authentication, videoCall,…) es esencial indicarle al **SDKController** que ésta va a comenzar, y así la SDK sabrá que las próximas llamadas de **Componentes** (también llamados **Steps**) formarán parte de dicha operación. Esto es necesario para trackear a la plataforma la información global de esta operación de forma satisfactoria.

Al iniciar un proceso o flujo, **siempre** se deberá realizar la llamada al método **newOperation**

Este método tiene 3 parámetros de entrada:

1. **operationType**: Indica si se va a hacer un proceso de ONBOARDING o de AUTHENTICATION
2. **customerId**: Id único del usuario si se tiene (controlado a nivel de aplicación)
3. **steps**: Lista de pasos de la operación si se han definido previamente

Hay 2 maneras de realizar este inicio de operación, dependiendo de si **se conocen los pasos** que formarán el flujo del proceso de registro o autenticación (en caso de que los componentes se ejecuten de forma secuencial y siempre de la misma forma) o, en caso contrario, de que el flujo **no esté definido** y sea desconocido (por ejemplo, el cliente final es el que decide el orden de ejecución de los componentes).

* Flujo **conocido** (aparecerá la operación trackeada en la plataforma con todos los pasos de la lista). Ejemplo de implementación:

```swift
SDKController.shared.newOperation(
    operationType: OperationType.X,
    customerId: "customerId",
    steps: [.SELPHI, .SELPHID, .OTHER("CUSTOM_STEP")],
    output: { _ in })
```

* Flujo **desconocido** (aparecerá la operación trackeada en la plataforma con puntos suspensivos). Ejemplo de implementación:

```swift
SDKController.shared.newOperation(
    operationType: OperationType.X,
    customerId: "customerId",
    output: { _ in })
```

En **`SdkResult.Success`**, el campo **`data`** contiene la información de la operación creada.

**Una vez creada la operación** se podrán ejecutar los componentes de la SDK asociados a esta operación. Consultar la documentación específica de cada componente para saber cómo hacerlo.

#### Tipos de operación existentes <a href="#id-41-tipos-de-operacion-existentes" id="id-41-tipos-de-operacion-existentes"></a>

En la actualidad, existen las siguientes operaciones, durante las cuales se hacen uso de unos determinados **Componentes (STEPS)**. A continuación se muestra una tabla con la relación entre operaciones y steps:

| **Operación (OperationType)** | **Componente (Step)**                          | Descripción                                                                                                                              |
| ----------------------------- | ---------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| ONBOARDING                    | <p>SELPHI\_COMPONENT<br>SELPHID\_COMPONENT</p> | <p>- Validación facial de un selfie contra la cara de un documento<br>- Extracción del OCR del documento<br>- Detección de vivacidad</p> |
| AUTHENTICATION                | SELPHI\_COMPONENT                              | <p>- Validación facial mediante plantillas<br>- Detección de vivacidad</p>                                                               |

Esta lista se irá ampliando en próximas actualizaciones de la SDK, según vayan apareciendo nuevos componentes y casos de uso.

### Opciones para el lanzamiento del componente

Una vez iniciado el SDK y creada una nueva operación se podrá lanzar el componente. Hay dos formas de lanzar el componente:

* **\[CON TRACKING]** Lanza el componente y **envía eventos** al servidor de *tracking*:

```swift
let controller = ExampleController(
    data: exampleConfigurationData,
    output: { sdkResult in
        // Do whatever with the result
    },
    viewController: viewController)
SDKController.shared.launch(controller: controller)
```

* **\[SIN TRACKING]** Lanza el componente **sin enviar eventos** al servidor de *tracking*:

```swift
let controller = ExampleController(
    data: exampleConfigurationData,
    output: { sdkResult in
        // Do whatever with the result
    },
    viewController: viewController)
SDKController.shared.launchMethod(controller: controller)
```

El método **launch** debe usarse **por defecto**. Este método permite utilizar ***tracking*** en caso de estar su componente activado, y no lo usará cuando esté desactivado (o no se encuentre el componente instalado).

Por el contrario, el método **launchMethod** cubre un caso especial, en el cual el integrador tiene instalado y activado el tracking, pero en un flujo determinado dentro de la aplicación no desea trackear información. En ese caso se usa este método para evitar que se envíe esa información a la plataforma.

### Retorno de resultado <a href="#id-6-retorno-de-resultado" id="id-6-retorno-de-resultado"></a>

El resultado de cada componente será devuelto a través de la SDK manteniendo siempre la misma estructura de 3 campos:

1. **finishStatus**: Que nos indicará si la operación ha finalizado correctamente. Posibles valores `FinishStatus.STATUS_OK`, `FinishStatus.STATUS_ERROR`
2. **errorType**: Si *finishStatus* indica que ha habido un error, este campo tendrá la descripción del mismo.
3. **data**: Datos de respuesta del SDK; su estructura depende del componente ejecutado (véase la documentación de cada módulo).

### Métodos auxiliares <a href="#id-6-controladores-auxiliares" id="id-6-controladores-auxiliares"></a>

En este apartado se incluyen otros controladores y operaciones auxiliares, algunos de ellos opcionales, y que pueden ser necesarios para la correcta finalización del flujo.

Estos campos son necesarios para la comunicación con el servicio de **Facephi**, en caso de querer realizar cualquier **verificación** y de desear realizar el *tracking* de una operación determinada.

#### Obtención del OperationId <a href="#id-61-obtencion-del-operationid" id="id-61-obtencion-del-operationid"></a>

```swift
SDKController.shared.getOperationId()
```

#### Obtención del OperationType <a href="#id-62-obtencion-del-operationtype" id="id-62-obtencion-del-operationtype"></a>

```swift
SDKController.shared.getOperationType()
```

#### Obtención del SessionId <a href="#id-63-obtencion-del-sessionid" id="id-63-obtencion-del-sessionid"></a>

```swift
SDKController.shared.getSessionId()
```

#### Obtención del CustomerID <a href="#id-64-obtencion-del-customerid" id="id-64-obtencion-del-customerid"></a>

```swift
SDKController.shared.getCustomerId()
```

#### Asignación del CustomerID <a href="#id-65-asignacion-del-customerid" id="id-65-asignacion-del-customerid"></a>

```swift
SDKController.shared.setCustomerId(customerId: customerId)
```
