Question

iOS 15/Xcode 13 [[RCPurchases sharedPurchases] offeringsWithCompletionBlock:] is never called

  • 24 September 2021
  • 28 replies
  • 446 views

Userlevel 1
Badge +1

iPadOS 15 running app from Xcode fails to return any products. Restore Purchases also fails to return.

Rebooting iPad allows it to work first time only.

This issue is specifically relating to auto-renewing subscriptions.

Built using Xcode Version 13.0 (13A233)

No issue with same code on iOS 14.

Success and failure logs follow.

Success:

2021-09-24 16:17:50.773181+0800 ZeroTime[345:4478] [Purchases] - DEBUG: ℹ️ Debug logging enabled
2021-09-24 16:17:50.773293+0800 ZeroTime[345:4478] [Purchases] - DEBUG: ℹ️ SDK Version - 3.12.4
2021-09-24 16:17:50.773336+0800 ZeroTime[345:4478] [Purchases] - DEBUG: 👤 Initial App User ID - (null)
2021-09-24 16:17:50.777445+0800 ZeroTime[345:4478] [Purchases] - DEBUG: ℹ️ Sending latest PurchaserInfo to delegate.
2021-09-24 16:17:50.778858+0800 ZeroTime[345:4478] didReceiveUpdatedPurchaserInfo: <PurchaserInfo
 originalApplicationVersion: (null),
 latestExpirationDate: (null)
 activeEntitlements: {
},
 activeSubscriptions: {
},
 nonConsumablePurchases: {(
)},
 requestDate: 2021-09-24 08:12:16 +0000
 firstSeen: 2021-09-24 08:12:16 +0000,
originalAppUserId: $RCAnonymousID:cada631d501147efa13dd3dd44741b9c,
entitlements: {
},
> {
    originalAppUserId = "$RCAnonymousID:cada631d501147efa13dd3dd44741b9c";
    willRenew = No;
}
2021-09-24 16:17:50.778946+0800 ZeroTime[345:4478] [Purchases] - DEBUG: ℹ️ Delegate set
2021-09-24 16:17:51.070276+0800 ZeroTime[345:4478] [Purchases] - DEBUG: ℹ️ Vending PurchaserInfo from cache.
2021-09-24 16:17:51.070546+0800 ZeroTime[345:4478] purchaserInfo: <PurchaserInfo
 originalApplicationVersion: (null),
 latestExpirationDate: (null)
 activeEntitlements: {
},
 activeSubscriptions: {
},
 nonConsumablePurchases: {(
)},
 requestDate: 2021-09-24 08:12:16 +0000
 firstSeen: 2021-09-24 08:12:16 +0000,
