iOS SDK 3.0
What changes when you move the Grovs iOS SDK from 2.x to 3.0
3.0.0 is a major release: it removes four public types that were SDK internals and changes one closure signature. Most apps upgrade by bumping the version, deciding on automatic screen tracking, and checking how they use setSDK(enabled:).
Requirements are unchanged: iOS 13.0, Swift 5.9 (Xcode 15).
Checklist
- Bump the dependency to 3.0.0.
- Decide on automatic screen tracking — it is on by default.
- Remove references to types that are now internal.
- Update
GrovsDeviceDataClosureClosureif you name it. - Review your consent gating —
setSDK(enabled: false)now stops everything, andconfigurehas anenabled:parameter. - Check the other behavior changes — the clipboard paste prompt, links in messages, and your App Store privacy details.
1. Bump the version
Swift Package Manager — in Xcode, open your project's Package Dependencies, select the Grovs package, and set the rule to Up to Next Major Version from 3.0.0. A rule pinned to 2.x will not pick up 3.0 on its own. In a Package.swift:
.package(url: "https://github.com/grovs-io/grovs-iOS.git", from: "3.0.0")CocoaPods — in your Podfile:
pod 'Grovs', '~> 3.0'Then run pod update Grovs.
2. Decide on automatic screen tracking
This changes behavior without any code edit on your side.
autoTrackScreenViews defaults to true. An app that only recompiles starts hooking UIViewController.viewDidAppear and sending a screen_view event for each screen.
Keep it if you want screen analytics — see Events & Screen Tracking for how names are chosen and how to override them.
To opt out, pass false:
Grovs.configure(
APIKey: "your-api-key",
useTestEnvironment: false,
autoTrackScreenViews: false,
delegate: self
)Existing configure calls compile unchanged — every new parameter has a default.
3. Remove references to types that are now internal
Four types were public in 2.x and are internal in 3.0. They were SDK implementation details, but if your code referenced or subclassed one, the build fails:
| Type | Was | Replacement |
|---|---|---|
DataCache | open class, plus DataCache.instance | None. Use your own cache. |
BaseService | open class | None. Use URLSession directly. |
ImageFormat | public enum | None. |
JSONClosure | public typealias | Define your own closure type. |
Everything else public in 2.x is still public and source-compatible.
4. Update GrovsDeviceDataClosureClosure if you use it
The typealias gained a leading success flag so a transport failure can be told apart from an empty result:
// 2.x
(_ dictionary: [String: Any]?, _ link: String?, _ tracking: [String: Any]?) -> Void
// 3.0
(_ success: Bool, _ dictionary: [String: Any]?, _ link: String?, _ tracking: [String: Any]?) -> VoidNo public method uses this type. If you declared a variable or parameter with it, add the leading parameter.
5. Review your consent gating
setSDK(enabled: false) now stops everything. In 2.x it blocked link generation and deep link resolution but left lifecycle event collection running. In 3.0, while disabled, the SDK does not authenticate, resolve the device, or send lifecycle events, custom events, screen views, or purchases. Changes to userIdentifier, userAttributes, pushToken, and screen aliases are held and sent when you enable it again. Events already queued stay on disk.
Start disabled with enabled:. Calling setSDK(enabled: false) right after configure is too late — configuring starts the first round of collection. If you gate on consent, pass it to configure instead:
// 2.x — collection has already started when setSDK runs
Grovs.configure(APIKey: "your-api-key", useTestEnvironment: false, delegate: self)
if !hasConsent {
Grovs.setSDK(enabled: false)
}
// 3.0
Grovs.configure(APIKey: "your-api-key", useTestEnvironment: false, enabled: hasConsent, delegate: self)The value is not persisted, so pass your stored consent on every launch. A disabled configure reports false to its completion without attempting authentication — if that completion feeds your error reporting, don't count it as a failure. See Privacy & Consent.
6. Check the other behavior changes
Clipboard-assisted deferred deep linking is on. On the first launch after a fresh install, the SDK can read a Grovs link from the clipboard to attribute the install, and iOS may show its paste confirmation. This only happens if the backend reports recent clicks on copy-to-clipboard links for your project (currently a 48-hour window) and the device's clipboard holds a web URL. If you never enable copy-to-clipboard for your project or its links, the prompt never appears. See Clipboard-assisted deferred deep linking.
Links in messages are restricted. Message content now opens only http, https, mailto, tel, and sms links. Any other scheme is ignored — if your messages link to a custom scheme such as yourapp://, switch those to a universal link.
The SDK ships a privacy manifest. PrivacyInfo.xcprivacy is bundled for Swift Package Manager and CocoaPods and is merged into your app's privacy report. Check your App Store privacy details against what the SDK collects.
Logging moved to os_log. setDebug(level:) works as before. In release builds, message content is marked private and appears as <private> in Console.app.
Device model is reported as Apple's identifier. The SDK sends the hardware identifier (for example iPhone15,2) instead of a name mapped inside the SDK, so new devices are reported without an SDK update.
Queued events survive the upgrade. 3.0 reads event archives written by 2.x, so nothing pending on a user's device is lost.
What's new in 3.0
Nothing here is required:
- Custom events and screen tracking —
track,trackScreenView, global tags, screen aliases,.grovsScreen()for SwiftUI, andGrovsScreenTrackingfor UIKit. - Consent gating — the
enabled:parameter onconfigure, and asetSDK(enabled:)that stops all collection. - Error callbacks — an optional
grovsDidEncounterError(_:message:)onGrovsDelegate. It has a default implementation, so existing delegates need no change. - Clipboard-assisted deferred deep linking — deterministic install attribution on first launch, with
clipboardDomainsfor custom link domains. copyToClipboardiOS/copyToClipboardAndroid— per-link override of the project's copy-to-clipboard setting.displayMessagesViewController(completion:onFailure:)— tells a dismissal apart from a presentation that never happened.
Verifying the upgrade
Turn on info logging before configure and confirm the completion reports true:
Grovs.setDebug(level: .info)
Grovs.configure(APIKey: "your-api-key", useTestEnvironment: true, delegate: self) { success in
print("Grovs configured: \(success)")
}Then check that deep links still reach grovsReceivedPayloadFromDeeplink, and — if you kept automatic screen tracking — that screen views appear in the dashboard under names you recognize. Use setScreenAliases to rename any that read like class names.
See also
- Quick Start — full configuration reference
- API Reference — every property, method, and type
- SDK Releases — where release notes are published