# iOS SDK 3.1

> What changes when you move the Grovs iOS SDK from 3.0 to 3.1.

Source: https://docs.grovs.io/docs/upgrade-guides/ios-3-1

3.1.0 adds [push campaigns](https://docs.grovs.io/docs/sdk/ios/push-notifications) and [in-app messages](https://docs.grovs.io/docs/sdk/ios/in-app-messages), and removes the messages inbox. Most apps bump the version and fix what the compiler flags.

Requirements are unchanged: **iOS 13.0**, Swift 5.9 (Xcode 15).

## Checklist

1. [Bump the dependency](#1-bump-the-version) to 3.1.0.
2. [Handle the new `GrovsError` case](#2-handle-grovserrorinappdisplayfailed) if you `switch` over it.
3. [Check your `GrovsDelegate` methods](#3-check-your-grovsdelegate-methods) for "nearly matches" warnings.
4. [Remove the messages inbox](#4-remove-the-messages-inbox) from your UI.
5. [Rename custom events that use a reserved name](#5-rename-reserved-event-names).
6. [Check the other behavior changes](#6-other-behavior-changes).
7. Optional: [set up push campaigns](https://docs.grovs.io/docs/sdk/ios/push-notifications) and [react to in-app messages](https://docs.grovs.io/docs/sdk/ios/in-app-messages).

## 1. Bump the version

**Swift Package Manager:** set the Grovs package rule to **Up to Next Major Version** from `3.1.0`. In a `Package.swift`:

```swift
.package(url: "https://github.com/grovs-io/grovs-iOS.git", from: "3.1.0")
```

**CocoaPods:** in your `Podfile`:

```ruby
pod 'Grovs', '~> 3.1'
```

For campaign images in push notifications, add the new `GrovsNotificationService` product or pod to a Notification Service Extension target. See [Campaign images](https://docs.grovs.io/docs/sdk/ios/push-notifications#4-campaign-images-optional).

## 2. Handle `GrovsError.inAppDisplayFailed`

New case `inAppDisplayFailed` (5): an in-app message couldn't be drawn. An exhaustive `switch` won't compile until you handle it:

```swift
func grovsDidEncounterError(_ error: GrovsError, message: String) {
    switch error {
    case .authenticationFailed, .networkRequestFailed, .eventDispatchFailed, .linkGenerationFailed:
        Log.warning("grovs: \(message)")
    case .inAppDisplayFailed:
        Log.info("grovs in-app: \(message)")
    }
}
```

## 3. Check your `GrovsDelegate` methods

`GrovsDelegate` and the new `GrovsInAppDelegate` are now `@objc` protocols with `@objc optional` methods, so Objective-C apps can adopt them. `GrovsError` is an `@objc` enum and `Grovs` an `NSObject`.

Most apps stay source-compatible, but the Swift default implementation of `grovsDidEncounterError` is gone. A delegate method that doesn't match the signature exactly compiles with only a "nearly matches" warning and is never called. Build once and check those warnings.

## 4. Remove the messages inbox

The inbox is gone on the device and the backend. In-app messages replace it.

- `Grovs.displayMessagesViewController(completion:)` and `displayMessagesViewController(completion:onFailure:)` are deprecated and show nothing. They call `completion` once on the main thread and never call `onFailure`.
- `Grovs.numberOfUnreadMessages(completion:)` is deprecated and always yields `0`.
- The SDK no longer displays dashboard messages automatically, calls the inbox endpoints, or ships the inbox XIBs.
- A push carrying only `grovs_notification_id` is no longer a Grovs push: `isGrovsNotification(userInfo:)` and the notification handlers return `false` for it. Remove any code that opened the inbox from such a push.

Remove inbox buttons and unread badges. Campaigns built under **Engage** in the dashboard show on their own once the SDK is configured.

## 5. Rename reserved event names

`track(_:)` now refuses the same names as the backend. Rename any custom event that uses one:

`in_app_viewed`, `in_app_clicked`, `in_app_dismissed`, `in_app_answered`, `in_app_commented`, `in_app_held`, `push_open`, `push_delivered`, `push_held`, `journey_entered`, `journey_held`, `journey_path`.

## 6. Other behavior changes

- **Push opens.** Call `handleNotificationOpen(userInfo:)` only for a tap on a notification, never from `didReceiveRemoteNotification` or `willPresent`, or each delivery counts as an open. A tap on a push that carries a Grovs link counts once, as `push_open`: the link isn't also counted as a link open, and later events aren't attributed to it.
- **Screen tracking.** A view controller class named exactly `ViewController` (or `Controller`) is now tracked under that name. Before, its cleaned name was empty and it was never tracked.
- **Push token.** A push token set before authentication no longer clears the user's identifier and attributes on the server.
- **Other apps' URL schemes.** `handleAppDelegate(open:options:)` returns `false` for a custom scheme other than your project's Grovs URL scheme, such as a sign-in callback, so a handler after Grovs in an `||` chain still gets it.
- **Purchases.** `logInAppPurchase` and `logCustomPurchase` save the purchase before sending it, including before authentication. Once configured and enabled, a `false` completion means it's kept and retried, so don't log it again.
- **Events before authentication.** `track` and `trackScreenView` calls made before authentication completes are stored on disk, not held in memory.
- **Locked after reboot.** On a background launch before the first unlock, `configure` waits until the device is unlocked or the app becomes active.
- **Privacy manifest.** It now declares the file timestamp reason (C617.1) for the SDK's disk cache. Review your App Store privacy details if you copy them from the manifest.
- **CocoaPods.** `Grovs.podspec` compiles only the main SDK; the extension code ships in its own pod, `GrovsNotificationService`.

## Verify the upgrade

1. Build with no "nearly matches" warnings on your delegate methods.
2. Open a Grovs link and check that `grovsReceivedPayloadFromDeeplink` still receives it.
3. In the dashboard, create an in-app campaign triggered on app open, use **Send test** with your own user identifier, and bring the app to the foreground. The message shows at the next sync.
4. If you use push, send a campaign to your own user identifier and tap it. The open shows in the campaign report.

Full list of changes: [iOS CHANGELOG](https://github.com/grovs-io/grovs-iOS/blob/main/CHANGELOG.md).