originalAppUserId: $RCAnonymousID:cada631d501147efa13dd3dd44741b9c,
entitlements: {
},
>
2021-09-24 16:17:51.070670+0800 ZeroTime[345:4478] [Purchases] - DEBUG: ℹ️ applicationDidBecomeActive
2021-09-24 16:17:51.079287+0800 ZeroTime[345:4655] [Purchases] - DEBUG: ℹ️ There are no requests currently running, starting request GET /subscribers/$RCAnonymousID0X0P+0cada631d501147efa13dd3dd44741b9c
2021-09-24 16:17:51.079500+0800 ZeroTime[345:4655] [Purchases] - DEBUG: ℹ️ API request started: GET /v1/subscribers/$RCAnonymousID:cada631d501147efa13dd3dd44741b9c
2021-09-24 16:17:51.081741+0800 ZeroTime[345:4655] [Purchases] - DEBUG: ℹ️ There's a request currently running and 0 requests left in the queue, queueing GET /subscribers/$RCAnonymousID0X0P+0cada631d501147efa13dd3dd44741b9c/offerings
2021-09-24 16:17:52.576457+0800 ZeroTime[345:4653] [Purchases] - DEBUG: ℹ️ API request completed with status: GET /v1/subscribers/$RCAnonymousID:cada631d501147efa13dd3dd44741b9c 304
2021-09-24 16:17:52.580989+0800 ZeroTime[345:4653] [Purchases] - DEBUG: ℹ️ Serial request done: GET /subscribers/$RCAnonymousID0X0P+0cada631d501147efa13dd3dd44741b9c, 1 requests left in the queue
2021-09-24 16:17:52.581240+0800 ZeroTime[345:4653] [Purchases] - DEBUG: ℹ️ Starting the next request in the queue, <RCHTTPRequest: httpMethod=GET
path=/subscribers/$RCAnonymousID0X0P+0cada631d501147efa13dd3dd44741b9c/offerings
requestBody=(null)
headers={
    Authorization = "Bearer vXpx...";
}
retried=0
>
2021-09-24 16:17:52.582667+0800 ZeroTime[345:4653] [Purchases] - DEBUG: ℹ️ There are no requests currently running, starting request GET /subscribers/$RCAnonymousID0X0P+0cada631d501147efa13dd3dd44741b9c/offerings
2021-09-24 16:17:52.582820+0800 ZeroTime[345:4653] [Purchases] - DEBUG: ℹ️ API request started: GET /v1/subscribers/$RCAnonymousID:cada631d501147efa13dd3dd44741b9c/offerings
2021-09-24 16:17:52.993356+0800 ZeroTime[345:4652] [Purchases] - DEBUG: ℹ️ API request completed with status: GET /v1/subscribers/$RCAnonymousID:cada631d501147efa13dd3dd44741b9c/offerings 304
2021-09-24 16:17:52.994226+0800 ZeroTime[345:4652] [Purchases] - DEBUG: ℹ️ Requesting products from the store with identifiers: {(
    "io.smudge.ZeroTime.SUB.Yearly",
    "io.smudge.ZeroTime.SUB.Monthly"
)}
2021-09-24 16:17:52.998017+0800 ZeroTime[345:4652] [Purchases] - DEBUG: ℹ️ Serial request done: GET /subscribers/$RCAnonymousID0X0P+0cada631d501147efa13dd3dd44741b9c/offerings, 0 requests left in the queue
2021-09-24 16:17:53.062085+0800 ZeroTime[345:4652] [Purchases] - DEBUG: ℹ️ Products request finished.
2021-09-24 16:17:53.062174+0800 ZeroTime[345:4652] [Purchases] - DEBUG: 💰 Retrieved SKProducts: 
2021-09-24 16:17:53.062242+0800 ZeroTime[345:4652] [Purchases] - DEBUG: 💰 io.smudge.ZeroTime.SUB.Monthly - <SKProduct: 0x283cbdc10>
2021-09-24 16:17:53.062297+0800 ZeroTime[345:4652] [Purchases] - DEBUG: 💰 io.smudge.ZeroTime.SUB.Yearly - <SKProduct: 0x283cbd820>
2021-09-24 16:17:53.062345+0800 ZeroTime[345:4652] [Purchases] - DEBUG: ℹ️ 1 completion handlers waiting on products
2021-09-24 16:17:58.074549+0800 ZeroTime[345:4478] [Purchases] - DEBUG: ℹ️ Vending Offerings from cache


Failure: 

2021-09-24 16:13:05.996820+0800 ZeroTime[503:10344] [Purchases] - DEBUG: ℹ️ Debug logging enabled
2021-09-24 16:13:05.996935+0800 ZeroTime[503:10344] [Purchases] - DEBUG: ℹ️ SDK Version - 3.12.4
2021-09-24 16:13:05.996978+0800 ZeroTime[503:10344] [Purchases] - DEBUG: 👤 Initial App User ID - (null)
2021-09-24 16:13:06.000895+0800 ZeroTime[503:10344] [Purchases] - DEBUG: ℹ️ Sending latest PurchaserInfo to delegate.
2021-09-24 16:13:06.001788+0800 ZeroTime[503:10344] didReceiveUpdatedPurchaserInfo: <PurchaserInfo
 originalApplicationVersion: (null),
 latestExpirationDate: (null)
 activeEntitlements: {
},
 activeSubscriptions: {
},
 nonConsumablePurchases: {(
)},
 requestDate: 2021-09-24 08:12:16 +0000
 firstSeen: 2021-09-24 08:12:16 +0000,
