# Migration Guide | Sentry for iOS

To upgrade from version 4.x of the SDK to version 9.x of the SDK, you must first migrate from 4.x to 5.x, then 5.x to 6.x, then 6.x to 7.x, 7.x to 8.x, and finally from 8.x to 9.x.

## [Migrating From 8.x to 9.x](https://docs.sentry.io/platforms/apple/guides/ios/migration.md#migrating-from-8x-to-9x)

Migrating to 9.x from 8.x includes several breaking changes. We provide this guide to help you update your SDK.

### [Changes to Minimum OS Versions and Xcode](https://docs.sentry.io/platforms/apple/guides/ios/migration.md#changes-to-minimum-os-versions-and-xcode)

We bumped the minimum supported OS versions to:

* **iOS**: 15.0 (previously 11.0)
* **macOS**: 10.14 (previously 10.13)
* **tvOS**: 15.0 (previously 11.0)
* **visionOS**: 1.0 (unchanged)
* **watchOS**: 8.0 (previously 4.0)

We now build the precompiled XCFramework with **Xcode 16**. To submit to the App Store, Apple now requires Xcode 16. If you need a precompiled XCFramework built with Xcode 15, continue using Sentry SDK 8.x.x.

Additionally, the Package.swift sets `swift-tools-version` to 6.0.

### [Carthage Support Dropped](https://docs.sentry.io/platforms/apple/guides/ios/migration.md#carthage-support-dropped)

We dropped official support for Carthage in v9. If you're using Carthage, please migrate to [Swift Package Manager (SPM)](https://docs.sentry.io/platforms/apple/guides/ios/install/swift-package-manager.md) or [CocoaPods](https://docs.sentry.io/platforms/apple/guides/ios/install/cocoapods.md).

### [Features Enabled by Default](https://docs.sentry.io/platforms/apple/guides/ios/migration.md#features-enabled-by-default)

We now enabled the following features by default:

