
The new version of Amplitude's iOS SDK (Amplitude-Swift) offers a plugin architecture, built-in type definitions, and broader support for front-end frameworks. The new version isn't backward compatible with Amplitude-iOS.

To migrate to Amplitude-Swift, update your dependencies and instrumentation.

## Terminology

- `Amplitude-iOS`: maintenance iOS SDK.
- `Amplitude-Swift`: new iOS SDK.

## Dependencies

{% tabs tabs="CocoaPods, Swift Package Manager, Carthage" %}
{% tab name="CocoaPods" %}
Add `AmplitudeSwift` dependency to `Podfile`.

```diff
- pod 'Amplitude', '~> 8.14'
+ pod 'AmplitudeSwift', '~> 1.0'
```

{% /tab %}
{% tab name="Swift Package Manager" %}
Enter `https://github.com/amplitude/Amplitude-Swift` into the search bar.

```diff
- `https://github.com/amplitude/Amplitude-iOS`
+ `https://github.com/amplitude/Amplitude-Swift`
```

{% /tab %}
{% tab name="Carthage" %}
Add `amplitude/Amplitude-Swift` to your `Cartfile`.

```diff
- github "amplitude/Amplitude-iOS" ~> 8.14
+ github "amplitude/Amplitude-Swift" ~> 1.0
```

{% /tab %}
{% /tabs %}

## Instrumentation changes

This SDK offers an API to instrument events. To migrate to the new SDK, update a few calls. The following sections detail which calls changed.

### Initialize the SDK

Amplitude-Swift removes `instance()` along with the other calls. The new iOS SDK uses the `Configuration` object to set configuration values.

{% code-group %}
```swift Swift
import Amplitude
import AmplitudeSwift

Amplitude.instance().trackingSessionEvents = true
Amplitude.instance().initializeApiKey("YOUR-API-KEY")
let amplitude = Amplitude(configuration: Configuration(
    apiKey: "API_KEY",
    autocapture: [.sessions, .appLifecycles, .screenViews, .networkTracking]
))
```

```objc Obj-c
#import "Amplitude.h"
@import AmplitudeSwift;

