# iOS

**BCC Face** is a library meant to be integrated into an iOS application from a `.framework` file.

It uses the device’s camera to take a picture of a face for biometric purposes. It provides a simple active liveness test, requiring the person to smile for about a second and/or look to the right or left. The liveness test includes an option to speak the instructions, facilitating the workflow for users. Additionally, it provides a passive liveness test that can be used to check if the photo was taken from a real person without requiring user interaction.

This manual is updated for BCC Face Mobile iOS version `4.11.3`.

{% hint style="warning" %}
The **passive liveness test** is available only from version `4.4.0` onwards.
{% endhint %}

## Requirements

* Git
* CocoaPods, available at <https://cocoapods.org/>.

## Installation

### Installing Dependencies

1 - Add the following Pods to the application dependencies on Podfile:

```ruby
pod 'GoogleMLKit/FaceDetection'
```

{% hint style="info" %}
If the application does not possess a Podfile, it can be created in the root folder of your Xcode project using the command `pod init` in the terminal. The Podfile will not appear directly in Xcode; it will be created in the project directory.
{% endhint %}

It is preferable to use dynamic frameworks. It can be indicated using the flag `use_frameworks!` on Podfile.

A Podfile example with a target called **BCCs-Sample** is shown below:

```ruby
platform :ios, '15.0'

target 'BCCs-Sample' do
	use_frameworks!

	pod 'GoogleMLKit/FaceDetection'
	pod 'lottie-ios'
end

post_install do |installer|
	installer.pods_project.targets.each do |target|
		target.build_configurations.each do |config|
			config.build_settings['DEVELOPMENT_TEAM'] = "YOUR_DEVELOPMENT_TEAM_KEY"
			config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'
		end
	end
end
```

{% hint style="warning" %}
It is recommended to use the same minimum supported iOS version for your application as the one for this framework: iOS 15.0, as in the example above. It is also advised to set the `BUILD_LIBRARY_FOR_DISTRIBUTION = YES` flag in the Podfile to ensure compatibility with older SDK versions.
{% endhint %}

2 - Close the Xcode project, open a terminal and go to the folder where the Podfile is, and then run:

```bash
pod install
```

After the execution finishes, a file with the `.xcworkspace` extension will be created in the same folder.

3 - Open the new `.xcworkspace` file.

{% hint style="warning" %}
From now on, every time the user wants to open the project, it is necessary to open it through this `.xcworkspace` file, as it includes the dependencies.
{% endhint %}

### Importing and Configuring

#### Importing the Project

* Open the project using the `.xcworkspace` file.
* Add the `BCCFace.framework` file to the project, then add it to the framework list of your application.
  * Move the `.framework` file to the project file tree.
  * If there’s already a framework folder, it is recommended to move the file there.
  * Open the project settings.
  * Go to *General* tab.
  * Click and drag the `.framework` to the project tree under the section `Frameworks, Libraries, etc.`
* Change the `BCCFace.framework` setting from `Do not embed` to `Embed & Sign`.
* Change the target version of your project to a minimum of iOS 15.

{% hint style="info" %}
It is recommended to disable iPad as a target.
{% endhint %}

#### Initial Configuration

This version does not have dependencies on Firebase, and neither from an initial configuration called by AppDelegate. The only initial configuration needed is that the application must request camera usage permission. To do so, add the following key in the `info.plist` file, at the Information Property List:

```properties
Key    :  Privacy - Camera Usage Description
Value  :  Allow access to camera
```

The key value is a message to be shown to the user when requesting camera use permission. This value can be blank or filled with a custom message.

## Usage

### Parameters and Constructor

To properly use the BCC Face library, there are some required parameters.

A simple library usage example is shown below:

```swift
BCCFaceBuilder(self, delegate: self).initializeCapture()
```

***

The `BCCFaceBuilder` class constructor receives the following parameters:

* `hostVC: UIViewController` - View controller that calls the capture screen.
* `delegate: BCCFaceDelegate` - Interface responsible for notifying capture events (e.g. failure or success).

