Posts under App & System Services topic

Post

Replies

Boosts

Views

Activity

How to handle subscription notifications with future purchase date
Our app server has subscription feature and processes purchase life cycles based on App Store Server Notification v1. Last year, when users purchased subscriptions during the following timeframe, we received "INITIAL_BUY" notifications with "unified_receipt.Latest_receipt_info.purchase_date" set to future date(approx. 1 hour after the actual purchase). 2024-11-03 08:00:00 - 2024-11-03 09:00:00 Etc/GMT (UTC) For example, we received the following v1 notification at 2024-11-03 08:36:33 Etc/GMT. "notification_type": "INITIAL_BUY" "unified_receipt.latest_receipt_info[].purchase_date": "2024-11-03 09:36:02 Etc/GMT" Our server grants subscription entitlement based on "purchase_date" so the users had to wait 1 hour before the subscription features became available. The timeframe coincided with the end of daylight saving time in the U.S., so we assume that it affected the behavior, but our country doesn't adopt daylight saving time. We have some questions regarding this behavior. In countries without daylight saving time, how should we handle such notifications with future purchase date in order to properly grant subscription entitlement? In App Store Server Notification v2, could purchase date be set to future date at the end of daylight saving time in the U.S., just as in v1 notifications? JWSTransactionDecodedPayload.purchaseDate
0
0
100
May ’25
SwiftData shared across apps?
The stuff I've found by searching has confused me, so hopefully someone can help simplify it for me? I have an app (I use it for logging which books I've given away), and I could either add a bunch of things to the app, or I could have another app (possibly a CLI tool) to generate some reports I'd like.
0
0
83
May ’25
Is there a way to dynamically configure Actionable Notifications?
Hello, We are trying to implement Actionable Notifications on iOS via Remote Notifications. According to Apple’s official documentation (Declaring Your Actionable Notification Types), it is recommended to register notification categories at launch time. However, in our use case, the number of buttons and their actions in the Actionable Notification are determined at the time of the Remote Notification request. This means that we cannot predefine the categories at app launch but need to dynamically configure them based on the payload of the Remote Notification. Our Approach We are considering setting aps.mutable-content = 1 and using Notification Service Extension to modify the categoryIdentifier dynamically. Below is the JSON payload we plan to use for Remote Notifications: { "aps": { "alert": { "title": "New Message Received!", "body": "Check out the details." }, "category": "DYNAMIC_CATEGORY", "mutable-content": 1 }, "categoryData": { "id": "DYNAMIC_CATEGORY", "actions": [ { "id": "REPLY_ACTION", "title": "Reply", "options": ["foreground"] }, { "id": "DELETE_ACTION", "title": "Delete", "options": ["destructive"] } ] } } Questions: Can we dynamically configure Actionable Notifications based on the Remote Notification payload? If we set categoryIdentifier in Notification Service Extension’s didReceive(_:withContentHandler:), will users still see the correct action buttons even if the app is terminated? What is the recommended approach to dynamically configure Actionable Notifications at the time of receiving the Remote Notification, rather than at app launch?
0
0
102
Mar ’25
sandbox account isn't logging in on purchase window
I don't know if I am posting this in the right place. I am using xcode's phone simulator and I have setup my sandbox account on appstoreconnect under users and access/sandbox/test accounts then in my app on the simulator when I tap the subscribe button to purchase my product the a window pops up for in app purchases and I get a login prompt for my sandbox credentials, but no matter how many times I enter them after tapping ok all I get is a blank login prompt. also not this a brand new sandbox account and I've only changed the password 3 times, that seems to be important because its inconsistent with some of the errors I am getting on the error log here is error log. Purchase did not return a transaction: Error Domain=ASDErrorDomain Code=530 "(null)" UserInfo={NSUnderlyingError=0x600000d09080 {Error Domain=AMSErrorDomain Code=100 "Authentication Failed The authentication failed." UserInfo={NSMultipleUnderlyingErrorsKey=( "Error Domain=AMSErrorDomain Code=2 "Password reuse not available for account The account state does not support password reuse." UserInfo={NSDebugDescription=Password reuse not available for account The account state does not support password reuse., AMSDescription=Password reuse not available for account, AMSFailureReason=The account state does not support password reuse.}", "Error Domain=AMSErrorDomain Code=0 "Authentication Failed Encountered an unrecognized authentication failure." UserInfo={NSDebugDescription=Authentication Failed Encountered an unrecognized authentication failure., AMSDescription=Authentication Failed, AMSFailureReason=Encountered an unrecognized authentication failure.}" ), AMSDescription=Authentication Failed, NSDebugDescription=Authentication Failed The authentication failed., AMSFailureReason=The authentication failed.}}, client-environment-type=Sandbox}
0
0
112
May ’25
CNContact poster
Hi all, From what I’ve seen on forums and other sources, it appears that nothing can be done to set the contact poster programmatically. Setting the imageData property affects only the thumbnail image. Does anyone know if this is explicitly documented somewhere? I need this information for a POC document. I watched the iOS 17 keynote (where it was introduced), the Platform State of Union, and other WWDC videos, but I couldn’t find any mention of it. The Contacts framework documentation only explains what can be retrieved from this property and doesn’t mention any way to set the contact poster. If anyone has any information on this, please help! Thanks in advance!
0
0
86
Mar ’25
Combining Screen Time Usage with HealthKit Data in a Chart
Hello Apple Developer Community, I’m working on creating a chart that combines Screen Time Usage data with Workout Time from HealthKit. I’ve successfully implemented a DeviceActivityReportExtension to fetch Screen Time data and draw a chart. I’m also able to read HealthKit data from the main app. However, I’m having trouble integrating the HealthKit data into the View generated by the DeviceActivityReportExtension. I’ve attempted to read HealthKit data directly from the extension , but this doesn’t seem to work, likely due to HealthKit access restrictions in extensions. I also tied using a shared object to pass HealthKit data to the extension, but unfortunately this didn’t seem to work as expected. I’d greatly appreciate any suggestions on how to successfully integrate HealthKit data into the extension-generated View. Has anyone dealt with a similar challenge or found a workaround for this? Thanks in advance for your help!
0
0
92
Mar ’25
Flow Divert behavior
Hello, Our app uses Network Extension / Packet Tunnel Provider to establish VPN connections on macOS and iOS. We have observed that after creating a utun device and adding any IPv4 routes (NEPacketTunnelNetworkSettings.IPv4Settings), the OS automatically adds several host routes via utun to services such as Akamai, Apple Push, etc. These routes appear to correspond to TCP flows that were active at the moment the VPN connection was established. When a particular TCP flow ends, the corresponding host route is deleted. We understand this is likely intended to avoid breaking existing TCP connections. However, we find the behavior of migrating existing TCP flows to the new utun interface simply because any IPv4 route is added somewhat questionable. This approach would make sense in a "full-tunnel" scenario — for example, when all IPv4 traffic (e.g., 0.0.0.0/0) is routed through the tunnel — but not necessarily in a "split-tunnel" configuration where only specific IPv4 routes are added. Is there any way to control or influence this behavior? Would it be possible for FlowDivert to differentiate between full-tunnel and split-tunnel cases, and only preserve existing TCP flows via utun in the full-tunnel scenario? Thank you.
0
0
112
Apr ’25
Understanding `EINTR`
I’ve talked about EINTR a bunch of times here on DevForums. Today I found myself talking about it again. On reading my other explanations, I didn’t think any of them were good enough to link to, so I decided to write it up properly. If you have questions or comments, please put them in a new thread here on DevForums. Use the App & System Services > Core OS topic area so that I see it. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" Understanding EINTR Many BSD-layer routines can fail with EINTR. To see this in action, consider the following program: import Darwin func main() { print("will read, pid: \(getpid())") var buf = [UInt8](repeating: 0, count: 1024) let bytesRead = read(STDIN_FILENO, &buf, buf.count) if bytesRead < 0 { let err = errno print("did not read, err: \(err)") } else { print("did read, count: \(bytesRead)") } } main() It reads some bytes from stdin and prints the result. Build this and run it in one Terminal window: % ./EINTRTest will read, pid: 13494 Then, in other window, stop and start the process by sending it the SIGSTOP and SIGCONT signals: % kill -STOP 13494 % kill -CONT 13494 In the original window you’ll see something like this: % ./EINTRTest will read, pid: 13494 zsh: suspended (signal) ./EINTRTest % did not read, err: 4 [1] + done ./EINTRTest When you send the SIGSTOP the process stops and the shell tells you that. But looks what happens when you continue the process. The read(…) call fails with error 4, that is, EINTR. The read man page explains this as: [EINTR] A read from a slow device was interrupted before any data arrived by the delivery of a signal. That’s true but unhelpful. You really want to know why this error happens and what you can do about it. There are other man pages that cover this topic in more detail — and you’ll find lots of info about it on the wider Internet — but the goal of this post is to bring that all together into one place. IMPORTANT The description of the EINTR error, as returned by strerror and friends, is Interrupted system call. If you see code display or log that description, you’re dealing with EINTR. Signal and Interrupts In the beginning, Unix didn’t have threads. It implemented asynchronous event handling using signals. For more about signals, see the signal man page. The mechanism used to actually deliver a signal is highly dependent on the specific Unix implementation, but the general idea is that: The system decides on a specific process (or, nowadays, a thread) to run the signal handler. If that’s blocked inside the kernel waiting for a system call to complete [1], the system unblocks the system call by failing it with an EINTR error. Thus, every system call that can block [2] might fail with an EINTR. You see this listed as a potential error in the man pages for read, write, usleep, waitpid, and many others. [1] There’s some subtlety around the definition of system call. On traditional Unix systems, executables would make system calls directly. On Apple platforms that’s not supported. Rather, an executable calls a routine in the System framework which then makes the system call. In this context the term system call is a shortcut for a System framework routine that maps to a traditional Unix system call. [2] There’s also some subtlety around the definition of block. Pretty much every system call can block for some reason or another. In this context, however, a block means to enter an interruptible wait state, typically while waiting for I/O. This is what the above man page quote is getting at when it says slow device. Solutions This is an obvious pitfall and it would be nice if we could just get rid of it. However, that’s not possible due to compatibility concerns. And while there are a variety of mechanism to automatically retry a system call after a signal interrupt, none of them are universally applicable. If you’re working on a large scale program, like an app for Apple’s platforms, you only good option is to add code to retry any system call that can fail with EINTR. For example, to fix the program at the top of this post you might wrap the read(…) system call like so: func readQ(_ d: Int32, _ buf: UnsafeMutableRawPointer!, _ nbyte: Int) -> Int { repeat { let bytesRead = read(d, buf, nbyte) if bytesRead < 0 && errno == EINTR { continue } return bytesRead } while true } Note In this specific case you’d be better off using the read(into:retryOnInterrupt:) method from System framework. It retries by default (if that’s not appropriate, pass false to the retryOnInterrupt parameter). You can even implement the retry in a generic way. See the errnoQ(…) snippet in QSocket: System Additions. Library Code If you’re writing library code, it’s important that you handle EINTR so that your clients don’t have to. In some cases it might make sense to export a control for this, like the retryOnInterrupt parameter shown in the previous section, but it should default to retrying. If you’re using library code, you can reasonably expect it to handle EINTR for you. If it doesn’t, raise that issue with the library author. And you get this error back from an Apple framework, like Foundation or Network framework, please file a bug against the framework. Revision History 2025-04-13 Added the description of the error, Interrupted system call, to make it easier for folks to find this post. 2024-10-14 First posted.
0
0
730
Apr ’25
Issues with Integration of Promotional Offers in React Native app
Hi All, We are trying to integrate Promotional Offer in our app, We have a React Native app and are using react-native-iap for handling our in app purchases, as per the documentation we are generating signature in our BE and passing the proper details to the function as well, but for subscription request which have offer applied we are getting the apple pop up properly as well with offer details but when trying to subscribe it gives us SKErrroDomain: 12, for subscription without applying offer the subscription goes through but when we apply the offer we get the above error. Our app is currently in Development Stages and has not been sent for review sam for our subscription plans as well. Please let me know what could be the probable cause for this and help us resolve the issue. This is the code snippet of ours for the front end : export const buySubscription = async (subscriptionData: any) => { try { if (subscriptionData.offer_id) { const response = await getSubscriptionSignature( subscriptionData.productId, subscriptionData.offer_id, ); const offerData = response?.data; const offer = { identifier: offerData?.offer_id, keyIdentifier: offerData?.key_id, nonce: offerData?.nonce, signature: offerData?.signature, timestamp: Number(offerData?.timestamp), }; await requestSubscription({ sku: subscriptionData.productId, withOffer: offer, }); } else { await requestSubscription({ sku: subscriptionData.productId }); } } catch (err) { logger.error('Subscription error: ' + JSON.stringify(err)); throw err; } }; and 
from my python Backend which generates the signature:

