Represents why an entitlement was not granted when presenting an offer. These are business outcomes, not errors — a user dismissing the sheet or having no eligible offers is a valid result. Genuine failures (network, decoding, SDK not configured) are thrown as an EncoreError from try await show(), never delivered here.
NotGrantedReason is a String-backed enum, so each case has a stable rawValue you can log.
Definition
Cases
| Case | Category | Description |
|---|
.userTappedClose | User | User tapped the close / “No thanks” button on the sheet. |
.userSwipedDown | User | User swiped down to dismiss the sheet. |
.userTappedOutside | User | User tapped the backdrop outside the sheet. |
.userCancelled | User | User cancelled mid-flow. |
.lastOfferDeclined | User | User declined the last available offer in the carousel. |
.dismissed | User | Generic dismissal when the specific gesture is unknown. |
.noOffersAvailable | System | No offers matched this user (targeting, caps reached, or already claimed). |
.unsupportedOS | System | The device’s iOS version can’t present the SwiftUI offer sheet. Returned immediately on iOS 15–16 (the sheet UI requires iOS 17+); no UI is shown. |
.experimentControl | Experiment | The user is in the Control cohort of a Net Conversion Lift experiment. A “ghost trigger” exposure was logged for measurement, but no UI was shown. Treat this exactly like a normal not-granted outcome — run your original flow. |
Usage
The supported path is the PresentationResult returned by try await show(). Branch on the reason when you need analytics or special handling; otherwise just proceed with the user’s original action (your onPassthrough handler already does this).
For most apps you can treat all not-granted reasons identically — just resume the original action. Distinguish cases only for analytics or experiment reporting.
- PresentationResult — the result returned by
try await show().
- Errors — genuine failures are thrown as
EncoreError, not surfaced as a NotGrantedReason.