[Amplitude instance].trackingSessionEvents = true;
[[Amplitude instance] initializeApiKey:@"YOUR-API-KEY"];
AMPConfiguration *configuration = [AMPConfiguration initWithApiKey:@"API_KEY"];
configuration.autocapture = [[AMPAutocaptureOptions alloc] initWithOptionsToUnion:@[
    AMPAutocaptureOptions.sessions,
    AMPAutocaptureOptions.appLifecycles,
    AMPAutocaptureOptions.screenViews,
    AMPAutocaptureOptions.networkTracking
]];
Amplitude *amplitude = [Amplitude initWithConfiguration:configuration];
```
{% /code-group %}

### Configure the SDK

| Amplitude-iOS                                                       | Amplitude-Swift                                                                                    |
| ------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- |
| `amplitude.instanceWithName("YOUR-INSTANCE-NAME")`                  | `config.instanceName`                                                                              |
| `amplitude.useDynamicConfig`                                        | NOT SUPPORTED.                                                                                     |
| `amplitude.setServerUrl("YOUR-SERVER-URL")`                         | `config.serverUrl`                                                                                 |
| `amplitude.setServerZone("AMPServerZone.EU or AMPServerZone.US")`   | `config.serverZone`                                                                                |
| `amplitude.trackingOptions`                                         | `config.trackingOptions`                                                                           |
| `amplitude.trackingSessionEvents`                                   | `config.autocapture.sessions`                                                                      |
| `amplitude.minTimeBetweenSessionsMillis`                            | `config.minTimeBetweenSessionsMillis`                                                              |
| `amplitude.eventUploadMaxBatchSize`                                 | `config.flushQueueSize`                                                                            |
| `amplitude.eventUploadThreshold`                                    | `config.flushQueueSize`                                                                            |
| `amplitude.eventUploadPeriodSeconds`                                | `config.flushIntervalMillis`                                                                       |
| Set max retries count. NOT SUPPORTED.                               | `config.flushMaxRetries`                                                                           |
| `amplitude.eventMaxCount`                                           | NOT SUPPORTED.                                                                                     |
| `amplitude.optOut`                                                  | `config.optOut`                                                                                    |
| `amplitude.enableCoppaControl() or amplitude.disableCoppaControl()` | `config.enableCoppaControl`                                                                        |
| Customize storage provider. NOT SUPPORTED.                          | `config.storageProvider`                                                                           |
| Set up log level. NOT SUPPORTED.                                    | `config.logLevel`                                                                                  |
| Customize logger provider. NOT SUPPORTED.                           | `config.loggerProvider`                                                                            |
| `deviceId` and `userId` don't have a minimum length.                | Minimum length is 5. `config.minIdLength` overwrites the minimum length of`deviceId` and `userId`. |
| Partner Id for partner integrations. NOT SUPPORTED.                 | `config.partnerId`                                                                                 |
| The event callback. NOT SUPPORTED. Refer to middleware.             | `config.callback`                                                                                  |
| `amplitude.libraryName`                                             | NOT SUPPORTED.                                                                                     |
| `amplitude.libraryVersion`                                          | NOT SUPPORTED.                                                                                     |
| `amplitude.adSupportBlock`                                          | NOT SUPPORTED. Go to [Plugins](#plugins).                                                            |
| `amplitude.useAdvertisingIdForDeviceId`                             | NOT SUPPORTED. Go to [Plugins](#plugins).                                                            |
| `amplitude.locationInfoBlock`                                       | `amplitude.locationInfoBlock`                                                                      |
| `amplitude.deferCheckInForeground`                                  | NOT SUPPORTED.                                                                                     |
| `amplitude.setOffline(Yes)`                                         | NOT SUPPORTED.                                                                                     |
| `amplitude.setContentTypeHeader("YOUR-CONTENT-TYPE-HEADER")`        | NOT SUPPORTED.                                                                                     |
| `amplitude.setPlan(plan)`                                           | `config.plan`                                                                                      |
| `plan.setBranch("YOUR-BRANCH")`                                     | `config.plan.branch`                                                                               |
| `plan.setSource("YOUR-SOURCE")`                                     | `config.plan.source`                                                                               |
| `plan.setVersion("YOUR-VERSION")`                                   | `config.plan.version`                                                                              |
| `plan.setVersionId("YOUR-VERSION-ID")`                              | `config.plan.versionId`                                                                            |
| `amplitude.setTrackingOptions(options)`                             | `config.trackingOptions`                                                                           |
| `amplitude.setSessionId(timestamp)`                                 | NOT SUPPORTED.                                                                                     |

### Track events

The maintenance iOS SDK offered several `logEvent` APIs with `withEventProperties`, `withApiProperties`, `withUserProperties`, `withGroup`, `withGroupProperties`, `withTimestamp`, and `outOfSession` to override specific properties in the event payload. Amplitude consolidates these variations into a unified `track` API.

#### logEvent

The `logEvent()` API maps to `track()`.

{% code-group %}
```swift Swift
let eventType = "Button Clicked"
let eventProperties: [String: Any] = ["key": "value"]

Amplitude.instance().logEvent(
 eventType,
 withEventProperties: eventProperties
)
let event = BaseEvent(
  eventType: eventType,
  eventProperties: eventProperties
)
amplitude.track(event)
```

```objc Obj-c
NSString* eventType = @"Button Clicked";
NSDictionary* eventProperties = @{@"key": @"value"};

[[Amplitude instance] logEvent:eventType withEventProperties:eventProperties];
AMPBaseEvent* event = [AMPBaseEvent initWithEventType:eventType
    eventProperties:eventProperties];
[amplitude track:event];
```
{% /code-group %}

#### logEvent withTimestamp

The `logEvent()` API maps to `track()`.

{% code-group %}
```swift Swift
let eventType = "Button Clicked"
let timestamp = Int64(NSDate().timeIntervalSince1970 * 1000)
Amplitude.instance().logEvent(
 eventType,
 withTimestamp: timestamp
)
let event = BaseEvent(
  eventType: eventType,
  timestamp: timestamp
)
amplitude.track(event)
```

```objc Obj-c
NSString* eventType = @"Button Clicked";
NSNumber* timestamp = [NSNumber numberWithLongLong:[[NSDate date] timeIntervalSince1970] * 1000];

[[Amplitude instance] logEvent:eventType withTimestamp:timestamp];
AMPBaseEvent* event = [AMPBaseEvent initWithEventType:eventType];
event.timestamp = [timestamp longLongValue];
[amplitude track:event];
```
{% /code-group %}

#### logEvent withGroup

The `logEvent()` API maps to `track()`.

{% code-group %}
```swift Swift
let eventType = "Button Clicked"
let eventProperties: [String: Any] = ["key": "value"]
let groups: [String: Any] = ["orgId": 10]

