Components-based paywall: conditional intro-offer row is missing in the first
render, even though eligibility is already cached
## Setup
- purchases-ios 5.70.0, SwiftUI, iOS 18
- Components-based paywall built in the editor, presented with
RevenueCatUI.PaywallView(offering:displayCloseButton:)
- In the editor, a text row ("7 days free trial") is hidden by default and
shown only when the customer is eligible for the introductory offer, by paywall logic.
- Product identifiers below are redacted.
## Problem
The paywall opens with that row missing and shows it one render pass later.
There is no transition or animation involved — the row simply is not there in
the first frame and is there in the next.
The plan card grows upward, so nothing below it moves and the purchase button
stays in place. It is purely cosmetic. Still, what appears late is the offer
itself, which is the one line we would want visible from the very first frame.
## What I tried
Resolving eligibility before rendering, so the answer is already in the SDK
cache by the time PaywallView is created:
let ids = offering.availablePackages.map(\.storeProduct.productIdentifier)
_ = await Purchases.shared.checkTrialOrIntroDiscountEligibility(
productIdentifiers: ids
)
// only afterwards set the offering that drives PaywallView
The same call also runs at app start, right after offerings().
## What the log shows
Both lookups are served from cache — there is no network round trip:
Vending Offerings from memory cache
Found cached trial or intro eligibility for products:
["pro_yearly", "pro_monthly"]
...
Found cached trial or intro eligibility for products:
["pro_monthly", "pro_yearly"]
The second line is the paywall's own evaluation after presentation. So the
data is available immediately, and the row still only appears in the second
render pass.
## Questions
1. Why does a components-based paywall perform an initial render with the
intro-offer condition unresolved, even when eligibility is already in the
SDK cache before PaywallView is created?
2. Is there a way to have the first render include the resolved condition —
an API to hand the eligibility in, or an option to defer presentation
until it is known?
3. If this is expected behaviour, is there a recommended pattern for
conditional content on a paywall so that it does not change after the
first frame?
