# Apple iOS SDK

## 1. Preparing

Before integrating Apple provisioning profiles for Application and Network Extension target should be created.

To do this visit Apple developer portal->Certificates, Identifiers & Profiles->Identifiers and add new identifier for your application target and enable next capabilities:

* App Groups
* Keychain sharing
* Network Extensions
* Personal VPN

Create another identifier for Network Extension target using the same capabilities as for Application.

## 2. Integration

### 2.1. Linking

* **Application**

To integrate SDK to application target, copy **FendSDK.framework** to desired location in your project folder, then add it to **Frameworks, Libraries, and Embedded content** application project section and make sure that Embed option is set to **Embed & Sign**

* *Network Extension*

For extension, target perform the same steps as for **Application** target with **FendTunnelProvider.framework**

### 2.2. Configuring capabilities

For both targets *Signing capabilities* should be configured:

### 2.3. App Groups

Create group name started with *group.* and use the same name for Application and Network extension target (ex. *group.fend.testapp*)

### 2.4. Keychain sharing

Create keychain group name and use the same and for Application and Network extension target.

### 2.5. Network extension

Select **Packet Tunnel** option for both targets.

### 2.6. Personal VPN

Make sure that Personal VPN capability is added.

### 2.7. Setup Network Extension target

Change `NSExtensionPrincipalClass` value to **FDTunnelProvider** in `NSExtension` dictionary of Network Extension target `Info.plist`

## 3. Start using FendSDK

### 3.1. Configure FendSDK

To start using the SDK, you need to import `import FendSDK` to your class under the application target.

Initialize FendSDK with `Configuration`:

```
import FendSDK    

    let configuration = Configuration(project: ##Project Name##,
                                          url: ##URL##,
                                      groupID: ##Group ID that you used in Integration step##,
                             providerBundleID: ##Bundle identifier for Network Extension target##,
                            isOnDemandEnabled: true)

    let sdk = FendSDK(configuration: configuration)
```

After SDK is initialized, you need to login to be able to start VPN. Login example with anonymous authorization:

```
import FendSDK
// ...

let sdk: FendSDK
// ...

       sdk.signIn(method: .anonymous()) { user, error in
            print("user = \(user)")
        }
```

### 3.2. Connecting VPN and obtaining status

To establish a VPN connection you need to select location to which you want to connect or pass `nil` and VPN location will be automatically selected.

```
import FendSDK
// ...

let sdk: FendSDK
// ...

        sdk.locations { locations, error in
            if let errror = error {
                print("Error has occured during loading locations: \(error)")
            } else {
                self.location = locations?.first
            }
        }
```

After choosing location use function `connect(to location:completion:)` to start VPN.

```
import FendSDK
// ...

let sdk: FendSDK
// ...

        sdk.connect(to: selectedLocation) { [unowned self] _, error in
            print(error ?? sdk.lastError)
        }
```

When VPN is started or an error occurred, completion handler will be called.

To get notifications about actual VPN state, subscribe to `NEVPNStatusDidChange` and get actual state from `FendSDK.state` variable.

```
import FendSDK
// ...

let sdk: FendSDK
private var stateCancellable: AnyCancellable?
// ...
        stateCancellable = NotificationCenter.default.publisher(for: .NEVPNStatusDidChange)
            .map { _ in () }
            .sink { [unowned self] in
                print("state = \(sdk.state)")
            }
```

### 3.3. Using On Demand mode

SDK provides functionality to restore VPN connection after:

* Changing Wi-Fi/Celluar network
* Wake up after sleep or reboot

Set parameter `isOnDemandEnabled` of `Configuration` to `true` to enable On Demand mode.

### 3.4. Tunnel provider delegate

To get vpn state callbacks in tunnel provider you need to create class with any name that conforms to `FendTunnelProviderDelegate` protocol and inherits from `NSObject`:

```
import FendSDK    
// ...

@objc
class ProviderDelegate: NSObject, FendTunnelProviderDelegate {
    func vpnWillStart() {
        print("vpnWillStart")
    }

    func vpnDidStart() {
        print("vpnDidStart")
    }

    func vpnWillStop() {
        print("vpnWillStop")
    }

    func didReceive(error: Error) {
        print("didReceive: \(error)")
    }
}
///
```

### 3.5. Error Handling

Most of the `FendSDK` calls are accepting completion blocks with errors. If an error occurs, you will receive non-nil `Error` object with an explanation.


---

# 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://fendai.gitbook.io/fendvpn-docs/apple-ios-sdk.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.
