Posts

Post not yet marked as solved
1 Replies
76 Views
If I use UIEditMenuInteraction to present an edit menu, it has a dismissMenu method that I can call to remove the menu when necessary. When I use UITextInteraction, I get an edit menu automatically that is normally presented and dismissed at appropriate times. But sometimes I want to dismiss the menu myself, and I can't find a way to do that. Am I missing something? I was hoping to find that UITextInteraction inherited from UIEditMenuInteraction, or had some other way to access the underlying menu in order to dismiss it. But it seems that the menu must be a private part of the UITextInteraction implementation. The particular case that I need to deal with is when I call resignFirstResponder. This seems to cause the keyboard to close and the insertion point and any selection to be hidden, but if an edit menu was shown then it remains visible (a ghost!). If anyone knows of an alternative to resignFirstResponder that will make UITextInteraction tidy up properly, that would also be useful to know. Thanks for any suggestions!
Posted
by endecotp.
Last updated
.
Post not yet marked as solved
11 Replies
2.3k Views
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?
Posted
by endecotp.
Last updated
.
Post not yet marked as solved
0 Replies
245 Views
Has anyone successfully completed DSA compliance phone number verification using the "receive a phone call" option? It seems that Apple first tries to send an SMS. You then have the option to resend another SMS, to receive a phone call, or to upload documents. When I choose to receive a phone call, it seems that the Apple system calls me but it hangs up without reading out a code. Has anyone got this to work?
Posted
by endecotp.
Last updated
.
Post not yet marked as solved
8 Replies
796 Views
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
Posted
by endecotp.
Last updated
.
Post not yet marked as solved
2 Replies
443 Views
I'm referring to the use of a "settings bundle" plist to cause the main Settings app to display your app's preferences which the app can then read via NSUserDefaults, as described here: https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/UserDefaults/Preferences/Preferences.html#//apple_ref/doc/uid/10000059i-CH6 I am wondering if this is actually deprecated, or something. I ask because, (1), it still has the high-quality old-style documentation, and (2) there doesn't seem to be a "required reason API" code for using it. Specifically, the NSUserDefaults required reason API codes are CA92.1 : "This reason does not permit reading information that was written by other apps or the system" 1C8F.1 : "This reason does not permit reading information that was written by apps, app extensions, or App Clips outside the same App Group or by the system." C56D.1: "...third-party SDK..." - nope. AC6B.1: "... com.apple.configuration.managed ..." - nope. None of the codes permit reading preferences that have been set by the Settings app using this method.
Posted
by endecotp.
Last updated
.
Post not yet marked as solved
3 Replies
531 Views
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?
Posted
by endecotp.
Last updated
.
Post not yet marked as solved
0 Replies
295 Views
The docs for Transaction.updates say: Use updates to receive new transactions while the app is running. This sequence receives transactions that occur outside of the app, such as Ask to Buy transactions, subscription offer code redemptions, and purchases that customers make in the App Store. It also emits transactions that customers complete in your app on another device. Note that after a successful in-app purchase on the same device, StoreKit returns the transaction through Product.PurchaseResult.success(_:). So Transaction.updates isn't supposed to include transactions for purchases that are made in this instance of the app, right? I have this code to get those transactions: SubscriptionStoreView(groupID: group_id) { } .onInAppPurchaseCompletion() { product, result in ..... } But when I make a purchase using this SubscriptionStoreView, I see that both this .onInAppPurchaseCompletion code and my code observing Transaction.updates is called. Is this expected? Will it work reliably without the .onInAppPurchaseCompletion ? Thanks.
Posted
by endecotp.
Last updated
.
Post not yet marked as solved
1 Replies
291 Views
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?
Posted
by endecotp.
Last updated
.
Post not yet marked as solved
0 Replies
259 Views
If I use SubscriptionStoreView.init(groupID), it seems to be able to look up all the Products that have that subscription group ID. But I don't see any public method for doing that myself. Am I missing something, or is SubscriptionStoreView using a private method to do this lookup? I know that historically it has always been necessary to know the product IDs of all the products you want to sell; you have never been able to ask Store Kit to give you a list. SubscriptionStoreView doesn't seem to have this limitation, which is a bit surprising.
Posted
by endecotp.
Last updated
.
Post not yet marked as solved
3 Replies
402 Views
I am looking at StoreKit Views, new in iOS 17. In a SubscriptionStoreView, is it possible to show the user their current subscription's renewal/expiry date, or to present a cancel button? According to https://developer.apple.com/documentation/storekit/storebuttonkind/4203108-cancellation , storeButton for: .cancellation is "A type of button for canceling a subscription.", but actually it just shows a (X) button at the top right to dismiss the view - and this is what the WWDC video presenter (2023 session 10013) seems to believe it should do (around 28:30, "The cancellation button shows a platform-appropriate button to dismiss the view"). Is that a documentation bug? It seems that I can show renewal/expiry dates and a cancellation button if I use AppStore.showManageSubscriptions(...). But this is rather disjointed. Shouldn't I be able to show all of this in one place? Does my UI need two separate buttons for these overlapping features? Or am I missing something?
Posted
by endecotp.
Last updated
.
Post not yet marked as solved
0 Replies
434 Views
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?
Posted
by endecotp.
Last updated
.
Post not yet marked as solved
2 Replies
682 Views
Dear All, I have a paid app which has in-app purchases to unlock additional content. In my App Store screenshots and preview videos, I used to indicate which content was paid and which was free with labels superimposed over the screen captures. App store review guideline 2.3.2 supports doing this - in fact, it seems to require it: 2.3.2 If your app includes in-app purchases, make sure your app description, screenshots, and previews clearly indicate whether any featured items, levels, subscriptions, etc. require additional purchases. But App Review don't like it. Some years ago they complained about the labels on the screenshots, which I removed. Now they are complaining about the preview videos. They cite guideline 2.3.7, which says (in part, my emphasis): 2.3.7 ... Metadata such as app names, subtitles, screenshots, and previews should not include prices, terms, or descriptions that are not specific to the metadata type. ... So these guidelines seem to be contradictory. If I label a screenshot as "free" or "paid", they consider that to violate 2.3.7. (I'm not showing an actual "$1.23" price, just "free" or "paid".) But I need to indicate whether the content shown is "free" or "paid" in order to comply with 2.3.2. (And I want to label it as such, because I don't want users to misunderstand what is included with their initial purchase.) Has anyone else had this problem? I wonder if there is some particular wording that they require, e.g. "Requires in-app purchase" rather than "Paid". Or something rather than "free". There is a limit to how much text I can legibly add without obscuring the actual content, so I have tried to keep it brief. I did refer to 2.3.2 in my reply to App Review, but they haven't addressed that; they've accepted the update as a bug fix. Ultimately I'll just do what they want - it always seems easiest - but I do have real concern that my customers are worse off without these annotations.
Posted
by endecotp.
Last updated
.
Post not yet marked as solved
4 Replies
990 Views
I have been trying to tidy up my Mac's storage which is getting full. (See also my other question about "bridgeOS".) In Settings -> General -> Storage -> Developer there were numerous multi-gigabyte items for different versions of iOS. Most of them were for point releases that I no longer have on my devices, which auto-update. For example I think I had 17.0, 17.1.1 and 17.1.2; my dev iPad and iPhone are both now running 17.1.2, so I deleted the others. But now when I try to run, XCode complains that "iOS 17.0 is not installed". Does this mean that iOS 17.0 device support is required in addition to iOS 17.1.2, in order to run on a 17.1.2 device? This would make sense if it just said "iOS 17", rather than "iOS 17.0".
Posted
by endecotp.
Last updated
.
Post not yet marked as solved
11 Replies
2.6k Views
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?
Posted
by endecotp.
Last updated
.
Post not yet marked as solved
1 Replies
1.1k Views
In my Mac's Settings -> General -> Storage -> Developer -> (i) I have a series of entries for "bridgeOS", all 2.49 GB except one that is "zero". Do I need these? Can I remove them? I am only doing "normal" iPhone / iPad development. (There was some previous mention of this here: https://developer.apple.com/forums/thread/711279 with no feedback.)
Posted
by endecotp.
Last updated
.