originalAppUserId: $RCAnonymousID:cada631d501147efa13dd3dd44741b9c,
entitlements: {
},
> {
    originalAppUserId = "$RCAnonymousID:cada631d501147efa13dd3dd44741b9c";
    willRenew = No;
}
2021-09-24 16:13:06.001865+0800 ZeroTime[503:10344] [Purchases] - DEBUG: ℹ️ Delegate set
2021-09-24 16:13:06.280716+0800 ZeroTime[503:10344] [Purchases] - DEBUG: ℹ️ Vending PurchaserInfo from cache.
2021-09-24 16:13:06.280911+0800 ZeroTime[503:10344] purchaserInfo: <PurchaserInfo
 originalApplicationVersion: (null),
 latestExpirationDate: (null)
 activeEntitlements: {
},
 activeSubscriptions: {
},
 nonConsumablePurchases: {(
)},
 requestDate: 2021-09-24 08:12:16 +0000
 firstSeen: 2021-09-24 08:12:16 +0000,
originalAppUserId: $RCAnonymousID:cada631d501147efa13dd3dd44741b9c,
entitlements: {
},
>
2021-09-24 16:13:06.281064+0800 ZeroTime[503:10344] [Purchases] - DEBUG: ℹ️ applicationDidBecomeActive
2021-09-24 16:13:06.287826+0800 ZeroTime[503:10402] [Purchases] - DEBUG: ℹ️ There are no requests currently running, starting request GET /subscribers/$RCAnonymousID0X0P+0cada631d501147efa13dd3dd44741b9c
2021-09-24 16:13:06.287919+0800 ZeroTime[503:10402] [Purchases] - DEBUG: ℹ️ API request started: GET /v1/subscribers/$RCAnonymousID:cada631d501147efa13dd3dd44741b9c
2021-09-24 16:13:06.290863+0800 ZeroTime[503:10402] [Purchases] - DEBUG: ℹ️ There's a request currently running and 0 requests left in the queue, queueing GET /subscribers/$RCAnonymousID0X0P+0cada631d501147efa13dd3dd44741b9c/offerings
2021-09-24 16:13:07.702613+0800 ZeroTime[503:10399] [Purchases] - DEBUG: ℹ️ API request completed with status: GET /v1/subscribers/$RCAnonymousID:cada631d501147efa13dd3dd44741b9c 304
2021-09-24 16:13:07.705077+0800 ZeroTime[503:10399] [Purchases] - DEBUG: ℹ️ Serial request done: GET /subscribers/$RCAnonymousID0X0P+0cada631d501147efa13dd3dd44741b9c, 1 requests left in the queue
2021-09-24 16:13:07.705201+0800 ZeroTime[503:10399] [Purchases] - DEBUG: ℹ️ Starting the next request in the queue, <RCHTTPRequest: httpMethod=GET
path=/subscribers/$RCAnonymousID0X0P+0cada631d501147efa13dd3dd44741b9c/offerings
requestBody=(null)
headers={
    Authorization = "Bearer vXpx...";
}
retried=0
>
2021-09-24 16:13:07.706122+0800 ZeroTime[503:10399] [Purchases] - DEBUG: ℹ️ There are no requests currently running, starting request GET /subscribers/$RCAnonymousID0X0P+0cada631d501147efa13dd3dd44741b9c/offerings
2021-09-24 16:13:07.706187+0800 ZeroTime[503:10399] [Purchases] - DEBUG: ℹ️ API request started: GET /v1/subscribers/$RCAnonymousID:cada631d501147efa13dd3dd44741b9c/offerings
2021-09-24 16:13:08.111173+0800 ZeroTime[503:10422] [Purchases] - DEBUG: ℹ️ API request completed with status: GET /v1/subscribers/$RCAnonymousID:cada631d501147efa13dd3dd44741b9c/offerings 304
2021-09-24 16:13:08.111475+0800 ZeroTime[503:10422] [Purchases] - DEBUG: ℹ️ Requesting products from the store with identifiers: {(
    "io.smudge.ZeroTime.SUB.Yearly",
    "io.smudge.ZeroTime.SUB.Monthly"
)}
2021-09-24 16:13:08.111900+0800 ZeroTime[503:10422] [Purchases] - DEBUG: ℹ️ Serial request done: GET /subscribers/$RCAnonymousID0X0P+0cada631d501147efa13dd3dd44741b9c/offerings, 0 requests left in the queue
2021-09-24 16:13:12.926935+0800 ZeroTime[503:10344] [Purchases] - DEBUG: ℹ️ No cached Offerings, fetching from network
2021-09-24 16:13:12.963155+0800 ZeroTime[503:10422] [Purchases] - DEBUG: ℹ️ There are no requests currently running, starting request GET /subscribers/$RCAnonymousID0X0P+0cada631d501147efa13dd3dd44741b9c/offerings
2021-09-24 16:13:12.963257+0800 ZeroTime[503:10422] [Purchases] - DEBUG: ℹ️ API request started: GET /v1/subscribers/$RCAnonymousID:cada631d501147efa13dd3dd44741b9c/offerings
2021-09-24 16:13:13.334771+0800 ZeroTime[503:10422] [Purchases] - DEBUG: ℹ️ API request completed with status: GET /v1/subscribers/$RCAnonymousID:cada631d501147efa13dd3dd44741b9c/offerings 304
2021-09-24 16:13:13.335316+0800 ZeroTime[503:10422] [Purchases] - DEBUG: ℹ️ Serial request done: GET /subscribers/$RCAnonymousID0X0P+0cada631d501147efa13dd3dd44741b9c/offerings, 0 requests left in the queue

 


