Posts under App & System Services topic

Post

Replies

Boosts

Views

Activity

Issue Integrating Apple Pay JS – `merchantSession` Blocke
Hello Apple Devs, We’re currently trying to integrate Apple Pay on the web using Apple Pay JS. We've followed the official documentation closely, but we're running into a blocker during the merchantSession validation phase. We successfully retrieved a merchantSession, which looks like this: json { "displayName": "Our Name", "domainName": "https://pay.ourdomain.co", "epochTimestamp": , "expiresAt": ****************, "merchantIdentifier": "", "merchantSessionIdentifier": ", "nonce": "", "operationalAnalyticsIdentifier": our name "t:", "pspId": "", "retries": 0, "signature": "*****************..." } Issue: Shortly after initiating the session, we receive a cancel event with the following info: ApplePayCancelEvent { type: "cancel", sessionError: { code: "unknown", info: {} } } We're unsure what causes the cancellation. There are no clear error messages or hints in the logs to identify what went wrong. What We’ve Checked: The merchantSession is returned successfully from our backend. The domainName matches our frontend domain (https://pay.durdomain.co). The session hasn’t expired when tested. We're using Apple Pay JS APIs as described in the documentation. Help Needed: What can trigger an ApplePayCancelEvent with an "unknown" error code? Any insight or guidance would be deeply appreciated. Thanks in advance!
1
0
131
Apr ’25
App Groups in Provisioning Profile
I'll preface by saying I am new to MacOS development. I've struggled with this issue for several days and have nowhere else to go for help. My MacOS app is an Electron build. It needs application-groups entitlement for IPC. But the developer portal, when generating the provisioning profile, always appends "groups." to the start and I am unable to remove it. This renders my provisioning profile invalid and causes my app to be rejected by Transporter because it is not supposed to start with "groups", but with my team identified for MacOS. Maybe I can still use the provisioning profile as is, but I've not found any way to do that. So I'm stuck unable to deliver. Any help with this is appreciated.
1
0
135
Apr ’25
Issue with Sticker Pack Extension
I'm unable to have stickers show in messages even with a new iOS app and a sticker pack extension target. I do see the iMessage App Icon but after tapping it nothing shows and I see a warning: "Error creating the CFMessagePort needed to communicate with PPT" This was tested on simulator and on real device. Xcode 16.1 (16B40) iOS 18.1 & 18.2
1
0
96
Mar ’25
SwiftData and async functions
Hello, I recently published an app that uses Swift Data as its primary data storage. The app uses concurrency, background threads, async await, and BLE communication. Sadly, I see my app incurs many fringe crashes, involving EXC_BAD_ACCESS, KERN_INVALID_ADDRESS, EXC_BREAKPOINT, etc. I followed these guidelines: One ModelContainer that is stored as a global variable and used throughout. ModelContexts are created separately for each task, changes are saved manually, and models are not passed around. Threads with different ModelContexts might manipulate and/or read the same data simultaneously. I was under the impression this meets the usage requirements. I suspect perhaps the issue lies in my usage of contexts in a single await function, that might be paused and resumed on a different thread (although same execution path). Is that the case? If so, how should SwiftData be used in async scopes? Is there anything else particularly wrong in my approach?
4
0
1.3k
Mar ’25
Push Notifications largely not get transmitted
I have three apps with a very low user rate, so it's easier to compare. In all three apps, when I send a notification to APNs, over two-thirds receive a "Stored - Device Offline" status, but only one or two notifications are delivered afterward. No message has been sent after that. The total number of recipients is 89; 26 were delivered to the device, and 62 were stored in APNs. One was delivered from storage, and one was discarded. All app users are located in the same region, and mobile internet or Wi-Fi is available everywhere. I can't believe that so many iPhone users aren't getting connected to APNs to receive the stored message. Or are event not connected. Or are there any other reasons why a notification cant be transmitted. (User beahaviour, time of not using the app or something else?)
4
0
113
Mar ’25
Wrong Product.displayPrice?
I am using StoreKit 2 for my products and noticed that users from Ukraine (for example) receive a wrong Product.displayPrice. The App Store works with USD but shows the local currency UAH. Any chance to display the correct currency (USD)?
1
0
79
Apr ’25
iOS 18.3.1 - QLPreviewControllerView closing triggers AX Lookup problem - errorCode:1100 error:Permission denied portName:'com.apple.iphone.axserver' PID:1022
Since iOS 18.3.1, In lower iOS versions it works fine though. QLPreviewController shows a blank white screen instead of showing the document. Additionally, it does not display the 'Done' option at the top-right to close the view. Presenting the QLPreviewController works fine to display the document, but for the second time, it renders the blank white screen as described. While launching QLPreviewControllerView for the first time. I'm receiving the following message in the console and it displays the document. LaunchServices: store (null) or url (null) was nil: Error Domain=NSOSStatusErrorDomain Code=-54 "process may not map database" UserInfo={NSDebugDescription=process may not map database, _LSLine=72, _LSFunction=_LSServer_GetServerStoreForConnectionWithCompletionHandler} Attempt to map database failed: permission was denied. This attempt will not be retried. Closing the QLPreviewController with the help of the 'Done' option from top-right or swipe to close triggers the following message in the console. Connection to appex interrupted AX Lookup problem - errorCode:1100 error:Permission denied portName:'com.apple.iphone.axserver' PID:1022 ( 0 AXRuntime 0x00000001d2cd7758 _AXGetPortFromCache + 796 1 AXRuntime 0x00000001d2cdd02c AXUIElementPerformFencedActionWithValue + 700 2 UIKit 0x0000000258cdf488 7F0274D9-D3C9-3193-B606-1C74BE53B86C + 1537160 3 libdispatch.dylib 0x0000000101bb888c _dispatch_call_block_and_release + 32 4 libdispatch.dylib 0x0000000101bba578 _dispatch_client_callout + 20 5 libdispatch.dylib 0x0000000101bc2454 _dispatch_lane_serial_drain + 840 6 libdispatch.dylib 0x0000000101bc325c _dispatch_lane_invoke + 408 7 libdispatch.dylib 0x0000000101bd06fc _dispatch_root_queue_drain_deferred_wlh + 328 8 libdispatch.dylib 0x0000000101bcfd0c _dispatch_workloop_worker_thread + 580 9 libsystem_pthread.dylib 0x0000000225ea4680 _pthread_wqthread + 288 10 libsystem_pthread.dylib 0x0000000225ea2474 start_wqthread + 8 ) Trying to open he document again, Ultimately results in the white blank screen to be displayed with no options to close. It displays the Navigation bar only for the fraction of time. Leading users to force close the app and start again.
1
0
273
Mar ’25
Invalid currency symbol
Strange issue with currency display in subscription products Hi everyone, I'm facing a strange issue in my app where I use a subscription-based in-app purchase model. The products I created in App Store Connect are all in "Approved" status. I've tested with both RevenueCat and StoreKit, but the result is the same. Here are the products being loaded: Product loaded: weekly_product_id Display name: Weekly Pro Description: Weekly Pro Subscription Price: ₺229,99 Product loaded: annual_product_id Display name: Annual Pro Description: Annual Pro Subscription Price: ₺1.799,99 Even though I can see the correct prices and currency (Turkish Lira) in the Xcode debug console, on my real device the currency appears as Philippine Peso, as shown in the attached screenshot. Interestingly, in the iOS simulator, it's displayed in USD. I've double-checked and my device's region settings are set to Turkey. Any ideas on what could be causing this? And more importantly, how can I fix it? Thanks in advance!
3
0
109
Apr ’25
Sleep Samples sum off by 2 minutes
Hi everyone! I'm trying to get the total sleep time for a given day, but users report that there's a difference between what my app reports and what the Apple Health app reports. In particular, we're off by 2 minutes less on average. What we're doing is: Get all the samples that are either core, deep, rem or unspecified Cut-off time at 3 PM previous day Merge overlapping intervals Add all the remaining intervals For debugging purposes I'm storing and sending all the raw samples to a server, and I have run tests and I don't find anything wrong. It looks like the number we come up with is correct according to our own rules. I wonder, how is Apple adding up all the samples to arrive at a number that's slightly off to our number. Any insight would be appreciated. Thanks.
5
0
254
Mar ’25
Inconsistent BLE Extended Advertising Scanning on iOS
I'm developing an iOS 18 app using Core Bluetooth on an iPhone 16 Pro to scan for BLE Extended Advertising packets. However, scanning behavior is inconsistent. Sometimes, the app detects extended advertising packets correctly, but other times, it fails to find them even when the advertiser is active. I tested using nRF Connect on both my iPhone 16 Pro and another Android device that I'm also developing an app for. The Android device consistently detects the extended advertising packets, but my iPhone 16 Pro has inconsistent results. Legacy advertising packets are scanned without any issues. The same peripheral is consistently detected on Android and other BLE scanners. I've tested with different scan settings, restarted Bluetooth, and rebooted the device, but the issue persists. Does iOS 18 have any known limitations with BLE Extended Advertising? Any workarounds to improve scanning reliability?
0
0
172
Mar ’25
BLE timeout issue when connecting two devices on iOS 18 (but not iOS 16)
Hi, We’re developing a BLE peripheral device and encountered a connection issue when connecting two devices (Device A and Device B) simultaneously to an iOS device. Problem: On iOS 18, we are experiencing occasional BLE timeouts and disconnections when both devices are connected at the same time. On iOS 16, we did not encounter this issue under the same conditions. What we’ve tried: Adjusted the connection interval from 30ms to 15ms. This seems to have improved stability somewhat. However, we still observe intermittent timeout/disconnection issues. Questions: Are there any known changes in BLE connection handling or timing constraints in iOS 18? Are there recommended connection parameter settings (interval, latency, timeout, etc.) for multi-device BLE connections in iOS? Is there a way to debug or log more details about the disconnection reasons on the iOS side? Any guidance or suggestions would be greatly appreciated.
0
0
166
Apr ’25
Custom IPSec IKEv2 with Packet Tunnel Provider Extension on iOS
We’re looking to implement a custom IPSec IKEv2 VPN using the Packet Tunnel Provider network extension on iOS because we need to add extra information to EAP, which the built-in IKEv2 VPN configuration does not support. Is it possible to handle the full IKEv2 negotiation and IPSec tunneling within the Packet Tunnel Provider extension? Or are there limitations that would prevent implementing a full IKEv2 stack this way? Any insights or alternative approaches would be appreciated. Thanks!
1
0
107
Mar ’25
Push Live Activity not showing up
This is in an iOS Simulator running iOS 18.2 I send a start live activity push notification from the Push Notifications Console on icloud.developer.apple.com. When checking the console.log output it seems to receive the message, yet the activity does not appear in the dynamic island. (the app is backgrounded when I test this) Can anyone tell me why it's not showing? Starting the same activity from within the app using Swift code works fine. Here is the console.app output: default 11:01:59.060954+0100 apsd <APSConnectionServer: 0x104207b80; development/com.apple.aps.sessioncore.PushNotifications.dev/liveactivitiesd 0>: Sending push to client. UUID: (null) default 11:01:59.061012+0100 apsd Dispatching high priority message on server: <APSConnectionServer: 0x104207b80; development/com.apple.aps.sessioncore.PushNotifications.dev/liveactivitiesd 0> default 11:01:59.061770+0100 apsd Looking up connection on peer: 4304b50 found <APSConnectionServer: 0x104207b80; development/com.apple.aps.sessioncore.PushNotifications.dev/liveactivitiesd 0> default 11:01:59.062283+0100 liveactivitiesd APSXPCDeliverMessageEvent: Created APSIncomingMessage. UUID: (null) default 11:01:59.062642+0100 liveactivitiesd <APSConnection: 0x600003d18000> Delivering message from apsd: <APSIncomingMessage: 0x600000c2e9a0> 2897852514 com.****.****.push-type.liveactivity default 11:01:59.062763+0100 liveactivitiesd <APSConnection: 0x600003d18000> Delivering message from apsd. UUID: (null) default 11:01:59.063374+0100 liveactivitiesd <APSConnection: 0x600003d18000> making delegate (<SessionPushNotifications.APSPushConnection: 0x600000227460>) calls to deliver message 2897852514 { aps = { alert = { "loc-key" = "recording_started_message"; "title-loc-key" = "recording_started_title"; }; attributes = { isRecording = 1; }; "attributes-type" = SWAutomaticTripRecorderActivityAttributes; "content-state" = { distance = 0; }; event = start; timestamp = 1742374701; }; } for topic com.****.****test.push-type.liveactivity default 11:01:59.063440+0100 liveactivitiesd <APSConnection: 0x600003d18000> calling <SessionPushNotifications.APSPushConnection: 0x600000227460> connection:didReceiveIncomingMessage: default 11:01:59.063740+0100 liveactivitiesd Acquiring keep-alive with reason: Received message default 11:01:59.063785+0100 liveactivitiesd Keep-alive reasons: ["Received message": 1] default 11:01:59.063803+0100 liveactivitiesd <APSConnection: 0x600003d18000> returned from <SessionPushNotifications.APSPushConnection: 0x600000227460> connection:didReceiveIncomingMessage: default 11:01:59.063883+0100 liveactivitiesd <APSConnection: 0x600003d18000> responding with an ack for message with guid E19D7D04-12A0-4F1B-B33C-F6BF57EE2EFF default 11:01:59.063921+0100 liveactivitiesd <APSConnection: 0x600003d18000> responding with an ack. UUID: (null) default 11:01:59.063996+0100 apsd Looking up connection on peer: 4304b50 found <APSConnectionServer: 0x104207b80; development/com.apple.aps.sessioncore.PushNotifications.dev/liveactivitiesd 0> default 11:01:59.064019+0100 apsd <APSUserCourier 0x100f052a0 development 0> informed that <APSConnectionServer: 0x104207b80; development/com.apple.aps.sessioncore.PushNotifications.dev/liveactivitiesd 0> acknowledges incoming message with guid E19D7D04-12A0-4F1B-B33C-F6BF57EE2EFF tracingUUID (null) default 11:01:59.064063+0100 liveactivitiesd Received message: topic: Topic(unsuffixed: "com.****.****test"); channelID: nil; token: Optional(128 bytes); eventType: start(SessionPushNotifications.IncomingMessage.EventType.StartParameters(attributesType: "SWAutomaticTripRecorderActivityAttributes", attributesData: 20 bytes, inputs: [])) for environment: development default 11:01:59.064198+0100 liveactivitiesd Received push event for com.****.****test::pushToStart default 11:01:59.064232+0100 liveactivitiesd Adding push-to-start budget for com.****.****test::pushToStart default 11:01:59.064273+0100 liveactivitiesd Acquiring keep-alive with reason: Database default 11:01:59.064296+0100 liveactivitiesd Keep-alive reasons: ["Database": 1, "Received message": 1] default 11:01:59.064313+0100 liveactivitiesd Acquiring keep-alive with reason: Database default 11:01:59.064330+0100 liveactivitiesd Keep-alive reasons: ["Database": 2, "Received message": 1] default 11:01:59.064342+0100 liveactivitiesd Reduced budget for com.****.****test::pushToStart to: 9 default 11:01:59.064358+0100 liveactivitiesd Topic com.****.****test.push-type.liveactivity has remaining budget for pushToStart of 9 default 11:01:59.064369+0100 liveactivitiesd Topic com.****.****test.push-type.liveactivity has not used any budget for activity default 11:01:59.064436+0100 liveactivitiesd Scheduling wake to re-evaluate push subscription budgets at 2025-03-19 11:01:59 +0000 default 11:01:59.064547+0100 liveactivitiesd Earliest nonwaking date from task "Push server budget timeout expiration": 2025-03-19T12:01:59+01:00, finalWakeTarget: 2025-03-19T12:01:59+01:00 3599.999696 default 11:01:59.064593+0100 liveactivitiesd Earliest waking date from task "Push server budget timeout expiration": 2025-03-19T12:01:59+01:00, finalWakeTarget: 2025-03-19T12:01:59+01:00 3599.999651 default 11:01:59.064620+0100 liveactivitiesd Scheduling nonwaking task for: 2025-03-19T12:01:59+01:00 in 3599.999622s default 11:01:59.064659+0100 liveactivitiesd Scheduling waking task for: 2025-03-19T12:01:59+01:00 in 3599.999584s default 11:01:59.064671+0100 liveactivitiesd Acquiring keep-alive with reason: wake scheduling default 11:01:59.064692+0100 liveactivitiesd Keep-alive reasons: ["Database": 2, "Received message": 1, "wake scheduling": 1] default 11:01:59.064734+0100 liveactivitiesd Scheduling waking task for adjusted date: 2025-03-19T12:01:59+01:00 in 3599.999508s default 11:01:59.064768+0100 liveactivitiesd xpc_activity_register: com.apple.sessionkit.wake, criteria: dictionary default 11:01:59.064843+0100 liveactivitiesd Received pushToStart notification for com.****.****test::pushToStart default 11:01:59.064955+0100 liveactivitiesd Keep-alive reasons: ["Database": 2, "Received message": 1] default 11:01:59.064979+0100 liveactivitiesd Publishing event: timestamp: 2025-03-19 08:58:21 +0000; activityIdentifier: F432AB2F-1799-4437-B54B-6D9D70A0B260; eventType: start(SessionPushNotifications.PushEvent.EventType.ActivityStartParameters(attributesType: "SWAutomaticTripRecorderActivityAttributes", attributesData: 20 bytes, contentSourceRequests: [ActivityKit.ActivityContentSource.Request.push(request: ActivityKit.PushActivityContentSource.Request.push, target: ProcessDescriptor.Request("com.****.****test")), ActivityKit.ActivityContentSource.Request.process(target: ProcessDescriptor.Request("com.****.****test"))]))
1
0
116
Mar ’25
Debugging/Fixing deleted relationship objects with SwiftData
Using SwiftData and this is the simplest example I could boil down: @Model final class Item { var timestamp: Date var tag: Tag? init(timestamp: Date) { self.timestamp = timestamp } } @Model final class Tag { var timestamp: Date init(timestamp: Date) { self.timestamp = timestamp } } Notice Tag has no reference to Item. So if I create a bunch of items and set their Tag. Later on I add the ability to delete a Tag. Since I haven't added inverse relationship Item now references a tag that no longer exists so so I get these types of errors: SwiftData/BackingData.swift:875: Fatal error: This model instance was invalidated because its backing data could no longer be found the store. PersistentIdentifier(id: SwiftData.PersistentIdentifier.ID(url: x-coredata://EEC1D410-F87E-4F1F-B82D-8F2153A0B23C/Tag/p1), implementation: SwiftData.PersistentIdentifierImplementation) I think I understand now that I just need to add the item reference to Tag and SwiftData will nullify all Item references to that tag when a Tag is deleted. But, the damage is already done. How can I iterate through all Items that referenced a deleted tag and set them to nil or to a placeholder Tag? Or how can I catch that error and fix it when it comes up? The crash doesn't occur when loading an Item, only when accessing item.tag?.timestamp, in fact, item.tag?.id is still ok and doesn't crash since it doesn't have to load the backing data. I've tried things like just looping through all items and setting tag to nil, but saving the model context fails because somewhere in there it still tries to validate the old value. Thanks!
2
0
380
Mar ’25
About USB accessory certification
I have a question about Apple certification. We are planning card reader via HID(human interface device) for iPad that support USB-C. iPad will receive data as HID protocol. In this case do I have to get certificate(for example MFi) like Apple USB accessory?
3
0
151
Apr ’25
BSD Privilege Escalation on macOS
This week I’m handling a DTS incident from a developer who wants to escalate privileges in their app. This is a tricky problem. Over the years I’ve explained aspects of this both here on DevForums and in numerous DTS incidents. Rather than do that again, I figured I’d collect my thoughts into one place and share them here. If you have questions or comments, please start a new thread with an appropriate tag (Service Management or XPC are the most likely candidates here) in the App & System Services > Core OS topic area. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" BSD Privilege Escalation on macOS macOS has multiple privilege models. Some of these were inherited from its ancestor platforms. For example, Mach messages has a capability-based privilege model. Others were introduced by Apple to address specific user scenarios. For example, macOS 10.14 and later have mandatory access control (MAC), as discussed in On File System Permissions. One of the most important privilege models is the one inherited from BSD. This is the classic users and groups model. Many subsystems within macOS, especially those with a BSD heritage, use this model. For example, a packet tracing tool must open a BPF device, /dev/bpf*, and that requires root privileges. Specifically, the process that calls open must have an effective user ID of 0, that is, the root user. That process is said to be running as root, and escalating BSD privileges is the act of getting code to run as root. IMPORTANT Escalating privileges does not bypass all privilege restrictions. For example, MAC applies to all processes, including those running as root. Indeed, running as root can make things harder because TCC will not display UI when a launchd daemon trips over a MAC restriction. Escalating privileges on macOS is not straightforward. There are many different ways to do this, each with its own pros and cons. The best approach depends on your specific circumstances. Note If you find operations where a root privilege restriction doesn’t make sense, feel free to file a bug requesting that it be lifted. This is not without precedent. For example, in macOS 10.2 (yes, back in 2002!) we made it possible to implement ICMP (ping) without root privileges. And in macOS 10.14 we removed the restriction on binding to low-number ports (r. 17427890). Nice! Decide on One-Shot vs Ongoing Privileges To start, decide whether you want one-shot or ongoing privileges. For one-shot privileges, the user authorises the operation, you perform it, and that’s that. For example, if you’re creating an un-installer for your product, one-shot privileges make sense because, once it’s done, your code is no longer present on the user’s system. In contrast, for ongoing privileges the user authorises the installation of a launchd daemon. This code always runs as root and thus can perform privileged operations at any time. Folks often ask for one-shot privileges but really need ongoing privileges. A classic example of this is a custom installer. In many cases installation isn’t a one-shot operation. Rather, the installer includes a software update mechanism that needs ongoing privileges. If that’s the case, there’s no point dealing with one-shot privileges at all. Just get ongoing privileges and treat your initial operation as a special case within that. Keep in mind that you can convert one-shot privileges to ongoing privileges by installing a launchd daemon. Just Because You Can, Doesn’t Mean You Should Ongoing privileges represent an obvious security risk. Your daemon can perform an operation, but how does it know whether it should perform that operation? There are two common ways to authorise operations: Authorise the user Authorise the client To authorise the user, use Authorization Services. For a specific example of this, look at the EvenBetterAuthorizationSample sample code. Note This sample hasn’t been updated in a while (sorry!) and it’s ironic that one of the things it demonstrates, opening a low-number port, no longer requires root privileges. However, the core concepts demonstrated by the sample are still valid. The packet trace example from above is a situation where authorising the user with Authorization Services makes perfect sense. By default you might want your privileged helper tool to allow any user to run a packet trace. However, your code might be running on a Mac in a managed environment, where the site admin wants to restrict this to just admin users, or just a specific group of users. A custom authorisation right gives the site admin the flexibility to configure authorisation exactly as they want. Authorising the client is a relatively new idea. It assumes that some process is using XPC to request that the daemon perform a privileged operation. In that case, the daemon can use XPC facilities to ensure that only certain processes can make such a request. Doing this securely is a challenge. For specific API advice, see this post. WARNING This authorisation is based on the code signature of the process’s main executable. If the process loads plug-ins [1], the daemon can’t tell the difference between a request coming from the main executable and a request coming from a plug-in. [1] I’m talking in-process plug-ins here. Plug-ins that run in their own process, such as those managed by ExtensionKit, aren’t a concern. Choose an Approach There are (at least) seven different ways to run with root privileges on macOS: A setuid-root executable The sudo command-line tool The authopen command-line tool AppleScript’s do shell script command, passing true to the administrator privileges parameter The osascript command-line tool to run an AppleScript The AuthorizationExecuteWithPrivileges routine, deprecated since macOS 10.7 The SMJobSubmit routine targeting the kSMDomainSystemLaunchd domain, deprecated since macOS 10.10 The SMJobBless routine, deprecated since macOS 13 An installer package (.pkg) The SMAppService class, a much-needed enhancement to the Service Management framework introduced in macOS 13 Note There’s one additional approach: The privileged file operation feature in NSWorkspace. I’ve not listed it here because it doesn’t let you run arbitrary code with root privileges. It does, however, have one critical benefit: It’s supported in sandboxed apps. See this post for a bunch of hints and tips. To choose between them: Do not use a setuid-root executable. Ever. It’s that simple! Doing that is creating a security vulnerability looking for an attacker to exploit it. If you’re working interactively on the command line, use sudo, authopen, and osascript as you see fit. IMPORTANT These are not appropriate to use as API. Specifically, while it may be possible to invoke sudo programmatically under some circumstances, by the time you’re done you’ll have code that’s way more complicated than the alternatives. If you’re building an ad hoc solution to distribute to a limited audience, and you need one-shot privileges, use either AuthorizationExecuteWithPrivileges or AppleScript. While AuthorizationExecuteWithPrivileges still works, it’s been deprecated for many years. Do not use it in a widely distributed product. The AppleScript approach works great from AppleScript, but you can also use it from a shell script, using osascript, and from native code, using NSAppleScript. See the code snippet later in this post. If you need one-shot privileges in a widely distributed product, consider using SMJobSubmit. While this is officially deprecated, it’s used by the very popular Sparkle update framework, and thus it’s unlikely to break without warning. If you only need escalated privileges to install your product, consider using an installer package. That’s by far the easiest solution to this problem. Keep in mind that an installer package can install a launchd daemon and thereby gain ongoing privileges. If you need ongoing privileges but don’t want to ship an installer package, use SMAppService. If you need to deploy to older systems, use SMJobBless. For instructions on using SMAppService, see Updating helper executables from earlier versions of macOS. For a comprehensive example of how to use SMJobBless, see the EvenBetterAuthorizationSample sample code. For the simplest possible example, see the SMJobBless sample code. That has a Python script to help you debug your setup. Unfortunately this hasn’t been updated in a while; see this thread for more. Hints and Tips I’m sure I’ll think of more of these as time goes by but, for the moment, let’s start with the big one… Do not run GUI code as root. In some cases you can make this work but it’s not supported. Moreover, it’s not safe. The GUI frameworks are huge, and thus have a huge attack surface. If you run GUI code as root, you are opening yourself up to security vulnerabilities. Appendix: Running an AppleScript from Native Code Below is an example of running a shell script with elevated privileges using NSAppleScript. WARNING This is not meant to be the final word in privilege escalation. Before using this, work through the steps above to see if it’s the right option for you. Hint It probably isn’t! let url: URL = … file URL for the script to execute … let script = NSAppleScript(source: """ on open (filePath) if class of filePath is not text then error "Expected a single file path argument." end if set shellScript to "exec " & quoted form of filePath do shell script shellScript with administrator privileges end open """)! // Create the Apple event. let event = NSAppleEventDescriptor( eventClass: AEEventClass(kCoreEventClass), eventID: AEEventID(kAEOpenDocuments), targetDescriptor: nil, returnID: AEReturnID(kAutoGenerateReturnID), transactionID: AETransactionID(kAnyTransactionID) ) // Set up the direct object parameter to be a single string holding the // path to our script. let parameters = NSAppleEventDescriptor(string: url.path) event.setDescriptor(parameters, forKeyword: AEKeyword(keyDirectObject)) // The `as NSAppleEventDescriptor?` is required due to a bug in the // nullability annotation on this method’s result (r. 38702068). var error: NSDictionary? = nil guard let result = script.executeAppleEvent(event, error: &error) as NSAppleEventDescriptor? else { let code = (error?[NSAppleScript.errorNumber] as? Int) ?? 1 let message = (error?[NSAppleScript.errorMessage] as? String) ?? "-" throw NSError(domain: "ShellScript", code: code, userInfo: nil) } let scriptResult = result.stringValue ?? "" Revision History 2025-03-24 Added info about authopen and osascript. 2024-11-15 Added info about SMJobSubmit. Made other minor editorial changes. 2024-07-29 Added a reference to the NSWorkspace privileged file operation feature. Made other minor editorial changes. 2022-06-22 First posted.
0
0
4.3k
Mar ’25
Potential memory leaks in CLLocationUpdate.Updates
This is my first post here. Please guide me, if I need to provide more information to answer this post. I write a simple application, that monitors GPS position (location). I followed Apple documentation for LiveUpdates: https://developer.apple.com/documentation/corelocation/supporting-live-updates-in-swiftui-and-mac-catalyst-apps My app can monitor location in foreground, background or it can completely stop monitoring location. Background location, if needed, is switched on when application changes scenePhase to .background. But it is in the foreground, that memory leaks occur (according to Instruments/Leaks. Namely Leaks points to the instruction: let updates = CLLocationUpdate.liveUpdates() every time I start location and then stop it, by setting updatesStarted to false. Leaks claims there are 5x leaks there: Malloc 32 Bytes 1 0x6000002c1d00 32 Bytes libswiftDispatch.dylib OS_dispatch_queue.init(label:qos:attributes:autoreleaseFrequency:target:) CLDispatchSilo 1 0x60000269e700 96 Bytes CoreLocation 0x184525c64 Malloc 48 Bytes 1 0x600000c8f2d0 48 Bytes Foundation +[NSString stringWithUTF8String:] NSMutableSet 1 0x6000002c4240 32 Bytes LocationSupport 0x18baa65d4 dispatch_queue_t (serial) 1 0x600002c69c80 128 Bytes libswiftDispatch.dylib OS_dispatch_queue.init(label:qos:attributes:autoreleaseFrequency:target:) I tried [weak self] in Task, but it doesn't solve the leaks problem and causes other issues, so I dropped it. Anyway, Apple doesn't use it either. Just in case this is my function, which has been slightly changed comparing to Apple example, to suit my needs: func startLocationUpdates() { Task() { do { self.updatesStarted = true let updates = CLLocationUpdate.liveUpdates() for try await update in updates { // End location updates by breaking out of the loop. if !self.updatesStarted { self.location = nil self.mapLocation = nil self.track.removeAll() break } if let loc = update.location { let locationCoordinate = loc.coordinate let location2D = CLLocationCoordinate2D(latitude: locationCoordinate.latitude, longitude: locationCoordinate.longitude) self.location = location2D if self.isAnchor { if #available(iOS 18.0, *) { if !update.stationary { self.track.append(location2D) } } else { // Fallback on earlier versions if !update.isStationary { self.track.append(location2D) } } } } } } catch { // } return } } Can anyone help me locating these leaks?
4
0
729
Apr ’25