Is there a recommended way to determine whether to use the development or the production server API endpoint for DeviceCheck?
For App Attest, the authenticator data includes either "appattest" or "appattestdevelop" in a field of the cbor data. For IAPs, we're supposed to try the production endpoint and then retry with the development endpoint if we get a particular HTTP status code. But the docs for DeviceCheck say only to use the development endpoint in development and the production endpoint in production.
What are others doing? Is there any clue in the docs that I have missed?
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
Dear Experts,
Where is the best place to persist an App Attest key id?
The docs ( https://developer.apple.com/documentation/devicecheck/establishing_your_app_s_integrity ) say “Record the identifier in persistent storage — for example, by writing it to a file”. That is what I have done, but I have encountered a problem. If a user gets a new device and restores a backup of an old device onto it, the new device will try to use the key id from the old device - which is of course wrong.
One solution is to detect the error when the invalid key is used and to generate a new one. Is that the best approach? I am wondering if there is some part of the filesystem that does not survive the backup/restore process, but is otherwise persistent? It should be more persistent than a cache file.
(Also looking at the docs again I now see that I am supposed to store distinct keys for each “user”. What is meant by “user” in this case?)
Thanks.
Does anyone know the relationship, if any, between Xcode's static analyzer and clang-tidy?
I.e. is Xcode's Analyze feature actually invoking a built-in clang-tidy?
If not, does anyone have any experience using upstream clang-tidy (homebrew?) with a mostly-Xcode development flow?
Dear Experts,
What is the current best practice for build numbering?
I ask because I am aware that when exporting an archived app for upload I am now asked if I want Xcode to manage the build number for me. In the past I have set a build number in the Info.plist, often based on the date, e.g. 2.4.20230218. Now, I am asked if I want that to be replaced by something like 2.4.7 (if I recall correctly). So far I've answered No.
Previously I have searched for automatic build numbering and I've found web pages that suggest adding a script to the build process that automatically increments the build number in the info.plist, or similar. I've not tried to implement that myself.
In some of my apps, I have code that needs to know the full version at compile time (e.g. app receipt validation). How would that interact with the new feature?
Thanks, Phil.
Topic:
App Store Distribution & Marketing
SubTopic:
App Store Connect
Tags:
App Store Connect
Xcode
Organizer Window
TestFlight
Dear Experts,
I am confused by what seems to be a difference in behaviour of the Files app on an iPhone compared to an iPad.
On the iPad, I seem to be able to view my app's Documents/ folder; on the iPhone, I can't. On the other hand I can access the app's iCloud documents on both devices.
Is this the expected behaviour? If so, what is the rationale?
Thanks, Phil.
Does anyone know if it’s possible for a WKWebView showing a web page in the app bundle - a help screen in my case - to show SF Symbols, by name? I’d like the help page to include some of the symbols that I use for buttons elsewhere in the app. Can I do this without having to make PNGs of the symbols?
Thanks.
Dear Experts,
Where do memory-mapped files appear in the Allocations instrument, if at all?
In the screenshot below, the green "all anonymous VM" graph is almost completely explained by the purple "IO Accelerator" graph (GPU buffers, textures etc) - but there are periods at the start of each cycle (such as at the cursor position) where there is some other contribution. I have not been able to find this in the other more-specific graphs.
Any ideas anyone? I have been trying to make this app better behaved memory-wise and have made a lot of progress, in particular by removing periods when two large memory allocations co-exist, and by breaking work up into chunks. It now bothers me that there is 150 MB of "anonymous VM" that I cannot explain!
Dear All,
I have working code that talks to the App Attest receipt refresh API using JWT authorization. I'm now trying to talk to the App Store Connect API, and I'm trying to use essentially the same code for the JWT generation - but it doesn't work.
It's frustrating that the API just returns a non-specific 401 "Not Authorized" response, without giving any further clue about what's wrong.
I am creating a JWT as follows for App Store Connect; yes I'm aware that the required fields are slightly different for the two APIs:
header = {"alg":"ES256","kid":"12345YZSX8","typ":"JWT"}
payload = {"iss":"1234567-1234-1234-1234-123456789012","iat":1687379230,"exp":1687379530,"aud":"appstoreconnect-v1"}
Using the resulting encoded token, with my own code or with curl, fails with a 401 error:
Status: 401
{
"errors": [{
"status": "401",
"code": "NOT_AUTHORIZED",
"title": "Authentication credentials are missing or invalid.",
"detail": "Provide a properly configured and signed bearer token, and make sure that it has not expired. Learn more about Generating Tokens for API Requests https://developer.apple.com/go/?id=api-generating-tokens"
}]
}
Doing essentially the same thing, with the slightly different JSON fields and a different .p8 key file, does work with the App Attest API - so I'm probably not creating complete garbage.
I've wasted hours on this now. Does anyone have any debugging hints?
Topic:
App Store Distribution & Marketing
SubTopic:
App Store Connect API
Tags:
App Store Connect API
App Attest
I'm confused by the stats on the TestFlight "builds" screen. See below.
There are more crashes than sessions. So the definition of "session" can't quite be what I thought. Does a session have to last more than a certain amount of time to be included? Do sessions that end in a crash not count as sessions? Do multiple invocations within a short period of time count as a single session?
The number of sessions falls over time. I.e. once I have released a new version, the reported "Sessions" numbers for older versions slowly fall. Maybe as soon as a user has used version N+1, all their sessions for version N are removed from the stats?
The "invites" column is clearly the same for every version, while it should have been slowly increasing.
Is there any value in these numbers?
I am seeing DCErrorInvalidInput returned from DCAppAttestService generateAssertion: in production.
Can anyone suggest what might cause this, and what I should do in response? The documentation says of this error code: "An error code that indicates when your app provides data that isn’t formatted correctly.:
The only input to the method is the key ID and the data hash. I generate the hash with CC_SHA256() and then put the bytes in an NSData. I don't think much can go wrong with that, though I can't see exactly what is being passed in my diagnostics.
There is another error response, DCErrorInvalidKey which I handle separately. I am wondering if problems with the key ID are being reported as "invalid input" rather than "invalid key". I can see the key ID in my diagnostics and it looks legitimate, i.e. it's 32 random-looking bytes, base64-encoded.
Suggestions anyone?
StoreKit.Transaction has an expirationDate property, but not a gracePeriodExpirationDate property. Product.SubscriptionInfo.RenewallInfo has a gracePeriodExpirationDate but no expirationDate.
If I have enabled a grace period I think I need to check both. That seems more complicated than it should be. Am I missing something?
The WWDC video "What’s new in App Store Connect" describes a new feature to nominate your apps for app store features.
Does anyone know when this is expected to be available to use? I don't see it immediately, and I don't think the video mentioned a timeline for its general availability.
Topic:
App Store Distribution & Marketing
SubTopic:
App Store Connect
Tags:
App Store
App Store Connect
I have a rather simple StoreKitSubscriptionView for my app's single subscription.
Question: Am I expected to write code to handle lack of network connectivity?
When I run the app on development device, not using the local StoreKit configuration but rather the real app store, if the network is not available I get a not-user-friendly error message instead of the normal SubscriptionStoreView content.
I'm uncertain if end-users actually see this. Maybe they see a more appropriate "Cannot connect to App Store, try later" message?
Maybe I am supposed to check for network and not present the view if it is not available. I don't recall any mention of this in the WWDC video but I guess I should check again.
Ideas anyone?
Consider this Swift struct:
public struct Example
{
public func foo(callback: ()->Void)
{
....
}
public func blah(i: Int)
{
....
}
....
}
Using Swift/C++ interop, I can create Example objects and call methods like blah. But I can't call foo because Swift/C++ interop doesn't currently support passing closures (right?).
On the other hand, Swift/objC does support passing objC blocks to Swift functions. But I can't use that here because Example is a Swift struct, not a class. So I could change it to a class, and update everything to work with reference rather than value semantics; but then I also have to change the objC++ code to create the object and call its methods using objC syntax. I'd like to avoid that.
Is there some hack that I can use to make this possible? I'm hoping that I can wrap a C++ std::function in some sort of opaque wrapper and pass that to swift, or something.
Thanks for any suggestions!
I have a grid-like container with subviews.
I recently changed some internal details of the subviews, so that changes to the values they display animate.
Now, the behaviour of the grid container has changed: the animation duration used for the internal changes is now also used when the grid is re-ordered or subviews are added or removed.
I can see why this happens: the grid repositions the subviews, and the subview has declared an animation that applies to all of its properties however they are modified.
This doesn't seem like a good idea to me. The principle of encapsulation suggests that I should be able to make internal changes to a component without suffering "spooky action at a distance", i.e. other components unexpectedly changing their behaviour.
Is this an inherent issue with SwiftUI animations, or does it suggest that I am doing something wrong?