Processes & Concurrency

RSS for tag

Discover how the operating system manages multiple applications and processes simultaneously, ensuring smooth multitasking performance.

Concurrency Documentation

Posts under Processes & Concurrency subtopic

Post

Replies

Boosts

Views

Activity

Processes & Concurrency Resources
General: DevForums subtopic: App & System Services > Processes & Concurrency Processes & concurrency covers a number of different technologies: Background Tasks Resources Concurrency Resources — This includes Swift concurrency. Service Management Resources XPC Resources Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com"
0
0
268
Jul ’25
Background Tasks Resources
General: Forums subtopic: App & System Services > Processes & Concurrency Forums tag: Background Tasks Background Tasks framework documentation UIApplication background tasks documentation ProcessInfo expiring activity documentation Using background tasks documentation for watchOS Performing long-running tasks on iOS and iPadOS documentation WWDC 2020 Session 10063 Background execution demystified — This is critical resource. Watch it! [1] WWDC 2022 Session 10142 Efficiency awaits: Background tasks in SwiftUI WWDC 2025 Session 227 Finish tasks in the background — This contains an excellent summary of the expected use cases for each of the background task types. iOS Background Execution Limits forums post UIApplication Background Task Notes forums post Testing and Debugging Code Running in the Background forums post Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" [1] Sadly the video is currently not available from Apple. I’ve left the link in place just in case it comes back.
0
0
4k
Nov ’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.2k
Mar ’25
Service Management Resources
Service Management framework supports installing and uninstalling services, including Service Management login items, launchd agents, and launchd daemons. General: Forums subtopic: App & System Services > Processes & Concurrency Forums tag: Service Management Service Management framework documentation Daemons and Services Programming Guide archived documentation Technote 2083 Daemons and Agents — It hasn’t been updated in… well… decades, but it’s still remarkably relevant. EvenBetterAuthorizationSample sample code — This has been obviated by SMAppService. SMJobBless sample code — This has been obviated by SMAppService. Sandboxing with NSXPCConnection sample code WWDC 2022 Session 10096 What’s new in privacy introduces the new SMAppService facility, starting at 07˸07 BSD Privilege Escalation on macOS forums post Getting Started with SMAppService forums post Background items showing up with the wrong name forums post Related forums tags include: XPC, Apple’s preferred inter-process communication (IPC) mechanism Inter-process communication, for other IPC mechanisms Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com"
0
0
2.2k
Sep ’25
XPC Resources
XPC is the preferred inter-process communication (IPC) mechanism on Apple platforms. XPC has three APIs: The high-level NSXPCConnection API, for Objective-C and Swift The low-level Swift API, introduced with macOS 14 The low-level C API, which, while callable from all languages, works best with C-based languages General: Forums subtopic: App & System Services > Processes & Concurrency Forums tag: XPC Creating XPC services documentation NSXPCConnection class documentation Low-level API documentation XPC has extensive man pages — For the low-level API, start with the xpc man page; this is the original source for the XPC C API documentation and still contains titbits that you can’t find elsewhere. Also read the xpcservice.plist man page, which documents the property list format used by XPC services. Daemons and Services Programming Guide archived documentation WWDC 2012 Session 241 Cocoa Interprocess Communication with XPC — This is no longer available from the Apple Developer website )-: Technote 2083 Daemons and Agents — It hasn’t been updated in… well… decades, but it’s still remarkably relevant. TN3113 Testing and Debugging XPC Code With an Anonymous Listener XPC and App-to-App Communication forums post Validating Signature Of XPC Process forums post This forums post summarises the options for bidirectional communication This forums post explains the meaning of privileged flag Related tags include: Inter-process communication, for other IPC mechanisms Service Management, for installing and uninstalling Service Management login items, launchd agents, and launchd daemons Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com"
0
0
3.2k
Nov ’25
Concurrency Resources
Swift Concurrency Resources: Forums tags: Concurrency The Swift Programming Language > Concurrency documentation Migrating to Swift 6 documentation WWDC 2022 Session 110351 Eliminate data races using Swift Concurrency — This ‘sailing on the sea of concurrency’ talk is a great introduction to the fundamentals. WWDC 2021 Session 10134 Explore structured concurrency in Swift — The table that starts rolling out at around 25:45 is really helpful. Swift Async Algorithms package Swift Concurrency Proposal Index DevForum post Why is flow control important? forums post Dispatch Resources: Forums tags: Dispatch Dispatch documentation — Note that the Swift API and C API, while generally aligned, are different in many details. Make sure you select the right language at the top of the page. Dispatch man pages — While the standard Dispatch documentation is good, you can still find some great tidbits in the man pages. See Reading UNIX Manual Pages. Start by reading dispatch in section 3. WWDC 2015 Session 718 Building Responsive and Efficient Apps with GCD [1] WWDC 2017 Session 706 Modernizing Grand Central Dispatch Usage [1] Avoid Dispatch Global Concurrent Queues forums post Waiting for an Async Result in a Synchronous Function forums post Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" [1] These videos may or may not be available from Apple. If not, the URL should help you locate other sources of this info.
0
0
2k
3w
Are XPCSession and XPCListener incomplete(ly documented)?
I've been experimenting with the new low-level Swift API for XPC (XPCSession and XPCListener). The ability to send and receive Codable messages is an appealing alternative to making an @objc protocol in order to use NSXPCConnection from Swift — I can easily create an enum type whose cases map onto the protocol's methods. But our current XPC code validates the incoming connection using techniques similar to those described in Quinn's "Apple Recommended" response to the "Validating Signature Of XPC Process" thread. I haven't been able to determine how to do this with XPCListener; neither the documentation nor the Swift interface have yielded any insight. The Creating XPC Services article suggests using Xcode's XPC Service template, which contains this code: let listener = try XPCListener(service: serviceName) { request in request.accept { message in performCalculation(with: message) } } The apparent intent is to inspect the incoming request and decide whether to accept it or reject it, but there aren't any properties on IncomingSessionRequest that would allow the service to make that decision. Ideally, there would be a way to evaluate a code signing requirement, or at least obtain the audit token of the requesting process. (I did notice that a function xpc_listener_set_peer_code_signing_requirement was added in macOS 14.4, but it takes an xpc_listener_t argument and I can't tell whether XPCListener is bridged to that type.) Am I missing something obvious, or is there a gap in the functionality of XPCListener and IncomingSessionRequest?
3
0
980
Feb ’25
GUI + XPC Service App Architecture Performance
Let's image that someone wants to use a background service to keep track of FSEvents activity, at the file level (a firehose, some might say). I choose this example, to indicate the volume and rate of data transmission in question. I'm not creating a front-end for FSEvents data, but my background service may generate data at a similar pace. The service runs off of user defined document/s that specify the FSEvent background filtering to be applied. Those that match get stored into a database. But filters can match on almost all the data being emitted by FSEvents. The user decides to check on the service's activity and database writes by launching a GUI that sends requests to the background service using XPC. So the GUI can request historic data from a database, but also get a real-time view of what FS events the service is busy filtering. So it's a client-server approach, that's concerned with monitoring an event stream over XPC. I understand XPC is a request/response mechanism, and I might look into using a reverse connection here, but my main concern is one of performance. Is XPC capable of coping with such a high volume of data transmision? Could it cope with 1000s of rows of table data updates per second sent to a GUI frontend? I know there are streaming protocol options that involve a TCP connection, but I really want to stay away from opening sockets.
7
0
1.1k
1w
HELP: Privileged Helper With SMAppService
Hi! I've been developing iOS and macOS apps for many years, but now I am looking to dive into smth i have never touched before, namely privileged helpers, and i am struggling hard trying to find my footing. Here’s my use case: I have a CLI tool that requires elevated privileges. I want to create a menu bar app that can interact with this tool, but I’m struggling to find solid documentation or examples of how to accomplish this using SMAppService. I might just be missing something obvious. If anyone could point me toward relevant documentation, examples, articles, tutorials, or even a WWDC session that covers running privileged helpers with SMAppService, I would greatly appreciate it. Thanks in advance!
1
0
513
Feb ’25
Spawning electron app from deamon process
Hi all, Our company has an application that runs on several machines, this app is launched via a deamon that keeps it alive. One of the feature of this app, is to start a headless electron application to run some tests. When spawning this electron application with the new arm64 OS, we are getting this issue: Silent Test Agent Worker exited with code: 133 [ERROR] [75873:0205/135842.347044:ERROR:mach_port_rendezvous.cc(384)] bootstrap_look_up com.hivestreaming.silenttestagent.MachPortRendezvousServer.1: Permission denied (1100) [ERROR] [75873:0205/135842.347417:ERROR:shared_memory_switch.cc(237)] No rendezvous client, terminating process (parent died?) [ERROR] [75872:0205/135842.347634:ERROR:mach_port_rendezvous.cc(384)] bootstrap_look_up com.hivestreaming.silenttestagent.MachPortRendezvousServer.1: Permission denied (1100) [ERROR] [75872:0205/135842.347976:ERROR:shared_memory_switch.cc(237)] No rendezvous client, terminating process (parent died?) Both application (main app and electron one) are signed and notarized, but it seems that there is some other permission issue. If we run the electron application manually, all runs as expected. I added the crash report as attachment CrashReport.log
2
0
553
Feb ’25
Why is xpc_connection_set_peer_code_signing_requirement() closing the connection instead of returning XPC_ERROR_PEER_CODE_SIGNING_REQUIREMENT?
I'm using libxpc in a C server and Swift client. I set up a code-signing requirement in the server using xpc_connection_set_peer_code_signing_requirement(). However, when the client doesn't meet the requirement, the server just closes the connection, and I get XPC_ERROR_CONNECTION_INTERRUPTED on the client side instead of XPC_ERROR_PEER_CODE_SIGNING_REQUIREMENT, making debugging harder. What I want: To receive XPC_ERROR_PEER_CODE_SIGNING_REQUIREMENT on the client when code-signing fails, for better debugging. What I’ve tried: Using xpc_connection_set_peer_code_signing_requirement(), but it causes the connection to be dropped immediately. Questions: Why does the server close the connection without sending the expected error? How can I receive the correct error on the client side? Are there any other methods for debugging code-signing failures with libxpc? Thanks for any insights!
1
0
497
Feb ’25
Combine delay & switchToLatest publisher don't emit value sometimes
Hello, I recently implemented a conditional debounce publisher using Swift's Combine. If a string with a length less than 2 is passed, the event is sent downstream immediately without delay. If a string with a length of 2 or more is passed, the event is emitted downstream with a 0.2-second delay. While writing test logic related to this, I noticed a strange phenomenon: sometimes the publisher, which should emit events with a 0.2-second delay, does not emit an event. The test code below should have all indices from 1 to 100 in the array, but sometimes some indices are missing, causing the assertion to fail. Even after observing completion, cancel, and output events through handleEvents, I couldn't find any cause. Am I using Combine incorrectly, or is there a bug in Combine? I would appreciate it if you could let me know. import Foundation import Combine var cancellables: Set<AnyCancellable> = [] @MainActor func text(index: Int, completion: @escaping () -> Void) { let subject = PassthroughSubject<String, Never>() let textToSent = "textToSent" subject .map { text in if text.count >= 2 { return Just<String>(text) .delay(for: .seconds(0.2), scheduler: RunLoop.main) .eraseToAnyPublisher() } else { return Just<String>(text) .eraseToAnyPublisher() } } .switchToLatest() .sink { if $0.count >= 2 { completion() } }.store(in: &cancellables) for i in 0..<textToSent.count { let stringIndex = textToSent.index(textToSent.startIndex, offsetBy: i) let stringToSent = String(textToSent[textToSent.startIndex...stringIndex]) subject.send(stringToSent) } } var array = [Int]() for i in 1...100 { text(index: i) { array.append(i) } } DispatchQueue.main.asyncAfter(deadline: .now() + 5) { for i in 1...100 { assert(array.contains(i)) } } RunLoop.main.run(until: .now + 10)
0
0
422
Feb ’25
Possible to allow x code builds to run background processes for over 3 minutes
I have an app that I'm using for my own purposes and is not in the app store. I would like to run an http server in the background for more than the allotted 3 minutes to allow persistent communications with a connected Bluetooth device. The Bluetooth device would poll the service at intervals. Is this possible to do? This app does not need app store approval since it's only for personal use.
2
0
419
Feb ’25
My system daemons are not getting launched in MacOS 15x post reboot
When I install my application, it installs fine and everything works alongwith all the system level daemons but when I reboot the system, none of my daemons are getting launched and this happens only on MacOS 15x, on older version it is working fine. In the system logs, I see that my daemons have been detected as legacy daemons by backgroundtaskmanagementd with Disposition [enabled, allowed, visible, notified] 2025-01-13 21:17:04.919128+0530 0x60e Default 0x0 205 0 backgroundtaskmanagementd: [com.apple.backgroundtaskmanagement:main] Type: legacy daemon (0x10010) 2025-01-13 21:17:04.919128+0530 0x60e Default 0x0 205 0 backgroundtaskmanagementd: [com.apple.backgroundtaskmanagement:main] Flags: [ legacy ] (0x1) 2025-01-13 21:17:04.919129+0530 0x60e Default 0x0 205 0 backgroundtaskmanagementd: [com.apple.backgroundtaskmanagement:main] Disposition: [enabled, allowed, visible, notified] (0xb) But later, it backgroundtaskmanagementd decides to disallow it. 2025-01-13 21:17:05.013202+0530 0x32d Default 0x4d6 89 0 smd: (BackgroundTaskManagement) [com.apple.backgroundtaskmanagement:main] getEffectiveDisposition: disposition=[enabled, disallowed, visible, notified], have LWCR=true 2025-01-13 21:17:05.013214+0530 0x32d Error 0x0 89 0 smd: [com.apple.xpc.smd:all] Legacy job is not allowed to launch: &lt;private&gt; status: 2 Is there anything changed in latest Mac OS which is causing this issue? Also what does this status 2 means. Can someone please help with this error? The plist has is true
3
0
370
Feb ’25
SSMenuAgent consuming lots of CPU
My load average on a largely idle system is around 22, going up to 70 or so periodically; SSMenuAgent seems to be consuming lots of CPU (and, looking at spindump, it certainly seems busy), but... it's not happening on any other system whose screens I am observing. (Er, I know about load average limitations, the process is also consuming 70-98% CPU according to both top and Activity Monitor.) Since this machine (although idle) has our network extension, I'm trying to figure out if this is due to that, or of this is generally expected. Anyone?
2
0
475
May ’25
Proper initialization - views, dependencies, laoder and viewcontroller
So i am pretty new to Xcode, but i have been using Python and other language for some while. But I am quite new to the game of view and view control. So it may be that i have over complicated this a bit - and it may be that I have some wrong understanding of the dependencies and appcontroller (that i thought would be a good idea). So here we have a main file we call it app.swift, we have a startupmanager.swift, a appcoordinator and a dependeciescontainer. But it may be that this is either a overkill - or that I am doing it wrong. So my thought was that i had a dependeciecontainer, a appcoordinator for the views and a startupmanager that controll the initialized fetching. I have controlled the memory when i run it - checking if it is higher, lower eg - but it was first when i did my 2 days profile i saw a lot of new errors, like this: Fikser(7291,0x204e516c0) malloc: xzm: failed to initialize deferred reclamation buffer (46). and i also get macro errors, probably from the @Query in my feedview. So my thought was that a depencecie manager and a startupmanager was a good idea together with a app coordinator. But maybe I am wrong - maybe this is not a good idea? Or maybe I am doing some things twice? I have added a lot of prints and debugs for checking. But it seems that it starts off to heavy? import SwiftUI import Combine @MainActor class AppCoordinator: ObservableObject { @Published var isLoggedIn: Bool = false private var authManager: AuthenticationManager = .shared private var cancellables = Set<AnyCancellable>() private let startupManager: StartupManager private let container: DependencyContainer @Published var path = NavigationPath() enum Screen: Hashable, Identifiable { case profile case activeJobs case offers case message var id: Self { self } } init(container: DependencyContainer) { self.container = container self.startupManager = container.makeStartupManager() setupObserving() startupManager.start() print("AppCoordinator initialized!") } private func setupObserving() { authManager.$isAuthenticated .receive(on: RunLoop.main) .sink { [weak self] isAuthenticated in self?.isLoggedIn = isAuthenticated } .store(in: &cancellables) } func userDidLogout() { authManager.logout() path.removeLast(path.count) } func showProfile() { path.append(Screen.profile) } func showActiveJobs() { path.append(Screen.activeJobs) } func showOffers() { path.append(Screen.offers) } func showMessage() { path.append(Screen.message) } @ViewBuilder func viewForDestination(_ destination: Screen) -> some View { switch destination { case .profile: ProfileView() case .activeJobs: ActiveJobsView() case .offers: OffersView() case .message: ChatView() } } @ViewBuilder func viewForJob(_ job: Job) -> some View { PostDetailView( job: job, jobUserDetailsRepository: container.makeJobUserDetailsRepository() ) } @ViewBuilder func viewForProfileSubview(_ destination: ProfileView.ProfileSubviews) -> some View { switch destination{ case .personalSettings: PersonalSettingView() case .historicData: HistoricDataView() case .transactions: TransactionView() case .helpCenter: HelpcenterView() case .helpContract: HelpContractView() } } enum HomeBarDestinations: Hashable, Identifiable { case postJob case jobPosting var id: Self { self } } @ViewBuilder func viewForHomeBar(_ destination: HomeBarView.HomeBarDestinations) -> some View { switch destination { case .postJob: PostJobView() } } } import Apollo import FikserAPI import SwiftData class DependencyContainer { static var shared: DependencyContainer! private let modelContainer: ModelContainer static func initialize(with modelContainer: ModelContainer) { shared = DependencyContainer(modelContainer: modelContainer) } private init(modelContainer: ModelContainer) { self.modelContainer = modelContainer print("DependencyContainer being initialized at ") } @MainActor private lazy var userData: UserData = { return UserData(apollo: Network.shared.apollo) }() @MainActor private lazy var userDetailsRepository: UserDetailsRepository = { return UserDetailsRepository(userData: makeUserData()) }() @MainActor private lazy var jobData: JobData = { return JobData(apollo: Network.shared.apollo) }() @MainActor private lazy var jobRepository: JobRepository = { return JobRepository(jobData: makeJobData(), modelContainer: modelContainer) }() @MainActor func makeUserData() -> UserData { return userData } @MainActor func makeUserDetailsRepository() -> UserDetailsRepository { return userDetailsRepository } @MainActor func makeStartupManager() -> StartupManager { return StartupManager( userDetailsRepository: makeUserDetailsRepository(), jobRepository: makeJobRepository(), authManager: AuthenticationManager.shared, lastUpdateRepository: makeLastUpdateRepository() ) } @MainActor func makeJobData() -> JobData { return jobData } @MainActor func makeJobRepository() -> any JobRepositoryProtocol { return jobRepository } @MainActor private lazy var jobUserData: JobUserData = { return JobUserData(apollo: Network.shared.apollo) }() @MainActor private lazy var jobUserDetailsRepository: JobUserDetailsRepository = { return JobUserDetailsRepository(jobUserData: makeJobUserData()) }() @MainActor func makeJobUserData() -> JobUserData { return jobUserData } @MainActor func makeJobUserDetailsRepository() -> JobUserDetailsRepository { return jobUserDetailsRepository } @MainActor private lazy var lastUpdateData: LastUpdateData = { return LastUpdateData(apollo: Network.shared.apollo) }() @MainActor private lazy var lastUpdateRepository: LastUpdateRepository = { return LastUpdateRepository(lastUpdateData: makeLastUpdateData()) }() @MainActor func makeLastUpdateData() -> LastUpdateData { return lastUpdateData } @MainActor func makeLastUpdateRepository() -> LastUpdateRepository { return lastUpdateRepository } }```
1
0
355
Feb ’25
Can we create a bundled non-interactive macOS application which uses CFRunLoop only(instead of using NSApplicationMain to run NSRunLoop)?
I am developing a macOS non-interactive macOS application which does not show any ui. i want to block main thread and do all the work on worker thread . Once done with work in worker thread, want to unblock main thread by exiting event loop to terminate application. Because i dont want to show any UI or use any Foundation/Cocoa functionality, i am thinking of using CFRunLoop to block main thread from exiting until i finish my work in worker thread. When i tried this in a project, I am able to finish work in worker thread after block main thread using CFRunLoop. I also want this application to be a bundled application, which can be launched by double clicking on application bundle . But when i tried it in my xcode project by launching it using double clicking on application bundle, application keeps on toggling/bouncing in the dock menu with a status "Not responding". Although i am able to complete my work in worker thread. import Foundation let runLoop = CFRunLoopGetCurrent() func workerTask() { DispatchQueue.global().async { print("do its work") sleep(5) // do some work print("calling exit event loop") CFRunLoopStop(runLoop) print ("unblocking main thread") } } workerTask () // blocking main thread print ("blocked main thread") CFRunLoopRun() print ("exit") Why i am getting this application bouncing in doc menu behavior ? I tried by using NSApplicationMain instead of CFRunLoop in my project, in that case i didnt get this behavior . Does NSApplicationMain does some extra work before starting NSRunLoop which i am not doing while using CFRunLoop, which is showing this toggling/Bouncing application icon in Dock menu ? or Is this bouncing app icon issue is related to run loop i am using which is CFRunLoop ? Note : If i dont use a bundled application and use a commandline application then i am able to do all steps in worker thread and exit main thread as i wanted after finishing my work . But i need to do all this in application which can be launched using double clicking (bundled applcation). If not by using CFRunLoop, then how can i achive this ? - Create a application which shows no UI and do all work in worker thread while main thread is blocked. Once work is done unblock main thread and exit. And user should be able to launch application using double click the application icon.
3
0
433
Mar ’25
Background Task Execution for FDA Class B Medical App Using BLE
Hello Apple Developer Community, I am developing a medical app that is classified as Class B according to FDA regulations. The app connects to a medical device using Bluetooth Low Energy (BLE) to collect critical medical data such as ECG readings. To ensure accurate data collection and maintain the quality of the medical readings, the app needs to wake up every five minutes in the background and perform tasks for approximately 30 seconds. I understand that iOS has strict limitations on background execution to preserve battery and system performance. However, due to the medical nature of the app and the need for periodic data collection, I am seeking guidance on the following: If I can provide documentation that the app is associated with an FDA-approved Class B medical device, would Apple allow more lenient background task execution policies? Are there specific APIs, such as BackgroundTasks, CoreBluetooth, or other recommended strategies, that could help me achieve this behavior reliably? Is there a process to apply for an exception or special consideration for medical apps that require periodic background activity? Any insights or recommendations would be greatly appreciated. Thank you!
2
0
349
Mar ’25
Push-to-Start Live Activity Background Task Issue After App Termination
Desired Behavior I want the app to be able to handle multiple Push-to-Start notifications even when it is completely terminated. Each Live Activity should: Be successfully displayed upon receiving a Push-to-Start notification. Trigger background tasks to send its update token to the server, regardless of the time interval between notifications. Problem I am facing an issue with iOS Live Activities when using Push-to-Start notifications to trigger Live Activities in an app that has been completely terminated. Here’s the detailed scenario: When the app is completely terminated and I send the first Push-to-Start notification: The Live Activity is successfully displayed. didFinishLaunchingWithOptions` is triggered, and background tasks execute correctly, including sending the update token to the server. When I send consecutive Push-to-Start notifications in quick succession (e.g., within a few seconds or minutes): Both notifications successfully display their respective Live Activities. Background tasks are executed correctly for both notifications. However, when there is a longer interval (e.g., 10 minutes) between two Push-to-Start notifications: The first notification works perfectly—it displays the Live Activity, triggers didFinishLaunchingWithOptions, and executes background tasks. The second notification successfully displays the Live Activity but fails to execute any background tasks, such as sending the update token to the server. My HypothesisI suspect that iOS might impose a restriction where background runtime for Push-to-Start notifications can only be granted once within a certain time frame after the app has been terminated. Any insights into why this issue might be occurring or how to ensure consistent background task execution for multiple Push-to-Start notifications would be greatly appreciated!
2
0
433
Mar ’25
How to check for cancellation of background task
When using the old withTaskCancellationHandler(operation:onCancel:isolation:) to run background tasks, you were notified that the background task gets cancelled via the handler being called. SwiftUI provides the backgroundTask(_:action:) modifier which looks quite handy. However how can I check if the background task will be cancelled to avoid being terminated by the system? I have tried to check that via Task.isCancelled but this always returns false no matter what. Is this not possible when using the modifier in which case I should file a bug report? Thanks for your help
0
0
280
Mar ’25
How to safely maximize concurrent UI rendering
I'm using Swift 6 and tasks to concurrently process multiple PDF files for rendering, and it's working well. But currently I'm manually limiting the number of simultaneous tasks to 2 out of fear that the system might run many tasks concurrently without having enough RAM to do the PDF processing. Testing on a variety of devices, I've tried increasing the task limit and haven't seen any crashes, but I'm quite concerned about the possibility. Any given device might be using a lot of RAM at any moment, and any given PDF might strain resources more than the average PDF. Is there a recommended technique for handling this kind of scenario? Should I not worry about it and just go ahead and start a high number of tasks, trusting that the system won't run too many concurrently and therefore won't run out of RAM?
2
0
275
Mar ’25