Amplitude.instance().logEvent(
 eventType,
 withEventProperties: eventProperties,
 withGroups: groups
)
let event = BaseEvent(
  eventType: eventType,
  eventProperties: eventProperties,
  groups: groups
)
amplitude.track(event)
```

```objc Obj-c
NSString* eventType = @"Button Clicked";
NSDictionary* eventProperties = @{@"key": @"value"};

NSDictionary* groups = @{@"orgId": @"10"};
[[Amplitude instance] logEvent:eventType
    withEventProperties:eventProperties
    withGroups:groups];
AMPBaseEvent* event = [AMPBaseEvent initWithEventType:eventType
    eventProperties:eventProperties];
[event.groups set:@"orgId" value:@"10"];
[amplitude track:event];
```
{% /code-group %}

#### uploadEvents

The `uploadEvents()` API maps to `flush()`.

{% code-group %}
```swift Swift
Amplitude.instance().uploadEvents()
amplitude.flush()
```

```objc Obj-c
[[Amplitude instance] uploadEvents];
[amplitude flush];
```
{% /code-group %}

### Set user properties

The APIs for setting user properties are the same, except that Amplitude-Swift removes `instance()`. The following code snippets show how to migrate user property APIs.

#### setUserId

{% callout type="warning" heading="ID length limit" %}
The maintenance SDK uses an old SDK endpoint (`api2.amplitude.com`) that enforces no length limit for `deviceId` and `userId`. The latest SDK uses Amplitude's HTTP V2 API (`api2.amplitude.com/2/httpapi`) and requires identifiers of at least 5 characters by default. When you migrate to the latest SDK, set `config.minIdLength` to a smaller value if you allowed identifiers shorter than 5 characters.
{% /callout %}

Set a user ID on `amplitude` without calling `getInstance()`.

{% code-group %}
```swift Swift
let userId = "TEST-USER-ID"
Amplitude.instance().setUserId(userId)
amplitude.setUserId(userId: userId)
```

```objc Obj-c
NSString* userId = @"TEST-USER-ID";
[[Amplitude instance] setUserId:userId];
[amplitude setUserId:userId];
```
{% /code-group %}

#### setDeviceId

{% callout type="warning" heading="ID length limit" %}
The maintenance SDK uses an old SDK endpoint (`api2.amplitude.com`) that enforces no length limit for `deviceId` and `userId`. The latest SDK uses Amplitude's HTTP V2 API (`api2.amplitude.com/2/httpapi`) and requires identifiers of at least 5 characters by default. When you migrate to the latest SDK, set `config.minIdLength` to a smaller value if you allowed identifiers shorter than 5 characters.
{% /callout %}

Set a device ID on `amplitude` without calling `instance()`.

{% code-group %}
```swift Swift
let deviceId = "TEST-DEVICE-ID"
Amplitude.instance().setDeviceId(deviceId)
amplitude.setDeviceId(deviceId: deviceId)
```

```objc Obj-c
NSString* deviceId = @"TEST-DEVICE-ID";
[[Amplitude instance] setDeviceId:deviceId];
[amplitude setDeviceId:deviceId];
```
{% /code-group %}

#### clearUserProperties

Amplitude-Swift removes the `clearUserProperties` API, but you can use the unified `identify` API to remove user properties.

{% code-group %}
```swift Swift
Amplitude.instance().clearUserProperties()
let identify = Identify()
identify.clearAll()
amplitude.identify(identify: identify)
```

```objc Obj-c
[[Amplitude instance] clearUserProperties];
AMPIdentify* identify = [AMPIdentify new];
[identify clearAll];
[amplitude identify:identify];
```
{% /code-group %}

#### setUserProperties

Amplitude-Swift removes the `setUserProperties` API, but you can use the unified `identify` API to add user properties.

{% code-group %}
```swift Swift
Amplitude.instance().setUserProperties([
  "membership": "paid",
  "payment": "bank",
])
amplitude.identify(userProperties: [
  "membership": "paid",
  "payment": "bank"
])
```

```objc Obj-c
[[Amplitude instance] setUserProperties:@{
    @"membership": @"paid",
    @"payment": @"bank"
}];
AMPIdentify* identify = [AMPIdentify new];
[identify set:@"membership" value:@"paid"];
[identify set:@"payment" value:@"bank"];
[amplitude identify:identify];
```
{% /code-group %}

#### identify

Make an identify call on `amplitude` without calling `instance()`.

{% code-group %}
```swift Swift
let identify = AMPIdentify()
identify.set("membership", value: "paid")
Amplitude.instance().identify(identify)
let identify = Identify()
identify.set(property: "membership", value: "paid")
amplitude.identify(identify: identify)
```

```objc Obj-c
AMPIdentify* identify = [AMPIdentify new];
[identify set:@"membership" value:@"paid"];

