---
title: Using the iOS SDK
description: >-
  Survicate allows you to launch precisely targeted surveys inside your app. In
  Survicate Panel, you'll be able to define conditions that your users have to
  meet for the surveys to appear.
source_url:
  html: 'https://developers.survicate.com/mobile-sdk/ios/using-sdk/'
  md: 'https://developers.survicate.com/mobile-sdk/ios/using-sdk.md'
---
# Using the iOS SDK

Survicate allows you to launch precisely targeted surveys inside your app. In Survicate Panel, you'll be able to define conditions that your users have to meet for the surveys to appear. Users matching conditions defined in the Survicate panel will see the survey automatically. Here's a list of conditions you can use to target your surveys:

- Name of the screen that a user currently sees
- Any application event
- User attributes and identities
- Device language
- Operating system

Make sure to list all the screens and events described in your application.
Once you got this covered, you or any person responsible for creating and managing surveys will be able to trigger surveys from the Survicate panel with no need for you to update the application.

**Warning**
The SDK utilizes [UserDefaults](https://developer.apple.com/documentation/foundation/userdefaults) to store information used by the targeting engine described in this section. Clearing UserDefaults will cause the targeting system to malfunction; f.e. by showing the same survey twice to a single user.

## Targeting a survey by the screen name

A survey can appear when a user is viewing a specific screen. For example, a survey can be triggered to show up on the application's home screen after a user spends more than ten seconds there. To achieve that, you need to send information to Survicate about the user entering and leaving a screen.

```swift title="Swift"
// UIKit version
class PurchaseSuccessViewController: UIViewController {

    let SCREEN_KEY: String = "purchaseSuccess"

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        SurvicateSdk.shared.enterScreen(value: SCREEN_KEY)
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        SurvicateSdk.shared.leaveScreen(value: SCREEN_KEY)
    }
}

// SwiftUI version
struct ContentView: View {
    // ...
    var body: some View {
        VStack {
            // ...
        }
        .onAppear {
            SurvicateSdk.shared.enterScreen(value: "Showcase")
        }
    }
}

```

```objective-c title="Objective-C"
@implementation PurchaseSuccessViewController

- (void)viewWillAppear:(BOOL)animated {
  [super viewWillAppear:animated];
  [[SurvicateSdk shared] enterScreenWithValue:@"purchaseSuccess"];
}

-(void)viewWillDisappear:(BOOL)animated {
  [super viewWillDisappear:animated];
  [[SurvicateSdk shared] leaveScreenWithValue:@"purchaseSuccess"];
}

@end
```

_Screen name is case sensitive. If there's any discrepancy between what's declared in the ‘Triggers’ tab of the Target section in the Survicate panel and the application code, the survey will not appear._

## Events-based survey targeting

You can log custom user events throughout your application. They can later be used in the Survicate panel to trigger your surveys. Your survey will show instantly after an event occurs in your app.

```swift title="Swift"
// UIKit version
@IBAction func didPressButton(_ sender: Any) {
    SurvicateSdk.shared.invokeEvent(name: "userPressedPurchase")
}

// SwiftUI version
struct ContentView: View {
    var body: some View {
        VStack {
            Button(action: {
                // event without properties
                SurvicateSdk.shared.invokeEvent(name: "userPressedPurchase")

                // event with properties
                SurvicateSdk.shared.invokeEvent(name: "userPressedPurchase", with: [
                    "property1": "value1",
                    "property2": "value2"
                ])
            })
        }
    }
}

```

```objective-c title="Objective-C"
- (IBAction)didPressButton:(id)sender {
    // event without properties
    [[SurvicateSdk shared] invokeEventWithName:@"userPressedPurchase"];

    // event with properties
    [[SurvicateSdk shared] invokeEventWithName:@"userPressedPurchase" withProperties: @{
        @"property1": @"value1",
        @"property2": @"value2"
    }];
}
```

_Event name and property keys are case sensitive. If there is any discrepancy between what's declared in the ‘Triggers’ tab of the Target section in the Survicate panel and the application code, the survey will not appear._

## User identification & attributes

You can pass user attributes to Survicate as an additional layer of information about your users. Attributes can be used to:

- Identify respondents (by default survey responses are anonymous).
- Target surveys to specific users with Audience filters.
- Filter survey results.
- Recall information in survey questions (e.g. include user name).

```swift title="Swift"
// set a single trait
SurvicateSdk.shared.setUserTrait(UserTrait(withName: "userId", value: "YourUserId"))
        
let trait = UserTrait(withName: "firstName", value: "John")
SurvicateSdk.shared.setUserTrait(trait)

// or multiple traits at once
let traits: [UserTrait] = [
  UserTrait(withName: "subscription_active", value: true),
  UserTrait(withName: "my_custom_attribute", value: "value"),
  UserTrait(withName: "age", value: 18),
  UserTrait(withName: "purchase_date", value: Date())
]
        
SurvicateSdk.shared.setUserTraits(traits: traits)
```

```objective-c title="Objective-C"
// Set a single trait
[[SurvicateSdk shared] setUserTraitWithName:@"userId" value:@"YourUserId"];
    
// Set multiple traits at once
[[SurvicateSdk shared] setUserTraitsWithNamesAndValues:@{
  @"subscription_active": @"true",
  @"my_custom_attribute": @"value",
  @"age": @"18",
  @"purchase_date": @"2024-02-01T11:04:48+01:00"}
];
```

_Bear in mind that user attributes are cached, you only have to provide them once, e.g. when user logs in, not after each `initialize()`. You can also change their values at any time (which may potentially trigger showing the survey)._

**Attribute types**

- **String**: any text, e.g. user name or e-mail.
- **Double**: a decimal value.
- **Boolean**: a logic value.
- **Date**: a `Date` that can be used in date or time interval filters.

**Special attributes**

- **user_id**: This corresponds to the "Logged-in status" in the panel's Audience filter. A user is considered logged-in when a trait with the "user_id" key has been set on the device, regardless of the value.

- **first_name**, **last_name**, **email**: If none of these is specified, a response will be marked as Anonymous in the panel.

**Additional notes**

- You can freely use custom attribute keys without the need to register them anywhere.

- In some panel functionalities (e.g. autocompletion), the attribute key will be available only after a survey response with the given attribute is uploaded (unless the key was added in the panel manually). By that time, the trait is saved only locally on the user's device.

- Note that the predefined attribute classes (`UserTrait.userId`, `UserTrait.firstName`, etc.) have been deprecated in version 4.0. Instead, you should use the `UserTrait(withName, value)` constructor. You will find migration details in the deprecation messages.

- In objective-c implementation you should use string values for every attribute type (e.g. `@"true"` for boolean attribute).

## Response attributes

Response attributes are session-scoped attributes attached to survey responses. Unlike user attributes, they are cleared at the start of each new app session and are sent to Survicate along with the user's survey answers.

To update a response attribute, call the method again with the same name and a new value. To clear an attribute, pass an empty string as the value.

```swift title="Swift"
// set a single attribute
SurvicateSdk.shared.setResponseAttribute(ResponseAttribute(name: "promo_code", value: "SAVE20"))

// or multiple attributes at once
let attributes: [ResponseAttribute] = [
    ResponseAttribute(name: "campaign_id", value: "summer-2024"),
    ResponseAttribute(name: "age", value: 18.0),
    ResponseAttribute(name: "subscription_active", value: true),
    ResponseAttribute(name: "trial_started_at", value: Date())
]
SurvicateSdk.shared.setResponseAttributes(attributes)
```

```objective-c title="Objective-C"
// set a single attribute
[[SurvicateSdk shared] setResponseAttribute:[[ResponseAttribute alloc] initWithName:@"promo_code" value:@"SAVE20" provider:nil]];

// or multiple attributes at once
NSArray *attributes = @[
    [[ResponseAttribute alloc] initWithName:@"campaign_id" value:@"summer-2024" provider:nil],
    [[ResponseAttribute alloc] initWithName:@"age" value:@"18" provider:nil],
    [[ResponseAttribute alloc] initWithName:@"subscription_active" value:@"true" provider:nil],
    [[ResponseAttribute alloc] initWithName:@"trial_started_at" value:@"2024-02-01T11:04:48+01:00" provider:nil]
];
[[SurvicateSdk shared] setResponseAttributes:attributes];
```

`ResponseAttribute` accepts the following parameters:
- **name** (required): The key that identifies the attribute.
- **value** (required): The attribute value. Pass an empty string to clear an existing attribute.
- **provider** (optional): The name of the external service where this data comes from (e.g., "hubspot", "intercom"). This helps integrations identify and match your survey respondents with their profiles in that service.

**Attribute types**

- **String**: any text value.
- **Double**: a decimal value.
- **Boolean**: a logic value.
- **Date**: a `Date`.

_Note: In Objective-C, `ResponseAttribute` only accepts `String` values._

## Setting the locale

Survicate SDK automatically detects the device locale using `NSLocale.preferredLanguages` and uses it both to choose the translation of a survey and to evaluate any Device language targeting filters.

If your app allows users to change the locale independently of the system settings, you can override the default by calling:

```swift title="Swift"
SurvicateSdk.shared.setLocale(languageTag)
```

```objective-c title="Objective-C"
[[SurvicateSdk shared] setLocale:@"languageTag"];
```

The argument must be a valid IETF language tag such as:

- A two‑letter ISO 639 code (e.g., "en", "fr")
- A three-letter code for languages without the two-letter equivalent (e.g., "haw", "yue")
- A language tag with region (e.g., "en-US", "pt-BR")

_Note: The specified locale setting applies only to the current application session. To preserve the preference after an app restart, make sure to call `setLocale(...)` again, anytime after `Survicate.init(...)`._

## Theme mode

When your survey has a theme with both light and dark modes, the SDK will select the proper variant following the system setting by default.

Optionally, you can enforce a specific theme mode with the `setThemeMode` method:

```swift title="Swift"
// light, dark, auto
SurvicateSdk.shared.setThemeMode(ThemeMode.auto)
```

```objective-c title="Objective-C"
// ThemeModeLight, ThemeModeDark, or ThemeModeAuto
[[SurvicateSdk shared] setThemeMode:ThemeModeAuto];
```

## Custom fonts

Using the `SurvicateSdk.shared.setFonts` method you can specify custom fonts for survey presentation. You need to provide a PostScript font name for each font style required by the SDK.

```swift title="Swift"
let fontSystem = SurvicateFontSystem(
    regular: "MyFont-Regular",
    regularItalic: "MyFont-Italic",
    bold: "MyFont-SemiBold",
    boldItalic: "MyFont-SemiBoldItalic"
)
SurvicateSdk.shared.setFonts(fontSystem)
```

```objective-c title="Objective-C"
SurvicateFontSystem *fontSystem = [[SurvicateFontSystem alloc]
    initWithRegular:@"MyFont-Regular"
    regularItalic:@"MyFont-Italic"
    bold:@"MyFont-SemiBold"
    boldItalic:@"MyFont-SemiBoldItalic"
];
[SurvicateSdk.shared setFonts:fontSystem];
```

Font names must be **PostScript font names** — not the file name or display name.

> **Note:**
> Custom fonts must be registered in your app's `Info.plist` file and included in your bundle before they can be used with `setFonts()`. Unregistered fonts will cause the SDK to fall back to the default Survicate fonts.

## Listeners

SDK allows you to utilize event listeners. You may find them useful to trigger actions in your application based on actions performed by respondents. Here's a list of events you can subscribe to:

- survey_displayed - occurs when survey is loaded and appears in the User Interface
- question_answered - occurs after a question is answered ( Survicate stores incomplete survey submissions )
- survey_closed - occurs when a user closes the survey using the close button
- survey_completed - occurs when a user finishes the survey.

```swift title="Swift"
class YourClassName{
    // ...
        SurvicateSdk.shared.initialize()
        SurvicateSdk.shared.addListener(delegate)
    // ...
}

extension YourClassName: SurvicateDelegate {
    func surveyDisplayed(event: SurveyDisplayedEvent) {
        print("DELEGATE survey_displayed \(event.surveyId)")
    }

    func questionAnswered(_ event: QuestionAnsweredEvent) {
        print("DELEGATE question_answered \(event.surveyId) \(event.questionId) \(event.answer.value)")
    }

    func surveyCompleted(event: SurveyCompletedEvent) {
        print("DELEGATE survey_completed \(event.surveyId)")
    }

    func surveyClosed(event: SurveyClosedEvent) {
        print("DELEGATE survey_closed \(event.surveyId)")
    }
}

```

```objective-c title="Objective-C"

@import Survicate;

@interface AppDelegate () <SurvicateDelegate>
@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// ...
    [[SurvicateSdk shared] initialize];
    [[SurvicateSdk shared] addListener:self];
// ...
}

- (void)surveyDisplayedWithEvent:(SurveyDisplayedEvent *)event {
    NSLog(@"Survey displayed");
}

- (void)surveyCompletedWithEvent:(SurveyCompletedEvent *)event {
    NSLog(@"Survey completed");
}

- (void)surveyClosedWithEvent:(SurveyClosedEvent *)event {
    NSLog(@"Survey closed");
}

- (void)questionAnswered:(QuestionAnsweredEvent *)event {
    NSLog(@"Question answered");
}
```

### _SurvicateAnswer_ object properties (_QuestionAnsweredEvent.answer_)

| Property | Type       | Description                                                                                    |
|:---------|:-----------|:-----------------------------------------------------------------------------------------------|
| type     | String     | Answer type. One of: ['text', 'single', 'multiple', 'smiley_scale', 'rating', 'csat', 'numerical_scale', 'nps', 'date', 'form', 'matrix', 'button_close', 'button_next', 'button_link']. |
| id       | Integer    | Answer ID. **Applicable only for types: ['single', 'smiley_scale', 'csat', 'rating', 'numerical_scale'].** |
| ids      | Integer[]  | Selected answer IDs. **Applicable only for type = ['multiple'].** |
| value    | String?    | Text representation of an answer, e.g. "Happy" for smiley scale. A `nil` value in case of a skipped question. **Not applicable for call-to-action answers: ['button_close', 'button_next', 'button_link'].** |

_Note: We currently support passing the `id`, `ids` and `value` properties only for the cases enlisted in the table above. You can expect to stumble upon answer objects that consist only of the `type` property._

## Reseting user data for testing purposes

If you need to test surveys on your device, the `reset()` method can be useful. It clears all user data stored on the device — including survey views, attributes, and information about answered surveys — as well as the current in-memory state of the SDK.

```swift title="Swift"
SurvicateSdk.shared.reset()
```

```objective-c title="Objective-C"
[SurvicateSdk.shared reset];
```
