Post

Replies

Boosts

Views

Activity

How are IAP receipts supposed to work when an iOS app runs on an Arm Mac?
Does anyone know how IAPs and receipt validation is supposed to work when an iOS app is run on a new Arm Mac? I have an iOS app which I'm pleased to discover runs well on my new Arm Mac mini. The app has non-consumable IAPs. At startup it parses the app receipt. A receipt is present, but my existing receipt validation code decides that it has the wrong hash. (This is with the app installed from the App Store, not a local build.) I'm aware that receipt validation is different for native Mac apps, including catalyst apps (e.g. getting a device GUID from the ethernet MAC addresses etc.) But what is supposed to happen in the case of a regular iOS app running on macOS? Is this documented anywhere? Has anyone got IAPs working, with local receipt validation?
15
0
4.2k
Mar ’22
Identifying "required reason" API call locations from app binary
Dear Experts, I've just received the exciting new email from App Store Connect telling me that I'm using a "required reason" API call and need to declare it in my privacy manifest. Of course this is easy to fix, I'll just add the code to my privacy manifest - but I thought I'd at least go through the motions of trying to work out what function I am calling and from where. First issue is that the email just tells me that the app "references one or more APIs that require reasons ... including NSPrivacyAcceeedAPICategoryFileTimestamp". Dear Apple, why on earth can't you actually tell me the specific function that I am calling? (FB13689896). So let's see if I can work out what has been detected. I look at the app binary: % objdump --syms App.app I think that is probably more or less what App Review must get from their scan, right? So I can see _stat in there but it doesn't know the corresponding source file. So I go to the build directory with the object files and extract symbols from them all individually, using objdump --syms. Provided that I've not enabled link-time optimisation that works and I can find ... zero calls to stat(). Which tells me that my C++ std::filesystem calls have not been detected! Interesting. So if you want to bypass this amazing new privacy technology, I guess that's the way to go. Anyway if there's a call to stat() in the binary but not in the object files, it must be coming from one of my .a files. That's a bit more difficult to track down as (1) my .a files are not in a convenient single directory, and (2) they may have calls to stat() in archive members that aren't needed and aren't included in this binary. So the question: is there some convenient way to take the binary and identify which object files or static library archive members resulted in which of its UND symbols?
12
2
4.1k
Apr ’24
"Required Reason" API - stat()
I've just been looking at this list of APIs for which we will be soon be required to declare a "required reason" in the app's privacy manifest: https://developer.apple.com/documentation/bundleresources/privacy_manifest_files/describing_use_of_required_reason_api One of the listed functions is stat(). The rationale seems to be that a malicious app can use stat to get the timestamps of files outside the app container, thereby "fingerprinting" the device. The allowed reasons that we can declare are : To get timestamps that are displayed to the user. To get timestamps of files that are within the app's container. To get timestamps of files that the user has granted access to. I am concerned that this does not include many of the legitimate non-timestamp uses of stat(). For example, it can be used simply to test if a file exists, or to test whether a path refers to a file or a directory, or to check if two paths refer to the same file (e.g. via different symlinks), or to get the size of a file. Some of these things can be achieved in other ways; for example, I can check if a file exists by trying to open() it and checking for an error, and I can get the file size by opening it and calling lseek(SEEK_END). Maybe I can check if two paths are equivalent by using readlink() to form canonical paths for both and comparing them. But I bet there are other things that can't be done. I could probably fix all of my code to not call stat() for non-timestamp reasons in a few hours. It would be more difficult to fix the various open-source libraries that I use. What do you think we should all be doing?: "File a bug" asking for an additional reason for using stat(), i.e. to get non-timestamp information about files in the app's container. Deliberately mis-read allowed reason C617.1, "to access the timestamps of files inside the app container", as " to access the timestamps and other metadata of files inside the app container", and declare that in the privacy manifest. Change code to not call stat(). Any other suggestions? P.S. I guess that libc++ std::filesystem calls stat(). What is the status of using that? The std::filesystem functions that access file timestamps are not listed on the page linked above. If I call std::exists() to check if a file exists, and assuming that is implemented using stat(), will that trigger the new filter?
11
1
3.7k
Dec ’23
DSA compliance web page has wrong address, and I can't change it.
I visit https://appstoreconnect.apple.com/apps A banner at the top of the screen tells me that I need to "provide and verify information regarding your account" for DSA compliance. I click on the "complete compliance requirements" link. The address shown for my business on this page is correct. I click on "Complete Compliance Requirements for (business)" near the top of this page. The address is also correct here. I click on "Complete Compliance Requirements" near the top of this page. This presents an "are you a trader?" popup; I select "This is a trader-provided account" and click Next. This shows a popup headed "Contact Information Verification". This page shows the wrong address. It shows an old personal address, pre-dating the establishment of my business. This popup tells me to contact Dun & Bradstreet to update my address. I click on the "Learn More" link. I follow the instructions to find my business on the D&B website. Of course Dun & Bradstreet already know the correct address for the business, so I am unable to change it. The result is that I am unable to complete DSA compliance. I think the root cause is that I had a personal developer account which Apple transferred to my business when I established it in 2018. Anyone else seeing problems like this? FB13687820
11
4
2.6k
Apr ’24
Thread QOS class
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?
8
0
5.5k
Jul ’23
AppAttest attestKey returns invalid key error
Dear Experts, I have App Attest deployed in an app that is currently in TestFlight. Its works OK most of the time. For one particular user, however, attestKey fails with DCErrorInvalidKey for a new key that it has just created. I have some insight into what the app is doing because I send diagnostics to the server. It seems that for this user, the sequence of events is: Initially the app has no key ID saved. The user initiates an action that requires App Attest-signed communication with my server. The app calls generateKey which seems to succeed. The app fetches a challenge from the server. The app calls attestKey. attestKey returns DCErrorInvalidKey. The app doesn't save the key ID persistently, so next time the same thing happens. attestKey really shouldn't fail with the invalid key error for a key that it has just created, should it? What could be going on here?
7
2
2.6k
Jun ’24
I can't use the word "*****", but adverts for prostitutes are OK?
Dear Apple, I know that content moderation is difficult, but surely you can do better than this. You seem to have a very crude profanity filter that ****s out words with perfectly normal dual uses, but you can't stop the constant stream of adverts for c all girls in D ubai. Come on, sort it out! (And amazingly, this message is rejected as "You have included content that is not permitted" when I wrote "c all girls in D ubai", until I added the spaces!) (The word in the title is a small metal item used to join pieces of wood together, which can also be used as a euphemism for something couples do.)
6
0
1.3k
Sep ’22
NSFileCoordinator/Presenter and background location apps
Dear Experts, It is necessary to remove NSFilePresenters when an app goes to the background and re-add them when it returns to the foreground - if you don't do so, the app will be terminated. But what about an app that has the location background mode enabled? Specifically, I have an app that records your location, in the foreground or background, and writes this data to a file. It does writes to the file inside a coordinated write block, and monitors for writes from other processes. This works fine in the foreground. I'd really like to also get notifications of concurrent changes to the file while the app is in the background, but this doesn't seem to be possible. (It's actually more likely that a file will be modified by another app while I'm in the background - consider switching to the Files app, and then back again.) Any suggestions?
6
0
1k
Oct ’22
Does SubscriptionStoreView .storeButton(for:.policies) work?
I've added .storeButton(.visible, for:.policies) to my SubscriptionStoreView, and the buttons do appear, but when I tap on them I get a sheet that just says "Terms of Service Unavailable / Somethng went wrong. Try Again.". (similar for Privacy Policy). Is this expected in development? Will these start working correctly in production? (and, more importantly, in App Review?) The docs say that these use the values (i.e. URLs) set in App Store Connect, but that I can override those. This is a new app. Is that wrong, do I need to set the URLs explicitly? Edited to add: the console reports: Failed to fetch terms of service and privacy policy: Error Domain=NSURLErrorDomain Code=-1011 "(null)"
6
1
948
Jul ’24
Watch-Phone communication when Phone app is in background
There doesn't seem to be a background mode that will allow an iPhone app to run in the background in order to communicate with its watch app, which is running in the foreground on the watch. Have I missed something? Related but not quite the same: say the iPhone app can run in the background to get location updates. But it only wants to do so when the watch app is running. Is there a way that the watch app can wake, or even start, the iPhone app, and for the iPhone app to then enable location updates? (I have previously implemented Bluetooth background modes - I think I could achieve both of the above if I had the watch and the iPhone communicate using my own BTLE protocol, rather than using Watch Connectivity. Is this true?)
6
0
880
Feb ’25
UIImage and CGImage have different aspect ratio for SFSymbols
Dear Experts, I create a UIImage for an SFSymbol using [UIImage systemImageNamed], get its CGImage, and look at the sizes of each: UIImageConfiguration* config = [UIImageSymbolConfiguration configurationWithPointSize: 64 weight: UIImageSymbolWeightLight scale: UIImageScaleMedium]; UIImage* img = [UIImage systemImageNamed: @"chevron.compact.down" withConfiguration: config]; CGImageRef c = [img CGImage]; printf("UIImage size %f x %f, CGImage size %f x %f\n", img.size.width, img.size.height, CGImageGetWidth(c), CGImageGetHeight(c)); (Consider that pseudo-code, it's not an exact copy-paste.) Results: UIImage is 70.3333 x 25.6667 and CGImage is 163 x 43. So the aspect ratios (W/H) are 2.74 and 3.79 respectively. That can't be right! I don't expect the UIImage and the CGImage dimensions to be the same, because of the UIImage's scale (which is 3 in this case). But that should be the same for both dimensions. The effect is most pronounced with symbols that have an aspect ratio far from 1, e.g. recordingtape, ellipsis, and this chevron.compact.down. I believe that the CGImage aspect ratios are the correct ones. What is going on here?
5
0
1.8k
Oct ’22
Address Sanitizer reports error whenever a C++ exception is caught
Dear Experts, When I try to use Address Sanitizer on my iOS app, it reports "attempting free on address which was not malloc()-ed" whenever a C++ exception is caught. If first saw it inside Apple's libFontParser and filed FB13271831, but I now see it in my own code. The Address Sanitizer stack trace always starts like this: #1 0x215766ae8 in __cxa_decrement_exception_refcount+0x40 (/usr/lib/libc++abi.dylib:arm64e+0x13ae8) Having looked up __cxa_decrement_exception_refcount in the C++ ABI docs, my guess is that the C++ runtime is creating and destroying the exception objects in some way that Address Sanitizer doesn't properly understand, causing it to think that they are being freed without having been allocated by malloc. This is only really a problem because it does not seem possible to continue after ASan has reported this error; the app is terminated. Question: is there a way to tell Address Sanitiser to ignore errors in this function? And/or, is there a way to continue after the error? Thanks.
5
0
2.1k
Nov ’23
When is NSMotionUsageDescription shown?
I'm using CMMotionManager startDeviceMotionUpdatesUsingReferenceFrame: CMAttitudeReferenceFrameXTrueNorthZVertical and have set the NSMotionUsageDescription ("Privacy - Motion Usage Description") property in the info.plist. But I don't see a permissions popup. I also don't see any mention of this in the app's section of the Settings app. When is this usage description string used? I wonder if there is some connection between the motion permission and the location permission, which I also use?
5
0
1.3k
Sep ’24