***

The `initializeCapture` method also accepts an optional parameter, an shown below:

```swift
public func initializeCapture(
	_ navController: UINavigationController? = nil
) {
	// ...
}
```

If you want the navigation to run through a navigation controller, you must provide it when calling the method.

***

The `BCCFaceBuilder` class is responsible for handling the usage configuration for `BCCFace`. The following parameters are accepted for configuring biometric capture and software behavior:

* `buildSmileCheck(with smileProbability: ClosedRange<Float> = 0.5...1.0)` - Adds smile for liveness test and defines the acceptance threshold. This feature is enabled by default.
* `removeSmileCheck()` - Removes smile for liveness check.
* `buildRotationCheck(_ rotationChecks: [HeadRotationCheck], headRotationAngle: ClosedRange<Float> = -6.0...6.0)` - Defines a list of liveness tests for head rotation and max rotation angle. This feature is enabled by default. The head rotation options are:

  ```swift
  enum class HeadRotationCheck {
  	case randomRotation
  	case leftRotation
  	case rightRotation
  }
  ```
* `removeHeadRotation()` - Removes head rotation for liveness check.
* `addPassiveLiveness()` - Adds the passive liveness test. This feature is used to check if the captured photo is from a real person without requiring any user interaction. To use this feature, you MUST disable the active liveness checks (`removeSmileCheck()` and `removeHeadRotation()`) that are added by default.
* `buildSpeechSettings(_ speechSettings: SpeechSettings)` - Defines the criteria for accessibility speech, using the following parameters:

  ```swift
  class SpeechSettings(
  	public let volume: Float
  	public let startsMuted: Bool
  	public let pitch: Float
  	public let speed: Float
  )
  ```

  * `volume` - The audio volume between `0.0` and `1.0`.
  * `startsMuted` - Defines whether the instructions start muted or not (`true` for muted).
  * `pitch` - Defines the voice pitch for the instructions between `0.5` (low) and `2.0` (high).
  * `speed` - Defines the voice speed for the instructions. This value must be positive.

  The pre-defined values can be accessed through the static variable:

  ```swift
  public static let defaultSpeechSettings = SpeechSettings(
  	volume: 1.0,
  	startsMuted: true,
  	pitch: 1.0,
  	speed: 0.5
  )
  ```
* `removeSpeech()` - Removes accessibility speech.
* `setInstructionEnable(_ enable: Bool)` – Defines whether the instruction screen is enabled or disabled.
* `forceLanguage(_ language: BCCLanguages?)` - Forces the instructions to be shown on a single language. If the device language is not supported, English will be used. The supported languages are:

  ```swift
  public enum BCCLanguages: String {
  	case ptBR = "pt-BR"
  	case enUS = "en"
  	case esMX = "es"
  	case deviceLanguage = "deviceLanguage"
  }
  ```
* `enableFlashButton(_ enable: Bool)` – Enables (`true`) or disables (`false`) the flash button on the rear camera. Default: disabled (`false`).
* `enableManualCapture(_ enable: Bool)` – Enables (`true`) or disables (`false`) the manual capture button, allowing the user to bypass automatic capture checks. When performing a manual capture, the user will be able to review the captured photo before completing the process.
* `setImageCompressionFormat(_ format: ImageCompressionFormat)` – Defines the compression format for a passive liveness capture. Available options are `.jpeg` (default) or `.jpeg2000`.
* `enableIntegrityValidation(clientSecret: Data, nonce: Data)` – Enables integrity validation for passive liveness detection, adding an extra security layer to ensure payload integrity.

For reference, here is a full list of parameters and default values:

