Docs
grovs.io Start for free

iOS SDK 3.1

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

Requires iOS SDK 3.1.0

3.1.0 adds push campaigns and 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 to 3.1.0.
  2. Handle the new GrovsError case if you switch over it.
  3. Check your GrovsDelegate methods for "nearly matches" warnings.
  4. Remove the messages inbox from your UI.
  5. Rename custom events that use a reserved name.
  6. Check the other behavior changes.
  7. Optional: set up push campaigns and react to 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.

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.

Last updated 2026-10-26
Was this page helpful?