iOS SDK 3.0
What changes when you move the Grovs iOS SDK from 2.x to 3.0.
3.0.0 removes four public types that were SDK internals and changes one closure signature. Most apps bump the version, decide on automatic screen tracking, and check 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's 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 your project's Package Dependencies, select Grovs and set the rule to Up to Next Major Version from 3.0.0. A rule pinned to 2.x won't pick up 3.0. In a Package.swift:
.package(url: "https://github.com/grovs-io/grovs-iOS.git", from: "3.0.0")CocoaPods: in your Podfile, then run pod update Grovs:
pod 'Grovs', '~> 3.0'2. Decide on automatic screen tracking
This changes behavior with no code change 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 for screen analytics. Events & Screen Tracking explains how names are chosen and overridden.
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 public in 2.x are internal in 3.0. They were implementation details, but code that referenced or subclassed one won't build:
| 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 differs 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 kept collecting lifecycle events. In 3.0, while disabled, the SDK doesn't authenticate, resolve the device, or send lifecycle events, custom events, screen views or purchases. Changes to userIdentifier, userAttributes, pushToken and screen aliases are held until you re-enable it. Queued events 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:
// 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 isn't persisted, so pass your stored consent on every launch. A disabled configure reports false without authenticating. 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 prompt. It happens only if the backend reports recent clicks on copy-to-clipboard links for your project (currently a 48-hour window) and the clipboard holds a web URL. If you never enable copy-to-clipboard for the 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. Other schemes are ignored. Switch links that use a custom scheme such as yourapp:// to a universal link.
The SDK ships a privacy manifest. PrivacyInfo.xcprivacy is bundled for Swift Package Manager and CocoaPods and 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 Apple's identifier. The SDK sends the hardware identifier (for example iPhone15,2) instead of a mapped name, so new devices need no SDK update.
Queued events survive the upgrade. 3.0 reads 2.x event archives, so nothing pending 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. The messages inbox was later removed in 3.1.
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. If you kept automatic screen tracking, check that screen views appear in the dashboard under names you recognize. Rename any that read like class names with setScreenAliases.
See also
- Quick Start: full configuration reference
- API Reference: every property, method, and type
- SDK Releases: where release notes are published