```swift
var headRotationAngle: ClosedRange<Float> = -6.0...6.0
var openEyesProbability: ClosedRange<Float> = 0.8...1.1
var smileProbability: ClosedRange<Float> = 0.5...1.0
var livenessChecks: [LivenessChecks] = [.smileDetection]
var headRotationChecks: [HeadRotationCheck] = [.randomRotation]
var speechSettings: SpeechSettings? = .defaultSpeechSettings
var cameraSettings: CameraSettings = .defaultCameraSettings
var canEnableManualCapture: Bool = false
var canEnableFlash: Bool = true
var language: BCCLanguages? = nil
var showInstructions: Bool = false
var imageCompressionFormat: ImageCompressionFormat = .jpeg
var integrityValidationData: IntegrityValidationData? = nil
```

{% hint style="warning" %}
The active liveness test (using smile and random head rotation) is enabled by default. To only use the passive liveness check, before adding it, it is necessary to remove the active liveness methods from the constructor:

```swift
BCCFaceBuilder(self, delegate: self)
	.removeSmileCheck()
	.removeHeadRotation()
	.addPassiveLiveness()
```

{% endhint %}

Here is a code snipped to initialize a capture using only the passive liveness test:

```swift
// From the desired ViewController...

// Create the builder
let faceBuilder = BCCFaceBuilder(self, delegate: self)

// Setup the builder
faceBuilder
	.removeSmileCheck()
	.removeHeadRotation()
	.addPassiveLiveness()

// Initialize the capture from the builder
faceBuilder.initializeCapture(self.navigationController)
```

### Return Values

The results from the last facial capture can be retrieved using the `faceCaptureDidFinish` method from the `BCCFaceDelegate` interface:

```swift
func faceCaptureDidFinish(
	data: BCCFaceReturnData,
	analytics: BCCFaceReturnAnalytics
)
```

The `data` object contains the images captured during the process:

```swift
public struct BCCFaceReturnData {
	// Previously 'photo', renamed to conform to the same standard as Android
	public internal(set) var originalPhoto: UIImage
	public internal(set) var croppedPhoto: UIImage?

	// Passive Liveness Result
	public internal(set) var passiveResult: Data?

	// LEGACY API: same as 'originalPhoto'
	public var photo: UIImage { self.originalPhoto }
}
```

The returned properties are:

* `originalPhoto` (*image*) - The original photo taken by the camera.
* `croppedPhoto` (*image*) - The cropped photo, which is the face image cropped from the original photo.
* `passiveResult` (*Data*) - File content of the collection for passive liveness. It is present only if successfully captured. It is the return of the collection for passive liveness as *JPEG Data*. This data can be saved/exported directly to a file or sent to the network (for networking: system encoding can be easily done, e.g. Base64 string).

If the user aborts the capture, closing before capturing the biometrics, the method `faceCaptureDidAbort` will be called. You can implement this method to treat this scenario.

### Sample Project

This is a functional sample project for a face capture using BCC Mobile Face iOS:

```swift
import UIKit
import BCCFace

class ViewController: UIViewController {
	override func viewDidLoad() {
		super.viewDidLoad()
	}

	@IBAction func startCapture(_ sender: UIButton) {
		BCCFaceBuilder(self, delegate: self)
			.removeSmileCheck()
			.removeHeadRotation()
			.addPassiveLiveness()
			.buildCameraSettings(.frontSwitchable)
			.enableFlashButton(true)
			.initializeCapture(navigationController)
	}
}

extension ViewController: BCCFaceDelegate {
	func faceCaptureDidFinish(
		data: BCCFace.BCCFaceReturnData,
		analytics: BCCFace.BCCFaceAnalytics
	) {
		// ...
	}

	func faceCaptureDidAbort(
		analytics: BCCFace.BCCFaceAnalytics
	) {
		// ...
	}
}
```

## Agent Instructions: Querying This Documentation <a href="#agent-instructions-querying-this-documentation" id="agent-instructions-querying-this-documentation"></a>

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:

```
GET https://docs.griaule.com/sdks/bcc-face/bccmobilefaceios.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language. 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.


---

# Agent Instructions: 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:

```
GET https://docs.griaule.com/sdks/en/bcc-face/bccmobilefaceios.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
