Dear All,
My iOS app used to work OK on macOS, but since a macOS update in-app purchases have stopped working. It seems that the storekitagent process is no longer able to save the receipt to the filesystem. Here is what I see in the system log after I do a "refresh receipt":
default 22:03:47.822657+0100 storekitagent [58C16E76_SK1] Writing receipt (83905 bytes) to file:///Users/phil/Library/Containers/0407ACA7-9EE2-4E32-AA3E-101A1B38EE70/Data/StoreKit/sandboxReceipt
error 22:03:47.823539+0100 kernel Sandbox: storekitagent(1382) deny(1) file-write-unlink /Users/phil/Library/Containers/0407ACA7-9EE2-4E32-AA3E-101A1B38EE70/Data/StoreKit/sandboxReceipt
error 22:03:47.824306+0100 storekitagent [58C16E76_SK1] Error writing receipt (83905 bytes) to file:///Users/phil/Library/Containers/0407ACA7-9EE2-4E32-AA3E-101A1B38EE70/Data/StoreKit/sandboxReceipt: Error Domain=NSCocoaErrorDomain Code=513 "You don’t have permission to save the file “sandboxReceipt” in the folder “StoreKit”." UserInfo={NSFilePath=/Users/phil/Library/Containers/0407ACA7-9EE2-4E32-AA3E-101A1B38EE70/Data/StoreKit/sandboxReceipt, NSUnderlyingError=0x145c19f80 {Error Domain=NSPOSIXErrorDomain Code=1 "Operation not permitted"}}
Note that is a sandboxReceipt on my development system, but I have a report from a user who seems to be suffering the same problem with the app store version of the app.
Is anyone else seeing this?
Is there a "quick hack" I can do to grant the storekitagent process permission to write to that folder?
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
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
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?
Documentation for the App Store Connect API is poor, especially in comparison to the good documentation for the now-defunct XML-based "transporter" API. In the hope that it will be useful to others trying to do this in the future, here is how I was able to do a bulk update of my in-app purchases' prices using the API.
Step 1: get the IDs for the IAPs, if you don't already know them:
GET v1/apps/$app/inAppPurchasesV2
If you have a lot of IAPs, follow any links/next URL to get subsequent pages.
The ids are in data/id .
Step 2: get the current prices, if you don't already know them.
I believe you need to do a separate request for each IAP (right?).
GET v1/inAppPurchasePriceSchedules/$iap/manualPrices?include=inAppPurchasePricePoint,territory
The price and currency are in included/attributes/customerPrice and included/attributes/currency (I generally only have one "manual" price).
Step 3: look up the available price points:
GET v2/inAppPurchases/$iap/pricePoints?filter[territory]=$territory
The prices and IDs are in data/attributes/customerPrice and data/id.
Note this query takes the specific IAP ID. I don't know why. Are the price points specific to the IAPs? Can I reuse a price point ID that I've looked up for one IAP with another IAP for the same app?
Step 4: choose your new prices.
Step 5: Submit the new prices:
POST v1/inAppPurchasePriceSchedules
{
"data" : {
"relationships" : {
"baseTerritory" : {
"data" : {
"id" : "$territory",
"type" : "territories"
}
},
"inAppPurchase" : {
"data" : {
"id" : "$iap",
"type" : "inAppPurchases"
}
},
"manualPrices" : {
"data" : [
{
"id" : "$random_id",
"type" : "inAppPurchasePrices"
}
]
}
},
"type" : "inAppPurchasePriceSchedules"
},
"included" : [
{
"attributes" : {
"startDate" : null,
"endDate" : null
},
"id" : "$random_id",
"relationships" : {
"inAppPurchasePricePoint" : {
"data" : {
"id" : "$price_point_id",
"type" : "inAppPurchasePricePoints"
}
},
"inAppPurchaseV2" : {
"data" : {
"id" : "$iap",
"type" : "inAppPurchases"
}
}
},
"type" : "inAppPurchasePrices"
}
]
}
In that, $iap is the IAP ID from step 1, $territory is probably a three-letter string like GBR, $random_id is a random identifier that you generate (using the same value in the two places) (I'm not sure what the scope of this is; do I have to check that I don't accidentally send the same value in the future, or does it only exist while this submission is processed?), and $price_point_id is the ID for the price point from step 3.
I believe it is necessary to send a separate submission for each IAP (right?)
That example makes the change immediately (start and end dates are both null). Note that if you want to schedule a future change, you need to include both the current period and price and the future period and price in the submission.
I would like to thank @Efun whose posts in this thread: https://developer.apple.com/forums/thread/727159 helped a lot with understanding this.
Topic:
App Store Distribution & Marketing
SubTopic:
App Store Connect API
Tags:
App Store Connect API
I've been getting 500 error responses from the https://data.appattest.apple.com/v1/attestationData server for the last few hours. About half of requests complete OK and half fail.
Anyone else seeing this?
Dear Experts,
Is there a way to create a new target in Xcode that is a copy of an existing target?
Specifically, I have a standard iOS app target in the project. I'd like to build a second iOS app by adding a second target to the same project. I'd like it to start as a copy of the first target, and then I'll add and remove source files and frameworks, change assets and settings etc.
It seems to me that I have to create a new target and then add all the source files etc to it, and then replicate all the settings. I've tried to do this, but it isn't working - bizarrely I just see a black screen, though log messages suggest that the app is running. I am unsure about whether the two targets are sharing e.g. the Info.plist file, etc.
Any advice? Thanks.
Is it possible to change the date formats used in the App Store Connect web interface?
It seems to me that things like the date range selection widget on the Sales & Trends page use only the US-style MM/DD/YYYY format. Is there some way to change this to YYYY-MM-DD or DD/MM/YYYY that I have missed?
Topic:
App Store Distribution & Marketing
SubTopic:
App Store Connect
Tags:
App Store Connect
Internationalization
I see this warning when my app runs:
Thread running at QOS_CLASS_USER_INTERACTIVE waiting on a lower QoS thread running at QOS_CLASS_DEFAULT. Investigate ways to avoid priority inversions
This is true; I know what is going on. I'd like this other thread to have a higher priority. But how do I set the "QOS class" for a thread?
Searching developer.apple.com for QOS_CLASS_USER_INTERACTIVE doesn't find much. It seems that dispatch queues have priorities, but in this case I have a thread, not a dispatch queue.
Any ideas?
Dear Experts,
NSLocale has a notification NSCurrentLocaleDidChangeNotification and a property autoupdatingCurrentLocale ("A locale which tracks the user’s current preferences"). These suggest that an app should be able to detect when the user changes their language preference while running, or when it is resumed from the background.
In practice, when I change language in the Settings app (either globally or just for my app), the app is terminated by iOS and restarts with new locale.
Is this the expected behaviour? I am wondering if there is something I need to do to advertise that the app can adopt language changes without restarting, or something.
Maybe only date-time formats, etc., trigger the notification but language changes don't?
Dear All,
I've just received an email from a user of my paid app who says he is no longer able to use it on his work phone. He works for a US government agency which I'll abbreviate to GOV below. Apparently they have started using Microsoft Intune for device management and as a result they need the following work-around:
This app is not free to download, so it cannot be added to Intune app catalog through this tool. Reach out to the app developer and explain that GOV uses Apple Business Manager (ABM) and MDM for delivering managed apps to devices. Payment through ABM is not supported by GOV, so the app developer will need to provide a version of the app that's free to download but take payment outside of the Apple ID payment process. GOV's Custom App Store can be access by developers by advertising their app to Organization ID 12345678.
I don't know much about MDM, ABM and Intune, and I would more or less consider this a scam except that I am confident that the person who has sent it really does work for this government agency and does use my app on his personal device.
Is there any possibility that what they are asking for is legitimate?
I suspect that the crucial part is: "Payment through ABM is not supported by GOV", i.e. fundamentally ABM/MDM/Intune can support paid apps, but the financial people at GOV AGENCY have chosen not to support that.
Has anyone else experienced anything like this?
Topic:
App Store Distribution & Marketing
SubTopic:
General
Tags:
App Store
Apple Business Manager
Device Management
Dear Experts,
I'm attempting to make a custom icon appear in the iOS Files app, etc., for my file type. I've found a couple of bits of documentation for Info.plist keys:
https://developer.apple.com/documentation/bundleresources/information_property_list/utexportedtypedeclarations/uttypeiconfiles describes UTTypeIconFiles, to be included in UTImportedTypeDeclarations. This documentation is very sparse!
Older document https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/TP40009249-SW9 describes CFBundleTypeIconFiles, to be included in CFBundleDocumentTypes.
Which of these should I be using? (Both? Neither?)
Nothing I've tried so far has worked. I wonder if I need to, for example, power-cycle to make the Files app pick up the new icons.
Also, in Xcode, I've found the Imported Type Identifiers section of the Info settings which has a box labelled "Add imported type identifiers here" - but clicking + and choosing a file does nothing; the box remains empty. Anyone else have that problem?
What size should the icons be? The older document suggests some rather small sizes, e.g. 22x29; the newer doc says nothing.
Suggestions anyone?
Topic:
Developer Tools & Services
SubTopic:
Xcode
Tags:
iOS
Xcode
Uniform Type Identifiers
Core Services
Has anyone paid a graphics designer to produce custom SF Symbols for them? Would you care to share your experiences?
I paid for some custom graphics a decade ago; the results were OK but not amazing. I forget how I found that guy. No doubt everything has changed since then.
Dear experts,
I get glyphs from the system font using CTFontGetGlyphsForCharacters, something like this:
UIFont* uifont = [UIFont monospacedDigitSystemFontOfSize: s weight: w];
CTFontRef font = (__bridge CTFontRef)uifont;
CTFontGetGlyphsForCharacters(font, ....);
The characters that I ask for are basically latin-1 plus a few others.
The app is not localised for Chinese. When I change the phone's default language to Chinese, this code gets glyphs for most characters OK but it fails for a few punctuation symbols:
91 = [
93 = ]
183 = middle dot
8220 = left double curly quote
8221 = right double curly quote
Can anyone guess what's going on here? What's special about those characters?
Thanks, Phil.
I've just downloaded Xcode 15 (3.18 GB), and when I start it it downloads "additional components". It's currently downloading "iOS 17.0 Simulator" (7.56 GB).
I don't need the simulator, but I do need to compile for iOS and run on devices. Do I need this "simulator" download?
I note that while the small download progress window says "iOS 17.0 Simulator (21A328)", the main Xcode window won't let me compile/run the project because it is "Downloading iOS 17.0..." - though I'm not sure if the "..." at the end of that is a truncation eliding the word "Simulator".
In TestFlight crash reports, all I see is the stack trace.
Is there any other information hidden in there, such as the specific signal (etc) that caused the app to terminate?
Thanks.