Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Delay file system access when app is prewarmed while locked to avoid losing entitlements and wrong user ids #4623

Open
10 of 12 tasks
KaiOelfke opened this issue Dec 28, 2024 · 3 comments
Labels

Comments

@KaiOelfke
Copy link

Describe the bug

For certain versions of iOS under certain conditions iOS can prewarm apps. RevenueCat writes about this in the documentation. There's also some community discussion.

The documentation only writes about issues when not using anonymous identifiers. But the problem scope is bigger. When an app is launched for prewarming, access to the file system is not possible, which includes UserDefaults (which are used by RevenueCat during the configuration).

This resulted in end users reporting losing access (they lost entitlements and got a new anonymous ID) after a reboot until they restored purchases. I fixed with a workaround of detecting the prewarming state and in this case configuring RevenueCat later. But as prewarming will only get more common with the popularity of live activities and the dynamic island a mission critical SDK like RevenueCat should mitigate this internally. Most developers don't know about prewarming and the behavior of completeFileProtectionUntilFirstUserAuthentication, which is the default for most files. So this results in very difficult bugs and frustrated end users.

  1. Environment
    1. Platform: iOS
    2. SDK version: 5.14.3
    3. StoreKit version:
      • StoreKit 1 (default on versions <5.0.0. Can be enabled in versions >=5.0.0 with .with(storeKitVersion: .storeKit1))
      • StoreKit 2 (default on versions >=5.0.0)
    4. OS version: iOS 18.1.1
    5. Xcode version: 16.1
    6. Device and/or simulator:
      • Device
      • Simulator
    7. Environment:
      • Sandbox
      • TestFlight
      • Production
    8. How widespread is the issue. Percentage of devices affected.
  2. Debug logs that reproduce the issue. Complete logs with Purchases.logLevel = .verbose will help us debug this issue.

I can't access logs as it's not available, when iOS does prewarming while the device is locked after the reboot.

  1. Steps to reproduce, with a description of expected vs. actual behavior
  • Create a sample app with a live activity for the lock screen / dynamic island and add RevenueCat SDK
  • Configure Purchases in AppDelegate init or didFinishLaunchingWithOptions
  • Run app and schedule live activity, lock device and allow live activities on the lock screen
  • Reboot device
  • Wait up to 60 sec while locked after reboot
  • Unlock device
  • Open sample app

Expected: RevenueCat and UserDefaults works normally
Actual: All UserDefaults.standard accesses return wrong values resulting in all kinds of other potential issues, RevenueCat cache is returning wrong values

I made a sample here that still needs adjustment to use and configure RevenueCat.

https://github.com/pointfreeco/swift-composable-architecture/discussions/3440

  1. Other information (e.g. stacktraces, related issues, suggestions how to fix, links for us to have context, eg. stackoverflow, etc.)

  2. Additional context
    Add any other context about the problem here.

@KaiOelfke KaiOelfke added the bug label Dec 28, 2024
@RCGitBot
Copy link
Contributor

👀 We've just linked this issue to our internal tracker and notified the team. Thank you for reporting, we're checking this out!

@KptnTanyel
Copy link

@KaiOelfke This blog post goes into detail about the same issue, that UserDefaults became unreliable. Especially in the context of Live Activities. There's also a proposed solution to this dilemma in a follow-up blog post - a replacement for the UserDefaults.

This obviously doesn't help, if dependencies are relying on UserDefaults. RC advices in their documentation to move the initialisation of the SDK from didFinishLaunchingWithOptions to the viewDidLoad of the first ViewController.

In certain cases on iOS 15 devices, iOS may prewarm your app - this essentially means your app will be launched silently in the background to improve app launch times for your users.
If you are not using RevenueCat's anonymous IDs as described above, and are instead providing your own app user ID on configuration, do not call configure in application:didFinishLaunchingWithOptions:. Instead, call the configure method in your root view controller's initialization method.

Source

I still wonder if RC is aware of how unreliable UserDefaults are at times. It seems that UserDefaults are unavailable at different times than just during the prewarm period.

There is also this discussion in the Apple's developer forum, where one of Apple's engineers is clarifying a few things about prewarming.

It would be really nice to have a follow-up on this topic, since we can't follow RC's internal tickets.

@KaiOelfke
Copy link
Author

Thank you. I know the blog post. I can't use this library for some internal reasons and have my own workarounds in place. Using such a library isn't enough anyway. It's necessary to delay the setup of the RevenueCat SDK until this bug is addressed, if an app must support prewarming (e.g. has live activities). Depending on the iOS version UserDefaults will not work until the the next app launch or until the file system becomes available. With this library you can protect your app data, but it's still a very broken experience, if a given user suddenly lost all his entitlements etc. This is exactly what happened to my users until I added the logic to delay RC SDK setup during prewarming until the device is unlocked.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants