> 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/docs.facephi-en/sdks/sdk-mobile/ios-sdk/ajustes-avanzados.md).

# Advanced settings

This section expands on the information in the section [Simplified Launch](/docs.facephi-en/sdks/sdk-mobile/ios-sdk/inicializacion/lanzamiento-simplificado.md).

### Add private repository

To gain access to our private repository, you must have previously installed **CocoaPods** on the machine.

For security and maintenance reasons, the new components of the ***SDKMobile*** are stored in private repositories that require specific credentials to access them. You must obtain those credentials through the Facephi support team. Below is how to prepare the environment to consume the components:

* First we install the command that will allow us to use cocoapods with **Artifactory**.

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

* On a Mac with **M1 chip** installation errors may occur; in that case, use the following command:

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

If there are problems with the installation, completely uninstall cocoapods and all its dependencies to perform a clean installation.

* We will need to add the repository to the list in the file **netrc**. To do this, from a Terminal, run the following command:

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

And we copy the following snippet with the corresponding data at the end of the file:

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

It is important to copy **exactly** the previous code snippet. The indentation before the words **login** and **password** is made up of two spaces.

* Finally, the repository containing private dependencies will be added:

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

### Required dependencies for the Integration <a href="#id-22-dependencias-requeridas-para-la-integracion" id="id-22-dependencias-requeridas-para-la-integracion"></a>

To avoid conflicts and compatibility issues, if you want to install the component in a project that contains an old version of the Facephi libraries (*Widgets*), these must be completely removed before installing the components of the ***SDKMobile***.

* Currently, the FacePhi libraries are distributed remotely through different dependency managers, in this case, ***CocoaPods***. **Mandatory dependencies** that must be installed beforehand (by adding them to the *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
```

* When dependencies need to be updated, before running **`pod install`** use the following command to update the local repository:

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

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

If the integrator uses a Macbook with Chip **M1**, there is a possibility that the installation of cocoapods-art will not be carried out correctly. Therefore, the following points should be taken into account:

* If cocoapods has been installed using Homebrew, there may be problems.
* It is recommended to install cocoapods and cocoapods-art using gem.

Below we include a script that allows all the necessary steps to be carried out to leave the environment prepared to work correctly:

```
 #! /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
```

In case of using ***xCode15*** the following configuration must be made:

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

The following must be added ***-ld\_classic*** in Other Linker Flags, in the application's Build Settings.

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

**A controller that is not going to be used should not be initialized.**

Each of the components has a controller (*Controller*) that will allow access to its own functionality. Before it can be used, it must be initialized correctly. The steps to follow in the initialization are:

1. Initialize the controllers that are going to be used.
2. Decide whether the License will be included as `String` or through a remote licensing service (see [License Injection](#id-31-inyeccion-de-licencias)) and invoke the SDK initialization.
3. If initialization returns `FinishStatus.STATUS_OK`, the SDK will be ready for use.

```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("Manual License set correctly")
    } else {
        self.log("The manual License is not correct")
    }
}, 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("Automatic License set correctly")
        } else {
            self.log("An error occurred while trying to obtain the License: \(sdkResult.errorType)")
        }
    },
    trackingController: trackingController)