[[Amplitude instance] identify:identify];
[amplitude identify:identify];
```
{% /code-group %}

### Set group properties

#### groupIdentify

Make an identify call on `amplitude` without calling `instance()`.

{% code-group %}
```swift Swift
let identify = AMPIdentify()
identify.set("membership", value: "paid")
Amplitude.instance().groupIdentify(
  withGroupType: "TEST-GROUP-TYPE",
  groupName: "TEST-GROUP-NAME",
  groupIdentify: identify
)

let identify = Identify()
identify.set(property: "membership", value: "paid")
amplitude.groupIdentify(
  groupType: "TEST-GROUP-TYPE",
  groupName: "TEST-GROUP-NAME",
  identify: identify
)
```

```objc Obj-c
AMPIdentify* identify = [AMPIdentify new];
[identify set:@"membership" value:@"paid"];

[[Amplitude instance] groupIdentifyWithGroupType:@"TEST-GROUP-TYPE"
    groupName:@"TEST-GROUP-NAME"
    groupIdentify:identify];
[amplitude groupIdentify:@"TEST-GROUP-TYPE"
    groupName:@"TEST-GROUP-NAME"
    identify:identify];
```
{% /code-group %}

### Track revenue

#### logRevenueV2

Track revenue using `revenue()` API on `amplitude` without calling `instance()`.

{% code-group %}
```swift Swift
let revenue = AMPRevenue()
revenue.setProductIdentifier("productIdentifier")
revenue.setQuantity(3)
revenue.setPrice(NSNumber(value: 3.99))
Amplitude.instance().logRevenueV2(revenue)

let revenue = Revenue()
revenue.productId = "productIdentifier"
revenue.quantity = 3
revenue.price = 3.99
amplitude.revenue(revenue: revenue)
```

```objc Obj-c
AMPRevenue* revenue = [AMPRevenue new];

[revenue setProductIdentifier:@"productidentifier"];
[revenue setQuantity:3];
[revenue setPrice:@3.99];
[[Amplitude instance] logRevenueV2:revenue];
revenue.productId = @"productidentifier";
revenue.quantity = 3;
revenue.price = 3.99;
[amplitude revenue:revenue];
```
{% /code-group %}

### Patterns

#### Plugins

The configs `amplitude.adSupportBlock` or `amplitude.useAdvertisingIdForDeviceId` were available in `Amplitude-iOS` to allow you to use IDFV or IDFA as the deviceID. Although `Amplitude-Swift` doesn't support these configurations, you can add plugins to the new iOS SDK to enrich event payloads.

{% code-group %}
```swift Swift
import AdSupport
import AmplitudeSwift
import AppTrackingTransparency
import Foundation
import SwiftUI

/// Plugin to collect IDFA values.  Users will be prompted if authorization status is undetermined.
/// Upon completion of user entry a track event is issued showing the choice user made.
///
/// Don't forget to add "NSUserTrackingUsageDescription" with a description to your Info.plist.
class IDFACollectionPlugin: Plugin {
    let type = PluginType.enrichment
    weak var amplitude: Amplitude? = nil

    func execute(event: BaseEvent?) -> BaseEvent? {
        let status = ATTrackingManager.trackingAuthorizationStatus
        var idfa = fallbackValue
        if status == .authorized {
            idfa = ASIdentifierManager.shared().advertisingIdentifier.uuidString
        }

        let workingEvent = event
        // The idfa on simulator is always 00000000-0000-0000-0000-000000000000
        event?.idfa = idfa
        // If you want to use idfa for the device_id
        event?.deviceId = idfa
        return workingEvent
    }
}

extension IDFACollectionPlugin {
    var fallbackValue: String? {
        // fallback to the IDFV value.
        // this is also sent in event.context.device.id,
        // feel free to use a value that is more useful to you.
        return UIDevice.current.identifierForVendor?.uuidString
    }
}

...
// To install your custom plugin, use 'add()' with your custom plugin as parameter.
amplitude.add(plugin: IDFACollectionPlugin())
```

```objc Obj-c
@import AmplitudeSwift;
#import <AppTrackingTransparency/AppTrackingTransparency.h>
#import <AdSupport/ASIdentifierManager.h>

