# iOS

{% hint style="info" %}
Hackle iOS SDK supports iOS 13 and above.

* Starting from Hackle iOS SDK 3.0.0, the minimum supported version has been changed to iOS 13.
* The minimum supported version for Hackle iOS SDK 2.x is iOS 10.
  {% endhint %}

## Add Dependency

Hackle iOS SDK supports Swift Package Manager and CocoaPods.

[![](https://img.shields.io/github/v/release/hackle-io/hackle-ios-sdk?label=spm)](https://github.com/hackle-io/hackle-ios-sdk) [![](https://img.shields.io/cocoapods/v/Hackle)](https://cocoapods.org/pods/Hackle)

{% tabs %}
{% tab title="Swift Package Manager" %}

```swift
// ...
dependencies: [
    .package(url: "https://github.com/hackle-io/hackle-ios-sdk.git", from: "3.2.1")
],
targets: [
    .target(
        name: "YOUR_TARGET",
        dependencies: ["Hackle"]
    )
],
// ...
```

{% endtab %}

{% tab title="CocoaPods" %}

```
pod 'Hackle', '3.2.1'
```

{% endtab %}
{% endtabs %}

## SDK Initialization

You must initialize `HackleApp` before using the SDK. An SDK Key is required to initialize `HackleApp`.

* `HackleApp` is the class that provides methods for using SDK features.
* You can find the SDK Key in [SDK Integration Info](https://dashboard.hackle.io/config/sdk-setting) in the Hackle Service Dashboard.

Initialization runs **asynchronously**, fetching the necessary information from the Hackle server and storing it in the SDK.

{% hint style="warning" %}
If you call A/B Test or Feature Flag methods before initialization is complete, they return the default group (A) or off (false).
{% endhint %}

{% tabs %}
{% tab title="Swift" %}

```swift
import Hackle

Hackle.initialize(sdkKey: YOUR_APP_SDK_KEY) {
    // SDK ready to use.
}
```

{% endtab %}

{% tab title="Objective-C" %}

```objectivec
@import Hackle;

[Hackle initializeWithSdkKey:@"YOUR_APP_SDK_KEY" config:[HackleConfig DEFAULT] completion:^{
    // SDK ready to use.
}];
```

{% endtab %}
{% endtabs %}

#### Recommended Initialization Strategy: Initialize via Loading Screen

Display a splash screen instead of immediately launching the app, and initialize the SDK. After initialization, close the splash screen via callback so the user can begin interacting with the app.

### Inject User on Initialization

You can initialize the SDK with user information included.

* If no user information is provided, the user information stored in local storage is used.
* If user information is provided, the user information stored in local storage is not used.
* If no user is injected and there is no user information in local storage, a user with the [Hackle Device ID](/en/getting-started/user-identifier.md) as the device ID is used.

{% hint style="info" %}
User information can be freely updated after SDK initialization using the user configuration functions.
{% endhint %}

{% hint style="warning" %}
User information injected at initialization is not merged with user information stored in local storage.

ex) If `userId: A` is stored and you inject `deviceId: B` at initialization, the user is set to `userId: null, deviceId: B`.
{% endhint %}

{% tabs %}
{% tab title="Swift" %}

```swift
let user = User.builder()
    .userId("142")                  // 사용자 ID
    .deviceId("ae2182e0")           // 디바이스 ID
    .build()

Hackle.initialize(sdkKey: YOUR_APP_SDK_KEY, user: user) {
    // SDK ready to use.
}
```

{% endtab %}

{% tab title="Objective-C" %}

```objectivec
HackleUserBuilder *builder = [HackleUser builder];
[builder userId:@"142"];                   // 사용자 ID
[builder deviceId:@"ae2182e0"];            // 디바이스 ID
HackleUser *user = [builder build];

[Hackle initializeWithSdkKey:@"YOUR_APP_SDK_KEY" user:user completion:^{
    // SDK ready to use.
}];
```

{% endtab %}
{% endtabs %}

### SDK Initialization Config

You can initialize the SDK with a configuration object.

{% tabs %}
{% tab title="Swift" %}

```swift
let config = HackleConfigBuilder()
  .build()

Hackle.initialize(sdkKey: YOUR_APP_SDK_KEY, config: config) {
    // SDK ready to use.
}
```

{% endtab %}

{% tab title="Objective-C" %}

```objectivec
HackleConfigBuilder *builder = [[HackleConfigBuilder alloc] init];
[builder exposureEventDedupIntervalSeconds:1];
HackleConfig *config = [builder build];

[Hackle initializeWithSdkKey:@"YOUR_APP_SDK_KEY" config:config completion:^{
    // SDK ready to use.
}];
```

{% endtab %}
{% endtabs %}

#### Configuration Options

<table data-full-width="false"><thead><tr><th width="215.02734375">Option</th><th width="295.48828125">Description</th><th width="125.8125">Default</th><th width="108.09765625">Min Version</th></tr></thead><tbody><tr><td><code>exposureEventDedupIntervalSeconds</code></td><td><p>Removes duplicate exposure events for the same A/B Test or Feature Flag result triggered consecutively by the same user.</p><ul><li>Min: 1</li><li>Max: 86400 (24 hours)</li></ul></td><td>60 (1 min)</td><td>2.7.0+</td></tr><tr><td><code>eventFlushInterval</code></td><td><p>The interval at which collected events are sent to the server.</p><ul><li>Min: 1</li><li>Max: 60 (1 minute)</li></ul></td><td>10</td><td>2.10.0+</td></tr><tr><td><code>pollingIntervalSeconds</code></td><td><p>Periodically updates configuration set in the Dashboard.</p><ul><li>Min: 60 (1 minute)</li></ul></td><td>-1<br>(no periodic update)</td><td>2.18.0+</td></tr><tr><td><code>automaticScreenTracking</code></td><td>Whether to enable automatic Screen Tracking</td><td><code>true</code></td><td>2.34.0+</td></tr><tr><td><code>automaticAppLifecycleTracking</code></td><td>Whether to enable automatic app start/stop tracking</td><td><code>true</code></td><td>2.59.0+</td></tr><tr><td><code>sessionPolicy</code></td><td>Configures session persistence and expiration conditions.</td><td><p><code>ALWAYS_NEW_SESSION</code> ,</p><p><code>1800000</code></p></td><td>3.1.0+</td></tr><tr><td><code>optOutTracking</code></td><td>Whether to enable Opt-out.</td><td><code>false</code></td><td>3.1.0+</td></tr><tr><td><code>sessionTimeoutIntervalSeconds</code><br>(deprecated)</td><td>Sets the session timeout duration. Use <code>sessionPolicy</code> instead.</td><td>1800 (30 min)</td><td>2.13.0+</td></tr></tbody></table>

> <sup>\*</sup> Supported even after app restart from version 2.41.0.\ <sup>\*</sup> For versions below 2.41.0, the maximum value is: 3600 (1 hour).

#### Session Policy Configuration

You can configure session persistence and expiration conditions using the session policy.

{% tabs %}
{% tab title="Swift" %}

```swift
let sessionPolicy = HackleSessionPolicy.builder()
    .persistCondition(.nullToUserId)
    .timeoutCondition(
        HackleSessionTimeoutCondition.builder()
            .timeoutIntervalSeconds(3600)
            .onForeground(false)
            .onBackground(true)
            .onApplicationStateChange(true)
            .build()
    )
    .build()

let config = HackleConfigBuilder()
    .sessionPolicy(sessionPolicy)
    .build()

Hackle.initialize(sdkKey: YOUR_APP_SDK_KEY, config: config) {
    // SDK ready to use.
}
```

{% endtab %}

{% tab title="Objective-C" %}

```objectivec
HackleSessionTimeoutCondition *timeoutCondition = [[[[[[HackleSessionTimeoutCondition builder]
    timeoutIntervalSeconds:3600]
    onForeground:NO]
    onBackground:YES]
    onApplicationStateChange:YES]
    build];

HackleSessionPolicy *sessionPolicy = [[[[HackleSessionPolicy builder]
    persistCondition:[HackleSessionPersistCondition nullToUserId]]
    timeoutCondition:timeoutCondition]
    build];

HackleConfigBuilder *configBuilder = [[HackleConfigBuilder alloc] init];
[configBuilder sessionPolicy:sessionPolicy];
HackleConfig *config = [configBuilder build];

[Hackle initializeWithSdkKey:@"YOUR_APP_SDK_KEY" config:config completion:^{
    // SDK ready to use.
}];
```

{% endtab %}
{% endtabs %}

### Get Instance

After initialization, you can retrieve the `HackleApp` instance with the code below. If called before initialization, it returns nil. You must call it after initialization.

{% tabs %}
{% tab title="Swift" %}

```swift
let hackleApp = Hackle.app()
```

{% endtab %}

{% tab title="Objective-C" %}

```objectivec
HackleApp *hackleApp = [Hackle app];
```

{% endtab %}
{% endtabs %}

### Refresh Dashboard Configuration

You can explicitly refresh the Dashboard configuration.

{% hint style="warning" %}
This function can only be called once every 60 seconds.
{% endhint %}

{% tabs %}
{% tab title="Swift" %}

```swift
hackleApp.fetch {
  // done
}
```

{% endtab %}

{% tab title="Objective-C" %}

```objectivec
[hackleApp fetch:^{
    // done
}];
```

{% endtab %}
{% endtabs %}


---

# 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.hackle.io/en/development-guide/ios.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.