28 replies

Userlevel 1
Badge +1

Thanks for reporting! While we look into this, have you given the RevenueCat version 4 beta a try (`4.0.0-beta.3`)? All of the code that you’re interacting with has changed in the beta. If you’re up for trying it, having data on whether this is still impacting you after switching to v4 would definitely help us narrow down any possible issues in the current release.

 

Userlevel 1
Badge +1

@taquitos do you have any further info in integration 4.0.0-beta.3 with Objective C?

I have been following this: https://github.com/RevenueCat/purchases-ios/blob/main/docs/V4_API_Updates.md

I’m getting a whole lot of Property '<property>' cannot be found in forward class object 'SKProduct'.

Badge

Was wondering for the last 6 hours what was going on but same issue here as well.. Hopefully there is a fix soon :sweat_smile:

[✓] Flutter (Channel stable, 2.5.1, on macOS 11.4 20F71 darwin-x64, locale en-GB)
[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
[✓] Xcode - develop for iOS and macOS
[✓] Chrome - develop for the web
[✓] Android Studio (version 4.2)
[✓] VS Code (version 1.60.1)
[✓] Connected device (2 available)
 

Pubspec: purchases_flutter: ^3.4.5

Phone: iPhoneX (iOS 15.0)

Userlevel 1
Badge +1

Re:  Property '<property>' cannot be found in forward class object 'SKProduct'.

We were just talking about this Friday, I think what is happening is that we used to expose StoreKit in our headers. So that meant you didn’t have to import them yourself. With Swift, there’s no nice way to do this, so you’ll have to @import StoreKit where you use any of our API that uses StoreKit objects 😬

 

We’re still working on this, one solution is that we might end up changing our API to wrap StoreKit objects so you don’t have to @import StoreKit

 

 

Userlevel 1
Badge +1

@taquitos exactly the same issue with 4.0.0-beta.3.

Fails on iOS 15, except for once after a reboot.

Works on iOS 14 consistently.

Userlevel 1
Badge +1

Erase All Content and Settings briefly resolved the issue, but soon returned to only working after reboot.

Userlevel 1
Badge +1

We’ve been trying to reproduce this, and I’ve been digging around seeing if other folks have the same issue. This is super weird, but I think it might be `StoreKit` side- as in, this appears to be an Apple problem 😿
 

 

@ryan’s response looks like it applies to your current situation, specifically 

The “Requesting products from the store with identifiers: … “ log message indicates that the product IDs were fetched successfully from RevenueCat and now a request is being made from the device to Apple to return the products with those IDs.

 

The fact that restarting the device or resetting it then allows it to work makes sense. IIRC StoreKit uses XPC to communicate with other device services to make the requests. If something happens between other services like something dies, or just spins, the XPC can timeout or just hang without any more information passed back about the situation. This is totally just speculation.

Since we can’t reproduce on our side, one thing you could try is to take those product ids that you have and manually request the products from Apple via StoreKit and see if the same thing happens. I’m still going through our code to double-check for potential issues.

Userlevel 1
Badge +1

Seems like it’s a weird issue related to:

  1. This sandbox account
  2. This device
  3. iOS 15

This seems to have resolved it currently:

  • Settings | App Store | Sandbox Account | Sign Out
  • Reboot
  • Run app and try to make/restore a purchase
  • Sign in with a different sandbox account

The original sandbox account works fine on iOS 14, and still causes an issue if I log back in with it.

Userlevel 1
Badge +1

This workaround is really helpful to document, thank you!

 

Also, @Andy found some places where completion blocks might not be called and he put a PR up: https://github.com/RevenueCat/purchases-ios/pull/879. I don’t think this helps your specific case (because iOS 14 works fine), but when it comes to different iOS versions I wouldn’t be entirely surprised if it did help somehow.

 

 

Userlevel 1
Badge +1

Further information after building a demo project for Apple Feedback: FB9650399

When running the project as the original account in Settings | App Store | Sandbox Account and using the RevenueCat SDK, the product identifiers will only be returned the first time, until the device is rebooted. Using native StoreKit, also fails to return product identifiers after the initial RevenueCat SDK failure.

Using native StoreKit with the original account, it will consistently return product identifiers until the RevenueCat SDK is used, and then it will fail for both RevenueCat SDK and native StoreKit until reboot.

When running the project as a different account in Settings | App Store | Sandbox Account, after a reboot, the account consistently returns product identifiers using either RevenueCat or native StoreKit.

It seems as though something like a process is crashing when using the RevenueCat SDK, only when using the original account, that is not restarted until the iOS device is restarted.

Userlevel 2
Badge +4

@smudge.io Did you end up creating a demo project that reproduces it? If so, would you mind sharing it with us? We’ve had a difficult time reproducing the issue, but we’d love to figure it out.

Also, we’ve released versions `3.12.6` (and made updates to our v4 beta in the `main` branch) that improve the SDK’s behavior for offerings in a couple of places. I don’t think they directly address the issue you were facing, but I’d still recommend updating.

Userlevel 1
Badge +1

@Andy sure, let me know how you would like me to share it, given that it contains sensitive information.

Userlevel 2
Badge +4

@smudge.io we created a support ticket for you, it includes a link to this post. You can use that to share it privately.

Thanks!! 🙌

As far as I understand it, Apple has changed something and the RevenueCat API needs to be updated as well. This is a stopper for being able to submit the app for review to Apple. When should we expect a fix in API and how will it be communicated?

Userlevel 2
Badge +4

@Sinecan Anhammer I replied on the other ticket, I hope that helps!

I’ve actually been having the same issue for a while now, I even raised an issue https://github.com/RevenueCat/purchases-ios/issues/851
But after I rebooted my device it started working again. But a couple weeks later it started hanging again. 
I noticed it was breaking the YouTube app if I tried to get products in my own app then tried launching YouTube it would hang and crash YouTube.

Userlevel 2
Badge +4

hey @Andrew Edwards ! Thanks for reporting!

Is this happening with a sandbox account? Have you made any purchases with a production account? I’m still trying to find a pattern in terms of which accounts trigger this, and it seems like many of the folks who ran into this had used a production account for a sandbox purchase.

Have you tried the steps I outlined in the other ticket?

 

hey @Andrew Edwards ! Thanks for reporting!

Is this happening with a sandbox account? Have you made any purchases with a production account? I’m still trying to find a pattern in terms of which accounts trigger this, and it seems like many of the folks who ran into this had used a production account for a sandbox purchase.

Have you tried the steps I outlined in the other ticket?

 

Yes it was a sandbox account. And it’s happened on all the iOS 15 betas I’ve been on when trying this. Even both the purchases-iOS SDK ObjC and the new swift one. 
 

Another note is I created the sandbox account during the summer so it wasn’t a carryover from iOS 14/AppStore connect. It was made during the new/summer/beta season. 
 

and yes, what just worked for me was signing out of the sandbox account in settings and trying the IAP again and this time it was able to fetch the products and allow me to sign in with the account and everything seems to work for now.

Userlevel 2
Badge +4

@Andrew Edwards 

Thanks for reporting back! So did you end up signing in with the same sandbox account when you signed in again? 

@Andy Yes I did. But it’s not working anymore lol. 
another thing to note is that it breaks all IAP for the entire device even production IAP for other apps. 
and another side effect is that all apps in the AppStore show as “Get” or “Buy” even for ones that I have already downloaded. Usually you’d see a cloud download button the App Store shows them as if you’ve NEVER downloaded them. I’m seeing it right now actually. Gonna do a reboot. And for extra context the sandbox account is currently signed out of right now. I signed out after I did the IAP last night after a couple hours I noticed other apps’ IAP not working or crashing their apps

Userlevel 2
Badge +4

another thing to note is that it breaks all IAP for the entire device even production IAP for other apps. 

 

Ouch, that’s gotta be super annoying. 

I don’t think there’s much we can do about the bug, though, since it’s very much on Apple’s side. Especially since this seems to be affecting other, production apps. 

My advice, though, is to never mix production accounts with sandbox, i.e.: never make a purchase in a sandbox environment using your regular iCloud account, and vice versa. This could lead to issues, and in the past it even broke accounts. 

For your case, I think you should try the following steps: 

  1. Creating another, new sandbox account in App Store Connect
  2. Logging out of sandbox and even production in app store. 
  3. Rebooting the device
  4. Logging into regular app store using your production account in Settings → Your account → Media & Purchases
  5. Logging into the new sandbox account in Settings → App Store → Sandbox Account

That should (hopefully) return things to normal. 

I’m currently working on an update that will time out the `SKProductsRequest` after a while, and cancel it. I’m not sure it’ll fix the problem, though, since it does depend on `SKProductsRequest` behaving correctly, which it doesn’t seem to. But it should at least provide some clarity and ensure the SDK doesn’t hang, even if StoreKit itself is hanging. 

 

 

@Andy makes sense! And I agree about mixing accounts. Just to be clear I always kept the sandbox account specific to the sandbox environment and never signed into my normal Media/purchases account in settings with the sandbox account. My main applied has been the only one signed into production and in app stores. 
 

it’s annoying creating a new sandbox account since it means a new AppleID and setup in AppStore connect 😞

 

but I’ll give it a shot. Thanks for the info!

Userlevel 2
Badge +4

@Andrew Edwards I feel ya. Working at RevenueCat, I’ve created more sandbox accounts than I’d like (over 70 as of writing), since I keep either messing them up or needing more for quick testing.

Since for testing I don’t really need apple’s emails, and email verification isn’t required, I just set up accounts under our domain name, but that don’t necessarily map to a real email account. Just mentioning in case it’s useful.

 

Userlevel 2
Badge +4

@smudge.io @Sinecan Anhammer @Andrew Edwards I’ve made a fix for purchases-ios. 

It’s available here, and you can get it by using `purchases-ios` branch:

  • `main` branch, for purchases-ios v4 (currently v4 is in beta)
  • `release/3.12.8` if you’re using the v3 version. 

Since we’ve had a tough time trying to reproduce this bug, if you still have access to one of the accounts that reproduces it, would you mind trying out the solution and letting us know if it solves it? It would be immensely helpful. And earn you some swag 😉

 

I made a summary of what we know about the issue here:

 

Userlevel 1
Badge +1

@Andy looks like it still occurs with release/3.12.8 and the existing failing account:


2021-10-20 13:43:54.096509+0800 SKProductsDemo[316:4690] [Purchases] - ERROR: 🍎‼️ SKProductsRequest took longer than 30 seconds, cancelling request and returning an empty set. This seems to be an App Store quirk. If this is happening to you consistently, you might want to try using a new Sandbox account. More information: https://rev.cat/skproductsrequest-hangs
2021-10-20 13:43:54.097286+0800 SKProductsDemo[316:4672] [Purchases] - ERROR: 🍎‼️ Error fetching offerings - Error Domain=RCPurchasesErrorDomain Code=23 "There's a problem with your configuration. None of the products registered in the RevenueCat dashboard could be fetched from App Store Connect (or the StoreKit Configuration file if one is being used). 
More information: https://rev.cat/why-are-offerings-empty" UserInfo={NSLocalizedDescription=There's a problem with your configuration. None of the products registered in the RevenueCat dashboard could be fetched from App Store Connect (or the StoreKit Configuration file if one is being used). 
More information: https://rev.cat/why-are-offerings-empty, readable_error_code=CONFIGURATION_ERROR}

Reply