[amplitude add:[AMPPlugin initWithType:AMPPluginTypeEnrichment execute:^AMPBaseEvent* _Nullable(AMPBaseEvent* _Nonnull event) {
    ATTrackingManagerAuthorizationStatus status = ATTrackingManager.trackingAuthorizationStatus;

    // fallback to the IDFV value.
    // this is also sent in event.context.device.id,
    // feel free to use a value that is more useful to you.
    NSUUID* idfaUUID = [UIDevice currentDevice].identifierForVendor;

    if (status == ATTrackingManagerAuthorizationStatusAuthorized) {
        idfaUUID = [ASIdentifierManager sharedManager].advertisingIdentifier;
    }

    NSString* idfa = (idfaUUID != nil) ? idfaUUID.UUIDString : nil;

    // The idfa on simulator is always 00000000-0000-0000-0000-000000000000
    event.idfa = idfa;
    // If you want to use idfa for the device_id
    event.deviceId = idfa;
    return event;
}]];
```
{% /code-group %}

#### Callback

`Amplitude-Swift` supports configuration-level and event-level callback functions that run on successful and failed uploads. The configuration-level callback runs on every successful and failed event upload. The event-level callback runs only for a specific event. Note that Amplitude-Swift stores event-level callbacks in cache, so the SDK loses these callbacks if the app crashes.

{% code-group %}
```swift Swift
let amplitude = Amplitude(
    configuration: Configuration(
        apiKey: "TEST-API-KEY",
        callback: { (event: BaseEvent, code: Int, message: String) -> Void in
            print("eventCallback: \(event), code: \(code), message: \(message)")
        },
    )
)
```

```objc Obj-c
AMPConfiguration* configuration = [AMPConfiguration initWithApiKey:@"YOUR-API-KEY"];
configuration.callback = ^(AMPBaseEvent* _Nonnull event, NSInteger code, NSString* _Nonnull message) {
    NSLog(@"eventCallback: %@, code: %@, message: %@", event.eventType, @(code), message);
};
Amplitude* amplitude = [Amplitude initWithConfiguration:configuration];
```
{% /code-group %}

Event-level callbacks:

{% tabs tabs="Swift, Obj-c" %}
{% tab name="Swift" %}

```swift
let event = BaseEvent(
    callback: { (event: BaseEvent, code: Int, message: String) -> Void in
        print("eventCallback: \(event), code: \(code), message: \(message)")
    },
    eventType: "TEST-EVENT-TYPE")

amplitude.track(event: event)
```

or:

```swift
let event2 = BaseEvent(eventType:"test")

amplitude.track(
    event: event2,
    callback: { (event: BaseEvent, code: Int, message: String) -> Void in
        print("eventCallback: \(event), code: \(code), message: \(message)")
})
```

{% /tab %}
{% tab name="Obj-c" %}

```objc
AMPBaseEvent* event = [AMPBaseEvent initWithEventType:@"TEST-EVENT-TYPE"];
event.callback = ^(AMPBaseEvent* _Nonnull event, NSInteger code, NSString* _Nonnull message) {
    NSLog(@"eventCallback: %@, code: %@, message: %@", event.eventType, @(code), message);
};

[amplitude track:event];
```

or:

```objc
AMPBaseEvent* event2 = [AMPBaseEvent initWithEventType:@"test"];

[amplitude track:event2 callback:^(AMPBaseEvent* _Nonnull event, NSInteger code, NSString* _Nonnull message) {
    NSLog(@"eventCallback: %@, code: %@, message: %@", event.eventType, @(code), message);
}];
```

{% /tab %}
{% /tabs %}

## Data migration

By default, Amplitude-Swift moves existing [maintenance SDK](/docs/sdks/analytics/ios/ios-sdk) data (events, user/device ID) to the latest SDK. To disable data migration, set `migrateLegacyData` to `false` in the [Configuration](/docs/sdks/analytics/ios/ios-swift-sdk#configure-the-sdk).

If your macOS app isn't sandboxed, data from the legacy SDK doesn't migrate. For more information about sandboxing, and how to determine if your app is sandboxed, go to Apple's article [Protecting user data with App Sandbox](https://developer.apple.com/documentation/security/app_sandbox/protecting_user_data_with_app_sandbox#4098972).

{% code-group %}
```swift Swift
amplitude = Amplitude(
    Configuration(
        ...
        migrateLegacyData: false,
    )
)
```

```objc Obj-c
AMPConfiguration* configuration = [AMPConfiguration initWithApiKey:@"YOUR-API-KEY"];
configuration.migrateLegacyData = false;
Amplitude* amplitude = [Amplitude initWithConfiguration:configuration];
```
{% /code-group %}