* **Performance V2 is enabled by default**: The app start duration now finishes when the first frame is drawn instead of when the OS posts the `UIWindowDidBecomeVisibleNotification`. We removed the `enablePerformanceV2` option.
* **Pre-warmed app start tracking**: The SDK now collects pre-warmed app starts by default via `enablePreWarmedAppStartTracing`.
* [App hang tracking V2](https://docs.sentry.io/platforms/apple/guides/ios/configuration/app-hangs.md#app-hangs-v2): This is now the default only on \*\*iOS and **tvOS** and we removed the option to enable/disable it. macOS still uses V1.

### [Disable App Hang Tracking for Extensions](https://docs.sentry.io/platforms/apple/guides/ios/migration.md#disable-app-hang-tracking-for-extensions)

We now automatically disable app hang tracking for: Widgets, Live Activities, Action Extensions, (Siri) Intent Extensions, Share Extensions. These components run in separate processes or sandboxes with different execution characteristics, which can cause false positive app hang reports.

### [Structured Logging](https://docs.sentry.io/platforms/apple/guides/ios/migration.md#structured-logging)

We moved structured logging out of experimental and made it part of the stable API. The `enableLogs` option moved from `options.experimental.enableLogs` to `options.enableLogs`. We added log APIs to `Hub` and `Client`, and logs now include a `sentry.replay_id` attribute.

**Migration required:** Update your code from `options.experimental.enableLogs = true` to `options.enableLogs = true`. Logging is not enabled by default; you must explicitly set this option.

#### [HTTP Client Errors](https://docs.sentry.io/platforms/apple/guides/ios/migration.md#http-client-errors)

HTTP client errors now mark sessions as errored. This provides better visibility into failed network requests in your release health data.

### [Profiling Changes](https://docs.sentry.io/platforms/apple/guides/ios/migration.md#profiling-changes)

We removed all deprecated profiling APIs in version [9.0.0](https://github.com/getsentry/sentry-cocoa/releases/tag/9.0.0).

The only supported profiling method is now [UI Profiling](https://docs.sentry.io/platforms/apple/guides/ios/profiling.md#enable-ui-profiling) (also known as continuous V2 profiling), which was introduced in [version 8.49.0](https://github.com/getsentry/sentry-cocoa/releases/tag/8.49.0).

**Removed deprecated profiling options from `SentryOptions`:**

* `profilesSampleRate` - used for transaction-based profiling (deprecated)
* `profilesSampler` - used for transaction-based profiling (deprecated)
* `enableAppLaunchProfiling` - used for launch profiling (deprecated)

**Migration to UI Profiling:**

If you were using any of the deprecated profiling options, you need to migrate to UI Profiling. Configure profiling by assigning a closure to `SentryOptions.configureProfiling`:

```swift
import Sentry

SentrySDK.start { options in
    options.dsn = "___PUBLIC_DSN___"
    options.configureProfiling = {
        $0.sessionSampleRate = 1
        $0.lifecycle = .manual // or .trace for trace-based lifecycle
    }
}
```

For more information, see the [UI Profiling documentation](https://docs.sentry.io/platforms/apple/guides/ios/profiling.md#enable-ui-profiling).

### [Breaking Changes](https://docs.sentry.io/platforms/apple/guides/ios/migration.md#breaking-changes)

#### [Option Changes](https://docs.sentry.io/platforms/apple/guides/ios/migration.md#option-changes)

* `enableFileManagerSwizzling` is now a top-level non-experimental option and remains disabled by default.

* `enableDataSwizzling` is now a top-level option and is enabled by default.

* `enableLogs` is now a top-level non-experimental option and remains disabled by default (you must set it to `true` to enable logging).

* We increased the maximum attachment size to 200MB (previously 20MB)

* We removed the following methods and properties:

  * `inAppExclude` (it had no effect)
  * `integrations`
  * `defaultIntegrations()`
  * `enableTracing` (use `tracesSampleRate` or `tracesSampler` instead)
  * `getStoreEndpoint()`
  * `enablePerformanceV2` the behavior of this option is now enabled by default.

#### [Behavioral Breaking Changes](https://docs.sentry.io/platforms/apple/guides/ios/migration.md#behavioral-breaking-changes)

* The default trace context status is now `ok` instead of `undefined`.
* The `function` property on `SentryFrame` now defaults to `nil` instead of `"<redacted>"`
* The `value` and `type` properties on `SentryException` are now nullable; when `NSException` has no reason, `type` is set to `nil`
* We changed the type of the `http.response.status_code` attribute for spans to int
* We converted `SentryDsn` to Swift and removed the public header file `SentryDsn.h`

#### [Renamed APIs](https://docs.sentry.io/platforms/apple/guides/ios/migration.md#renamed-apis)

* We renamed `SentryStructuredLogLevel` to `SentryLogLevel`
* We renamed `SentryStructuredLogAttribute` to `SentryLogAttribute`

#### [Removed APIs](https://docs.sentry.io/platforms/apple/guides/ios/migration.md#removed-apis)

* We removed the `segment` property from `SentryTraceContext`, `SentryUser`, and `SentryBaggage`
* We removed the initializers from `SentryTraceContext`
* We removed `SentryDsn.getHash()`
* We removed `SentryFrame.instruction`

We removed the following deprecated APIs:

* `SentrySpan.setExtraValue(_:forKey:)`
* User feedback API (use the new [feedback API](https://docs.sentry.io/platforms/apple/guides/ios/user-feedback.md) instead)
* `Scope.useSpan()` (use `Scope.span` instead)
* `SentryDebugMeta.uuid` (use `debugID` instead)
* `SentryDebugMeta.name` (use `codeFile` instead)

We made the following classes and APIs private:

* `SentryEventDecoder` and `SentryEventDecodable`
* `SentryEnvelopeItemHeader`
* `SentryIntegrationProtocol`
* `SentrySession`
* `SentrySDKInfo`
* `SentryDebugImageProvider`

#### [Other breaking changes](https://docs.sentry.io/platforms/apple/guides/ios/migration.md#other-breaking-changes)

* We made the following classes `final`: `PreviewRedactOptions`, `SentryProfileOptions`, `SentryRedactViewHelper`, `SentryViewScreenshotOptions`, `SentryReplayOptions`, `SentryUserFeedbackConfiguration`, `SentryUserFeedbackFormConfiguration`, `SentryUserFeedbackThemeConfiguration`, `SentryUserFeedbackWidgetConfiguration`, `SentryFeedback`, and `SentryExperimentalOptions`

For a complete list of changes, see the [Changelog of version 9.0.0](https://github.com/getsentry/sentry-cocoa/releases/tag/9.0.0)

## [Migrating From 7.x to 8.x](https://docs.sentry.io/platforms/apple/guides/ios/migration.md#migrating-from-7x-to-8x)

Migrating to 8.x from 7.x includes a few breaking changes. We provide this guide to help you update your SDK. It's important to note that this version adds a dependency to Swift, and that we renamed the default branch on the [sentry-cocoa repository](https://github.com/getsentry/sentry-cocoa) from `master` to `main`.

### [Changes to Minimum OS Versions and Xcode](https://docs.sentry.io/platforms/apple/guides/ios/migration.md#changes-to-minimum-os-versions-and-xcode-1)

The minimum supported OS versions have been bumped to macOS 10.13, iOS 11, tvOS 11, and watchOS 4. We bumped the minimum Xcode version to 13.

### [Features Enabled by Default](https://docs.sentry.io/platforms/apple/guides/ios/migration.md#features-enabled-by-default-1)

The following features are now enabled by default:

* [The user interaction tracing integration](https://docs.sentry.io/platforms/apple/guides/ios/tracing/instrumentation/automatic-instrumentation.md#user-interaction-tracing)
* [The File I/O tracing integration](https://docs.sentry.io/platforms/apple/guides/ios/tracing/instrumentation/automatic-instrumentation.md#file-io-tracking)
* [Core Data tracing integration](https://docs.sentry.io/platforms/apple/guides/ios/tracing/instrumentation/automatic-instrumentation.md#core-data-tracing)
* [Capture failed requests](https://docs.sentry.io/platforms/apple/guides/ios/configuration/http-client-errors.md)
* [App Hangs](https://docs.sentry.io/platforms/apple/guides/ios/configuration/app-hangs.md) (not available for watchOS)

### [Changes to Grouping](https://docs.sentry.io/platforms/apple/guides/ios/migration.md#changes-to-grouping)

App Hang events might group differently as we now set the event stack trace snapshot property to `true`.

### [Rename OOM to Watchdog Termination](https://docs.sentry.io/platforms/apple/guides/ios/migration.md#rename-oom-to-watchdog-termination)

The OOM (out of memory integration) actually tracks [watchdog terminations](https://developer.apple.com/documentation/xcode/addressing-watchdog-terminations) based on heuristics. We renamed the integration to better reflect what it does.

### [Breaking Changes](https://docs.sentry.io/platforms/apple/guides/ios/migration.md#breaking-changes-1)

#### [Configuration Changes](https://docs.sentry.io/platforms/apple/guides/ios/migration.md#configuration-changes)

This version includes the following configuration changes:

* Rename `SentryOptions.enableAutoPerformanceTracking` to `SentryOptions.enableAutoPerformanceTracing`
* Rename `SentryOptions.enableUIViewControllerTracking` to `SentryOptions.enableUIViewControllerTracing`
* Rename `SentryOptions.enablePreWarmedAppStartTracking` to `SentryOptions.enablePreWarmedAppStartTracing`
* Rename `SentryOptions.enableFileIOTracking` to `SentryOptions.enableFileIOTracing`
* Rename `SentryOptions.enableCoreDataTracking` to `SentryOptions.enableCoreDataTracing`
* Rename `SentryOptions.enableOutOfMemoryTracking` to `SentryOptions.enableWatchdogTerminationTracking`

#### [Swift API Improvements](https://docs.sentry.io/platforms/apple/guides/ios/migration.md#swift-api-improvements)

We made some changes to make the API more ergonomic in Swift:

* Rename `SentrySDK.addBreadcrumb(crumb:)` to `SentrySDK.addBreadcrumb(_ crumb:)`
* Rename `SentryScope.add(_ crumb:)` to `SentryScope.addBreadcrumb(_ crumb:)`
* Rename `SentryScope.add(_ attachment:)` to `SentryScope.addAttachment(_ attachment:)`
* Rename `Client` to `SentryClient`

#### [Cleanup Public Classes](https://docs.sentry.io/platforms/apple/guides/ios/migration.md#cleanup-public-classes)

We cleaned up our public classes by removing a few functions and properties, that shouldn't be public, to make the API cleaner. In case we removed something you need, please [open an issue](https://github.com/getsentry/sentry-cocoa/issues/new/choose) on GitHub.

* Make `SpanProtocol.data` non nullable

* Mark `[SpanProtocol setExtraValue:forKey:]` as deprecated

* Make `SpanContext` immutable

  * Remove tags from `SpanContext`
  * Remove context property from `SentrySpan`

* Remove `SentryScope.apply(to:)`

* Remove `SentryScope.apply(to:maxBreadcrumb:)`

* Remove `[SentryOptions initWithDict:didFailWithError:]`

* Remove `[SentryOptions sdkInfo]`

* Make `SentrySession` and `SentrySDKInfo` internal

* Remove default attachment content type

* Remove `captureEnvelope` from `SentryHub` and `SentryClient`

* Remove confusing transaction tag

#### [SDK Inits](https://docs.sentry.io/platforms/apple/guides/ios/migration.md#sdk-inits)

We removed the version of `SentrySDK.startWithOptions` that took a dictionary, and renamed `SentrySDK.startWithOptionsObject` to `SentrySDK.startWithOptions`. The recommended way to initialize Sentry has not changed:

```swift
import Sentry

SentrySDK.start { options in
    options.dsn = "___PUBLIC_DSN___"
    // ...
}
```

#### [SentrySDK.close Is Now Blocking](https://docs.sentry.io/platforms/apple/guides/ios/migration.md#sentrysdkclose-is-now-blocking)

`SentrySDK.close` now calls flush, which is a blocking call.

## [Migrating From 6.x to 7.x](https://docs.sentry.io/platforms/apple/guides/ios/migration.md#migrating-from-6x-to-7x)

##### Important

We recommend updating to at least [7.5.3](https://github.com/getsentry/sentry-cocoa/releases/tag/7.5.3), because the HTTP instrumentation can lead to crashes. Alternatively, you can also [disable the feature](https://docs.sentry.io/platforms/apple/guides/ios/tracing/instrumentation/automatic-instrumentation.md#network-tracking).

Migrating to 7.x from 6.x includes a few breaking changes. We provide this guide to help you to update your SDK.

### [Configuration Changes](https://docs.sentry.io/platforms/apple/guides/ios/migration.md#configuration-changes-1)

This version includes the following configuration changes:

* Change the default maximum number of cached envelopes from 100 to 30. You can now configure this number with `SentryOptions.maxCacheItems`.
* When setting a value `SentryOptions.sampleRate` that is not >= 0.0 and <= 1.0 the SDK sets it to the default of 1.0 instead of keeping the set value.

### [Breaking Changes](https://docs.sentry.io/platforms/apple/guides/ios/migration.md#breaking-changes-2)

#### [Issue Grouping](https://docs.sentry.io/platforms/apple/guides/ios/migration.md#issue-grouping)

This version introduces a change to the grouping of issues. The SDK now sets the `inApp` flag for frames originating from only the main executable using [CFBundleExecutable](https://developer.apple.com/documentation/bundleresources/information_property_list/cfbundleexecutable). In previous versions, all frames originating from the application bundle were marked as `inApp`. This had the downside of marking frames of private frameworks inside the bundle as `inApp`. This problem is fixed now. Applications using static frameworks shouldn't be affected by this change. For more information read [mark in-app frames](https://docs.sentry.io/concepts/data-management/event-grouping/stack-trace-rules.md#mark-in-app-frames).

#### [Cleanup Public Classes](https://docs.sentry.io/platforms/apple/guides/ios/migration.md#cleanup-public-classes-1)

We cleaned up our public classes by removing a few functions and properties, that shouldn't be public, to make the API cleaner. In case we removed something you need, please [open an issue](https://github.com/getsentry/sentry-cocoa/issues/new/choose) on GitHub.

* Remove `SentrySDK.currentHub` and `SentrySDK.setCurrentHub`.
* Remove `SentryClient.storeEnvelope`, which is reserved for Hybrid SDKs.
* Make `closeCachedSessionWithTimestamp` private, which is reserved for internal use.
* Remove deprecated `SentryHub.getScope`. Use `SentryHub.scope` instead.
* Replace `SentryException.thread` with `SentryException.threadId` and `SentryException.stacktrace` to align with the [unified API](https://develop.sentry.dev/sdk/miscellaneous/unified-api/).
* Replace dict `SentryMechanism.meta` with new class `SentryMechanismMeta` and move `SenryNSError` to `SentryMechanismMeta` to align with the [unified API](https://develop.sentry.dev/sdk/miscellaneous/unified-api/).
* Change `SentryEvent.timestamp` to `nullable`.

### [SentryLogLevel](https://docs.sentry.io/platforms/apple/guides/ios/migration.md#sentryloglevel)

We replaced the `SentryLogLevel` with `SentryLevel`, renamed `logLevel` to `diagnosticLevel` on `SentryOptions` to align with other Sentry SDKs, and set the default `diagnosticLevel` to `SentryLevel.debug`. Furthermore, we removed setting the `logLevel` statically on the `SentrySDK`. Please use the `SentryOptions` to set the `diagnosticLevel` instead.

6.x

```swift
SentrySDK.start { options in
  options.logLevel = SentryLogLevel.verbose
}

// Or

SentrySDK.logLevel = SentryLogLevel.verbose
```

7.x

```swift
SentrySDK.start { options in
  options.diagnosticLevel = SentryLevel.debug
}
```

## [Migrating From 5.x to 6.x](https://docs.sentry.io/platforms/apple/guides/ios/migration.md#migrating-from-5x-to-6x)

Migrating to 6.x from 5.x includes a few breaking changes. We provide this guide to help you to update your SDK.

### [Configuration Changes](https://docs.sentry.io/platforms/apple/guides/ios/migration.md#configuration-changes-2)

This version includes the following configuration changes:

* [Auto Session Tracking](https://github.com/getsentry/sentry-cocoa/blob/7876949ca78aebfe7883432e35727993c5c30829/Sources/Sentry/include/SentryOptions.h#L101) is enabled by default. [This feature](https://docs.sentry.io/product/releases/health.md) is collecting and sending health data about the usage of your application.
* [Attach stack traces](https://github.com/getsentry/sentry-cocoa/blob/b5bf9769a158c66a34352556ade243e55f163a27/Sources/Sentry/Public/SentryOptions.h#L109) is enabled per default.
* We bumped the minimum iOS version to 9.0.
* Use a BOOL in SentryOptions instead of NSNumber to store booleans.
* We had previously removed the [enabled](https://github.com/getsentry/sentry-cocoa/blob/5.2.2/Sources/Sentry/include/SentryOptions.h#L63) option from SentryOptions, but we brought it back in version 6.0.7 with slightly changed functionality. Previously setting an empty or incorrect DSN also set `enabled` to `false`. This side effect is removed. Setting the DSN has no impact on `enabled`. If the DSN is nil or empty or `enabled` is set to `false` and the client won't send any data to Sentry.

### [Breaking Changes](https://docs.sentry.io/platforms/apple/guides/ios/migration.md#breaking-changes-3)

#### [Store Endpoint](https://docs.sentry.io/platforms/apple/guides/ios/migration.md#store-endpoint)

This version uses the [envelope endpoint](https://develop.sentry.dev/sdk/data-model/envelopes/). If you are using self-hosted Sentry, you must use Sentry version `>= v20.6.0` or higher. If you are using sentry.io, there is no impact. For this change, we also now cache events in envelopes on the disk. We decided not to migrate the few cached events from 5.x to 6.x into envelopes. Instead, we remove them from the disk. As a result, you might lose a few cached events when upgrading.

#### [SDK Inits](https://docs.sentry.io/platforms/apple/guides/ios/migration.md#sdk-inits-1)

We removed the [deprecated SDK inits](https://github.com/getsentry/sentry-cocoa/blob/5.2.2/Sources/Sentry/include/SentrySDK.h#L35-L47). The recommended way to initialize Sentry is now:

```swift
import Sentry

SentrySDK.start { options in
    options.dsn = "___PUBLIC_DSN___"
    // ...
}
```

#### [Cleanup Public Headers](https://docs.sentry.io/platforms/apple/guides/ios/migration.md#cleanup-public-headers)

We cleaned up our public headers and made most of our classes private. If you can't access one of the classes you need please [open an issue](https://github.com/getsentry/sentry-cocoa/issues/new/choose) and tell us your use case so we can evaluates whether to either make the class public again or provide another API for you.

#### [New type SentryId for eventId](https://docs.sentry.io/platforms/apple/guides/ios/migration.md#new-type-sentryid-for-eventid)

In 5.x, we used a nullable NSString to represent an event ID. The SDK, Hub, and Client returned this nullable NSString for the event ID to capture messages, events, errors, and so forth. In 6.x, we have a new type SentryId, which is not nullable, to represent an event ID. Instead of returning `nil` when an event couldn't be queued for submission we return `SentryId.empty`.

Example in 5.x:

```swift
import Sentry

let eventId = SentrySDK.capture(message: "A message")
if (nil != eventId) {
    // event was queued for submission
} else {
    // event wasn't queued for submission
}
```

Example in 6.x:

```swift
import Sentry

let eventId = SentrySDK.capture(message: "A message")
if (eventId != SentryId.empty) {
    // event was queued for submission
} else {
    // event wasn't queued for submission
}
```

#### [New type SentryMessage for Event.message](https://docs.sentry.io/platforms/apple/guides/ios/migration.md#new-type-sentrymessage-for-eventmessage)

In 6.x, we introduce a new type [SentryMessage](https://develop.sentry.dev/sdk/data-model/event-payloads/message/) for `event.message`. SentryMessage provides you the ability to pass a format string with parameters to Sentry, which can help group similar messages into the same issue.

Example in 5.x:

```swift
import Sentry

let event = Event()
event.message = "Hello World"
```

Example in 6.x:

```swift
import Sentry

let event = Event()
event.message = SentryMessage(formatted: "Hello World")
```

#### [Make Scope nonnull for capture methods](https://docs.sentry.io/platforms/apple/guides/ios/migration.md#make-scope-nonnull-for-capture-methods)

In 5.x, you could pass a nullable scope to capture methods of the SDK, Hub, and Client, such as `SentrySdk.captureMessage()`. In 6.x, we changed the Scope to nonnull and provide overloads for the Hub and the Client.

Please see the [Changelog](https://github.com/getsentry/sentry-cocoa/blob/main/CHANGELOG.md) for a complete list of changes.

## [Upgrading From 4.x to 5.x](https://docs.sentry.io/platforms/apple/guides/ios/migration.md#upgrading-from-4x-to-5x)

The samples below illustrate how the SDK works:

### [Initialization](https://docs.sentry.io/platforms/apple/guides/ios/migration.md#initialization)

Example in 4.x:

```swift
do {
    Client.shared = try Client(dsn: "___PUBLIC_DSN___")
    try Client.shared?.startCrashHandler()
} catch let error {
    print("\(error)")
}
```

Example in 5.x:

```swift
SentrySDK.start(options: [
    "dsn": "___PUBLIC_DSN___",
    "debug": true
])
```

### [Add Breadcrumb](https://docs.sentry.io/platforms/apple/guides/ios/migration.md#add-breadcrumb)

Example in 4.x:\`

```swift
Client.shared?.breadcrumbs.add(Breadcrumb(level: .info, category: "test"))
```

Example in 5.x:

```swift
SentrySDK.addBreadcrumb(Breadcrumb(level: .info, category: "test"))
```

### [CaptureMessage with tags/environment/extra](https://docs.sentry.io/platforms/apple/guides/ios/migration.md#capturemessage-with-tagsenvironmentextra)

Example in 4.x:

```swift
let event = Event(level: .debug)
event.message = "Test Message"
event.environment = "staging"
event.extra = ["ios": true]
Client.shared?.send(event: event)
```

Example in 5.x:

```swift
SentrySDK.capture(message: "Test Message") { (scope) in
    scope.setEnvironment("staging")
    scope.setExtras(["ios": true])
    let u = Sentry.User(userId: "1")
    u.email = "tony@example.com"
    scope.setUser(u)
}
```

### [setUser](https://docs.sentry.io/platforms/apple/guides/ios/migration.md#setuser)

Example in 4.x:

```swift
let u = User(userId: "1")
u.email = "tony@example.com"
Client.shared?.user = user
```

Example in 5.x:

```swift
let u = Sentry.User(userId: "1")
u.email = "tony@example.com"
SentrySDK.setUser(u)
```
