# In-App Experiences for the Apple SDK

Integrate Scenes & In-App Automations into your Apple app to display embedded content and create custom in-app experiences with minimal code.

In-App Experiences use Airship's on-device automation framework to provide instant, personalized content that integrates natively with your app. This includes [Scenes](https://www.airship.com/docs/reference/glossary/#scene), which can be displayed as modal or fullscreen overlays or embedded directly within your app screens, and In-App Automations (IAA), which power banner, modal, and fullscreen in-app messages triggered by events.

<!-- TODO: Add image: scenes-overview.png - Examples of Scenes: modal overlay, fullscreen, and embedded in app screen -->

Scenes are fully customizable in the Airship dashboard and require minimal SDK integration. For advanced In-App Automation customization options, see [In-App Automation](https://www.airship.com/docs/developer/sdk-integration/apple/in-app-experiences/in-app-automation/).

## Requirements

To use In-App Experiences, you need:

- The `AirshipAutomation` module installed (see [Getting Started](https://www.airship.com/docs/developer/sdk-integration/apple/installation/getting-started/))
- Airship SDK initialized with `takeOff` (see [Getting Started](https://www.airship.com/docs/developer/sdk-integration/apple/installation/getting-started/))

> **Note:** **In-App Experiences work out of the box**: Once you install the `AirshipAutomation` module and initialize Airship with `takeOff`, In-App Experiences will function automatically. The rest of this documentation covers optional customization and advanced features.


## Adding custom fonts

Custom fonts added to your app bundle can be used in In-App Experiences. To add fonts to your app, follow Apple's guide on [Adding a Custom Font to Your App](https://developer.apple.com/documentation/uikit/text_display_and_fonts/adding_a_custom_font_to_your_app).

Once added, you'll need the font family name to use it in Airship. To find the family name:

1. Add the font files to your Xcode project
2. Use this code to print all available font family names:


#### Swift


```swift
for family in UIFont.familyNames.sorted() {
    print("Family: \(family)")
    for name in UIFont.fontNames(forFamilyName: family) {
        print("  - \(name)")
    }
}
```



#### Objective-C


```objc
for (NSString *familyName in [UIFont familyNames]) {
    NSLog(@"Family: %@", familyName);
    for (NSString *fontName in [UIFont fontNamesForFamilyName:familyName]) {
        NSLog(@"  - %@", fontName);
    }
}
```




After adding fonts to your app, create a Font Stack in the Airship dashboard by following the steps in [Setting brand guidelines](https://www.airship.com/docs/guides/messaging/features/brand-guidelines/). You can then select the stack when [setting In-App Experience defaults](https://www.airship.com/docs/guides/messaging/in-app-experiences/configuration/defaults/) and creating in-app messages.

## Controlling display

Control when and how In-App Experiences are displayed in your app. You can auto-pause displays on launch (useful for splash screens), manually pause all in-app displays, set intervals between displays, control when individual messages are ready to display, and specify which scene window displays messages in multi-scene apps.

### Auto-pausing on launch

For apps with splash screens, you can configure Airship to automatically pause In-App Automation on launch. This prevents In-App Experiences from displaying during the splash screen. Once your app is ready, resume display by setting `isPaused` to `false`.

Set the `autoPauseInAppAutomationOnLaunch` option in your Airship config when calling `takeOff`:


#### Swift


```swift
var config = AirshipConfig()

// ... other config settings ...

// Auto-pause on launch for splash screen
config.autoPauseInAppAutomationOnLaunch = true

try! Airship.takeOff(config)

// Later, when splash screen is dismissed and app is ready:
Airship.inAppAutomation.isPaused = false
```



#### Objective-C


```obj-c
UAConfig *config = [UAConfig config];

// ... other config settings ...

// Auto-pause on launch for splash screen
config.autoPauseInAppAutomationOnLaunch = YES;

[UAirship takeOff:config error:&airshipError];

// Later, when splash screen is dismissed and app is ready:
UAirship.inAppAutomation.isPaused = NO;
```




### Pausing display

Pausing will still allow In-App Experiences to be triggered and queued up 
for execution, but they will not display. This is useful for preventing in-app experiences from
displaying on screens where it would be detrimental to the user experience,
such as splash screens, settings screens, or landing pages.


#### Swift


```swift
Airship.inAppAutomation.isPaused = true
```



#### Objective-C


```obj-c
Airship.inAppAutomation.isPaused = YES
```




### Display interval

The display interval controls the amount of time to wait before the manager can display the next triggered In-App Experience. The default value is set to **0 seconds** and can be adjusted to any amount of time in seconds.


#### Swift


```swift
Airship.inAppAutomation.inAppMessaging.displayInterval = 30
```



#### Objective-C


```obj-c
UAirship.inAppAutomation.inAppMessaging.displayInterval = 30
```




### Controlling per-message display

You can control when individual In-App Experiences are ready to display and listen for when they are displayed or finished. This is useful when you need to check app state before displaying content, such as:

- Verifying the current screen or view controller is appropriate for the message
- Checking custom data in the message's extras (custom keys) to determine if it should display
- Ensuring certain app conditions are met before showing the message
- Integrating with other in-app messaging products


#### Swift



Set a closure on to control the display. You have access to the message and schedule ID:

```swift
Airship.inAppAutomation.inAppMessaging.onIsReadyToDisplay = { message, scheduleID in
    // Return false to prevent display
    return false
}
```


`onIsReadyToDisplay` will be called whenever state in the app changes (screen, app state, message finished displaying, etc...), you can also 
trigger it manually with `notifyDisplayConditionsChanged`:

```swift
Airship.inAppAutomation.inAppMessaging.notifyDisplayConditionsChanged()
```




#### Objective-C



Implement the `InAppMessageDisplayDelegate` to control the display. You have access to the message and schedule ID:

**Implement the InAppMessageDisplayDelegate**


```obj-c
- (BOOL)isMessageReadyToDisplay:(UAInAppMessage *)message scheduleID:(NSString *)scheduleID {
    // Return NO to prevent display
    return NO;
}
```


**Set the delegate**


```obj-c
UAirship.inAppAutomation.inAppMessaging.displayDelegate = self;
```


`isMessageReadyToDisplay` will be called whenever state in the app changes (screen, app state, message finished displaying, etc...), you can also trigger it manually with `notifyDisplayConditionsChanged`:

```obj-c
[UAirship.inAppAutomation.inAppMessaging notifyDisplayConditionsChanged];
```





### Displaying in multiple scene apps

By default, In-App Experiences are displayed in the last active window scene. The [InAppMessageSceneDelegate](https://urbanairship.github.io/ios-library/v20/AirshipAutomation/documentation/airshipautomation/inappmessagescenedelegate)
 allows you to override this behavior and control which UIWindowScene displays a given in-app message. Use this delegate when your app supports multiple scenes and you need to customize which scene displays the message.


#### Swift



**Implement the InAppMessageSceneDelegate**

```swift
func sceneForMessage(_ message: InAppMessage) -> UIWindowScene? {
    // return a custom scene or nil to use default
}
```


**Set the delegate**

```swift
Airship.inAppAutomation.inAppMessaging.sceneDelegate = sceneDelegate
```




#### Objective-C



**Implement the InAppMessageSceneDelegate**

```obj-c
- (UIWindowScene *)sceneForMessage:(UAInAppMessage *)message {
    // return a custom scene or nil to use default
    return nil;
}
```


**Set the delegate**

```obj-c
UAirship.inAppAutomation.inAppMessaging.sceneDelegate = self;
```





## Next steps

- Learn how to [create Scenes in the Airship dashboard](https://www.airship.com/docs/guides/messaging/in-app-experiences/scenes/create/)
- Present Scene content with [Embedded Content](https://www.airship.com/docs/developer/sdk-integration/apple/in-app-experiences/embedded-content/)
- Create reusable components with [Custom Views](https://www.airship.com/docs/developer/sdk-integration/apple/in-app-experiences/custom-views/)
- Customize [In-App Automation](https://www.airship.com/docs/developer/sdk-integration/apple/in-app-experiences/in-app-automation/) for IAA