def generate_signature(self, product_id: str, offer_id: str) -> dict: """ Generate signature for Apple StoreKit promotional offers. Args: product_id: The product identifier from App Store Connect offer_id: The promotional offer identifier Returns: dict: Contains signature and required metadata Reference: https://developer.apple.com/documentation/storekit/in-app_purchase/original_api_for_in-app_purchase/subscriptions_and_offers/implementing_promotional_offers_in_your_app """ try: # Generate UUID without dashes and use as nonce nonce = str(uuid.uuid4()) timestamp = get_current_time_ms() # milliseconds # Create the payload string in exact order required by Apple payload_components = [ self.bundle_id, # App Bundle ID self.key_id, # Key ID from App Store Connect product_id, # Product identifier offer_id, # Promotional offer identifier nonce, # UUID without dashes str(timestamp) # Current timestamp in milliseconds ] payload_str = "\u2063".join(payload_components) # Use Unicode separator logger.debug(f"Signing payload: {payload_str}") # Create SHA256 hash of the payload digest = hashes.Hash(hashes.SHA256()) digest.update(payload_str.encode('utf-8')) payload_hash = digest.finalize() # Sign the hash using ES256 (ECDSA with SHA-256) signature = self.private_key.sign( data=payload_hash, signature_algorithm=ec.ECDSA(hashes.SHA256()) ) # Encode signature in base64 signature_b64 = base64.b64encode(signature).decode('utf-8') logger.info(f"Generated signature for product {product_id} and offer {offer_id}") return { "key_id": self.key_id, # Changed to match Apple's naming "nonce": nonce, # UUID without dashes "timestamp": timestamp, # As integer "signature": signature_b64, # Base64 encoded signature "product_id": product_id, # Changed to match Apple's naming "offer_id": offer_id # Changed to match Apple's naming } except Exception as e: logger.error(f"Failed to generate signature: {str(e)}") raise HTTPException( status_code=500, detail=f"Failed to generate signature: {str(e)}" )
0
0
81
Apr ’25
Location Permission Management for Parental Control Apps with Screen Time Authorization
Apple Feedback Ticket: FB16804936 Background We develop a parental control application called Adora Kids (https://apps.apple.com/us/app/adora-kids/id6443787669) that requires "Location Always" permission to function properly. Our app has Screen Time authorization and provides monitoring services for parents. Issue We are experiencing a recurring problem where child users receive the system notification "Adora accessed your location in the background" every few days. This frequently results in children disabling location permissions, which prevents our app from functioning as intended. Current Approach and Limitations We have explored using Content & Privacy Restrictions for Location Services as a potential solution, but have encountered two significant limitations: These restrictions cannot be accessed programmatically via the ManagedSettings framework (unlike AppStoreSettings and other restrictions). The current implementation is "all-or-nothing" - enabling location restrictions blocks permission changes for ALL apps on the device, preventing children from granting legitimate location access to other applications. Questions Is there a way to programmatically access and manage Content & Privacy Restrictions for Location Services through the ManagedSettings framework that we might have overlooked? Are there any recommended approaches for apps with Screen Time authorization to prevent users from changing specific permissions (particularly location) while still allowing them to manage permissions for other apps? Does Apple have plans to implement app-specific permission locking for apps with Screen Time authorization in future iOS releases? Are there any alternative approaches or workarounds that other developers have successfully implemented for this use case? Any guidance from the developer community or Apple engineers would be greatly appreciated. This is a critical functionality issue affecting the reliability of our parental control service. Thank you in advance for your assistance.
0
3
379
Mar ’25
Disambiguation for .system.search AppIntent
I'd like to display a list of items to disambiguate for a fulltext search intent. Using the Apple AppIntentsSampleApp, I added TrailSearch.swift: import AppIntents @AssistantIntent(schema: .system.search) struct TrailSearch: AppIntent { static let title: LocalizedStringResource = "Search Trail" static let description = IntentDescription("Search trail by name.", categoryName: "Discover", resultValueName: "Trail") @Parameter(title: "Trail") var criteria: StringSearchCriteria func perform() async throws -> some IntentResult & ReturnsValue<TrailEntity> { if criteria.term.isEmpty { throw $criteria.needsValueError(IntentDialog("need value")) } let trails = TrailDataManager.shared.trails { trail in trail.name.contains(criteria.term) } if trails.count > 1 { throw $criteria.needsDisambiguationError(among: trails.map { StringSearchCriteria(term: $0.name) }) } else if let firstTrail = trails.first { return .result(value: TrailEntity(trail: firstTrail)) } throw $criteria.needsValueError(IntentDialog("Nothing found")) } } Now when I type "trail" which matches several trails and thus lets us enter the disambiguation code path, the Shortcut app just displays the dialog title but no disambiguation items to pick from. Is this by design or a bug? (filed as FB17412220)
0
0
110
Apr ’25
not getting stable release versions of some apps from the ios app store
I have been receiving beta software from the iPad App Store, despite not being enrolled in a beta program. Additionally, I do not have TestFlight or the Feedback app installed on my device. There are no certificates or profiles displayed either. I am using the App Store app that comes preinstalled on my device (note that I am not located in Europe). My iPad has been experiencing significant bugs, including numerous screen glitches and periods of sluggishness. Furthermore, numerous applications have crashed frequently. I was able to confirm that I was receiving beta software because the crash reports include beta identifier numbers. According to Apple documentation regarding analytic reports, a beta identifier will only be visible for beta applications. anyone know what could be going on or how to fix this?
0
0
58
Apr ’25
StoreKit 2: jwsRepresentation Validation, Rate-Limit Relief, and Send Consumption Info Effectiveness
Hi everyone, We operate an online game where all in-app assets are stored server-side and require a logged-in account (no device binding). I’d like guidance on four areas: Do we really need deviceVerification / deviceVerificationNonce? – Because every purchase is tied to an account and we enforce a global transactionId UNIQUE constraint, replay or cross-account reuse appears infeasible. Under these conditions, is omitting device verification acceptable, or are there situations where Apple still recommends it? Permanent rate-limit increase for the App Store Server API – During anniversary events we saw bursts of ~18 000 requests per hour, breaching the current hourly cap on the App Store Server API (verifyTransaction, getNotificationHistory, etc.). Is there a formal process to request a long-term rate-limit expansion (or an alternative tier) from Apple? When is an App Store Server API call required for a StoreKit 2 jwsRepresentation? Docs say “call the API if you’re unsure,” but there’s no clear cut-off. Because we fully validate the JWS signature plus the entire certificate chain (including CRL/OCSP checks) on our server, local cryptographic validation seems sufficient for consumables. For subscriptions we still plan to hit the API to fetch the latest status. Does this separation match Apple’s best practice? If Apple does recommend hitting the API for consumables as well, we’d like a concrete rule of thumb—e.g. “if the item price is USD 50 or higher, always use the API.” Is establishing such thresholds consistent with Apple’s intent? Refund-risk reduction from Send Consumption Info – Adapty reports a 40–60 % refund-rate drop for subscriptions when using Send Consumption Info (blog reference). Can we expect similar reduction for consumable IAP in social/online games? Any real-world results would be helpful. Thanks in advance for any guidance!
0
0
191
Apr ’25
Proper way to create an AppleEvent record descriptor from NSDictionary
When using NSScriptCommand, is there any way to create an NSAppleEventDescriptor from an NSDictionary with arbitrary keys without using keyASUserRecordFields? Am I correct in thinking that this constant is deprecated? I ask because there is still active documentation using it. Is there another way to return a record where the keys aren't known at compile-time?
0
0
127
Apr ’25
Stopping certain data models from syncing to cloudkit
Hi all, I am using SwiftData and cloudkit and I am having an extremely persistent bug. I am building an education section on a app that's populated with lessons via a local JSON file. I don't need this lesson data to sync to cloudkit as the lessons are static, just need them imported into swiftdata so I've tried to use the modelcontainer like this: static func createSharedModelContainer() -> ModelContainer { // --- Define Model Groups --- let localOnlyModels: [any PersistentModel.Type] = [ Lesson.self, MiniLesson.self, Quiz.self, Question.self ] let cloudKitSyncModels: [any PersistentModel.Type] = [ User.self, DailyTip.self, UserSubscription.self, UserEducationProgress.self // User progress syncs ] However, what happens is that I still get Lesson and MiniLesson record types on cloudkit and for some reason as well, whenever I update the data models or delete and reinstall the app on simulator, the lessons duplicate (what seems to happen is that a set of lessons comes from the JSON file as it should), and then 1-2 seconds later, an older set of lessons gets synced from cloudkit. I can delete the old set of lessons if I just delete the lessons and mini lessons record types, but if I update the data model again, this error reccurrs. Sorry, I don't know if I managed to explain this well but essentially I just want to stop the lessons and minilessons from being uploaded to cloudkit as I think this will fix the problem. Am I doing something wrong with the code?
0
0
108
Apr ’25