```

#### License Injection <a href="#id-31-inyeccion-de-licencias" id="id-31-inyeccion-de-licencias"></a>

As mentioned previously, there are currently two ways to inject the License:

**a. Obtaining the License through a service**

Through a service that will simply require a URL and an API-KEY as an identifier. This would avoid problems when handling the License, as well as the constant replacement of those License values when any problem arises with it (malformation or improper modification, License expiration...)

```swift
// AUTO License
SDKController.shared.initSdk(licensingUrl: SdkConfigurationManager.LICENSING_URL, apiKey: SdkConfigurationManager.APIKEY_LICENSING, output: { sdkResult in
    if sdkResult.finishStatus == .STATUS_OK {
        self.log("Automatic License set correctly")
    } else {
        self.log("An error occurred while trying to obtain the License: \(sdkResult.errorType)")
    }
}, trackingController: trackingController)
```

**b. Injecting the License as a String**

The License can be assigned directly as a String, as follows:

```swift
// MANUAL License
SDKController.shared.initSdk(license: SdkConfigurationManager.LICENSE, output: { sdkResult in
    if sdkResult.finishStatus == .STATUS_OK {
        self.log("Manual License set correctly")
    } else {
        self.log("The manual License is not correct")
    }
}, trackingController: trackingController)
```

### Start new operation <a href="#id-4-iniciar-nueva-operacion" id="id-4-iniciar-nueva-operacion"></a>

Whenever you want to start the flow of any new operation (examples of operations would be: onboarding, authentication, videoCall,…) it is essential to tell the **SDKController** that this is going to start, and thus the SDK will know that the next calls to **Components** (also called **Steps**) will be part of that operation. This is necessary to track the global information of this operation successfully on the platform.

When starting a process or flow, **always** the call to the method **newOperation**

This method has 3 input parameters:

1. **operationType**: Indicates whether an ONBOARDING or AUTHENTICATION process will be carried out
2. **customerId**: Unique user ID if available (handled at application level)
3. **steps**: List of operation steps if previously defined

There are 2 ways to carry out this operation start, depending on whether **the steps are known** that will make up the registration or authentication process flow (in case the components are executed sequentially and always in the same way) or, otherwise, the flow **is not defined** and is unknown (for example, the end customer is the one who decides the execution order of the components).

* Flow **known** (the tracked operation will appear on the platform with all the steps in the list). Implementation example:

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

* Flow **unknown** (the tracked operation will appear on the platform with ellipses). Implementation example:

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

In **`SdkResult.Success`**, the field **`data`** contains the information of the created operation.

**Once the operation has been created** the SDK components associated with this operation can be executed. Refer to the specific documentation for each component to find out how to do it.

#### Existing operation types <a href="#id-41-tipos-de-operacion-existentes" id="id-41-tipos-de-operacion-existentes"></a>

Currently, there are the following operations, during which certain **Components (STEPS)**. Below is a table with the relationship between operations and steps:

| **Operation (OperationType)** | **Component (Step)**                           | Description                                                                                                                         |
| ----------------------------- | ---------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| ONBOARDING                    | <p>SELPHI\_COMPONENT<br>SELPHID\_COMPONENT</p> | <p>- Facial validation of a selfie against the face of a document<br>- OCR extraction from the document<br>- Liveness detection</p> |
| AUTHENTICATION                | SELPHI\_COMPONENT                              | <p>- Facial validation using templates<br>- Liveness detection</p>                                                                  |

This list will be expanded in future updates to the SDK, as new components and use cases appear.

### Component launch options

Once the SDK has started and a new operation has been created, the component can be launched. There are two ways to launch the component:

* **\[WITH TRACKING]** Launches the component and **sends events** to the *tracking*:

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

* **\[WITHOUT TRACKING]** Launches the component **without sending events** to the *tracking*:

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

The method **launch** should be used **by default**. This method allows it to be used ***tracking*** when its component is enabled, and it will not use it when it is disabled (or the component is not installed).

On the other hand, the method **launchMethod** covers a special case, in which the integrator has tracking installed and enabled, but in a certain flow within the application does not want to track information. In that case, this method is used to prevent that information from being sent to the platform.

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

The result of each component will be returned through the SDK, always keeping the same structure of 3 fields:

1. **finishStatus**: Which will indicate whether the operation has ended successfully. Possible values `FinishStatus.STATUS_OK`, `FinishStatus.STATUS_ERROR`
2. **errorType**: If *finishStatus* indicates that there has been an error, this field will contain its description.
3. **data**: SDK response data; its structure depends on the executed component (see the documentation of each module).

### Auxiliary methods <a href="#id-6-controladores-auxiliares" id="id-6-controladores-auxiliares"></a>

This section includes other controllers and auxiliary operations, some of them optional, and which may be necessary for the correct completion of the flow.

These fields are necessary for communication with the Facephi service, in case you want to perform any **Facephi**verification **tracking** and if you wish to perform the *tracking* of a given operation.

#### Obtaining the OperationId <a href="#id-61-obtencion-del-operationid" id="id-61-obtencion-del-operationid"></a>

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

#### Obtaining the OperationType <a href="#id-62-obtencion-del-operationtype" id="id-62-obtencion-del-operationtype"></a>

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

#### Obtaining the SessionId <a href="#id-63-obtencion-del-sessionid" id="id-63-obtencion-del-sessionid"></a>

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

#### Obtaining the CustomerID <a href="#id-64-obtencion-del-customerid" id="id-64-obtencion-del-customerid"></a>

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

#### Assigning the CustomerID <a href="#id-65-asignacion-del-customerid" id="id-65-asignacion-del-customerid"></a>

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