Background Tasks

RSS for tag

Request the system to launch your app in the background to run tasks using Background Tasks.

Posts under Background Tasks tag

131 Posts
Sort by:

Post

Replies

Boosts

Views

Activity

Background Task in iOS App
Hi, I am working on a React Native app and i want to have a latitude longitude of a user in every 15 minutes and want to do something like an api call with it. I want to keep continuing this no matter my app is in background, foreground or in killed state. Is there any way or method through which i can achieve this natively or using React Native?
1
0
208
Oct ’24
Urgent Issue with SoundAnalysis in iOS 18 - Critical Background Permissions Error
We are experiencing a major issue with the native .version1 of the SoundAnalysis framework in iOS 18, which has led to all our user not having recordings. Our core feature relies heavily on sound analysis in the background, and it previously worked flawlessly in prior iOS versions. However, in the new iOS 18, sound analysis stops working in the background, triggering a critical warning. Details of the issue: We are using SoundAnalysis to analyze background sounds and have enabled the necessary background permissions. We are using the latest XCode A warning now appears, and sound analysis fails in the background. Below is the warning message we are encountering: Warning Message: Execution of the command buffer was aborted due to an error during execution. Insufficient Permission (to submit GPU work from background) [Espresso::handle_ex_plan] exception=Espresso exception: "Generic error": Insufficient Permission (to submit GPU work from background) (00000006:kIOGPUCommandBufferCallbackErrorBackgroundExecutionNotPermitted); code=7 status=-1 Unable to compute the prediction using a neural network model. It can be an invalid input data or broken/unsupported model (error code: -1). CoreML prediction failed with Error Domain=com.apple.CoreML Code=0 "Failed to evaluate model 0 in pipeline" UserInfo={NSLocalizedDescription=Failed to evaluate model 0 in pipeline, NSUnderlyingError=0x30330e910 {Error Domain=com.apple.CoreML Code=0 "Failed to evaluate model 1 in pipeline" UserInfo={NSLocalizedDescription=Failed to evaluate model 1 in pipeline, NSUnderlyingError=0x303307840 {Error Domain=com.apple.CoreML Code=0 "Unable to compute the prediction using a neural network model. It can be an invalid input data or broken/unsupported model (error code: -1)." UserInfo={NSLocalizedDescription=Unable to compute the prediction using a neural network model. It can be an invalid input data or broken/unsupported model (error code: -1).}}}}} We urgently need guidance or a fix for this, as our application’s main functionality is severely impacted by this background permission error. Please let us know the next steps or if this is a known issue with iOS 18.
10
10
843
5d
Ensuring Successful Video Uploads in iOS Background Mode(terminated state)
If we start uploading a video file from the foreground and then switch to another app or press the home button, we can enable background processing by selecting the 'Background processing' option in the app's background modes. We utilize URLSession to handle the upload. I have a few questions regarding this process: If the user manually kills the app, will the upload continue in the background? For files around 100 MB, if the user locks the phone while the upload is in progress (and the app is in the background but not terminated), will the upload still be successful? Does Apple provide any additional APIs that would facilitate successful file uploads even if the user terminates the app? I would appreciate any solutions or insights you can provide. Thank you!
3
0
250
Oct ’24
Background modes in Flutter project (Android Studio)
Hello, I'm developing an iOS app in Flutter, but I'm having trouble enabling Background Mode. I added the following configuration to Info.plist and Runner.entitlements: <key>UIBackgroundModes</key> <array> <string>processing</string> <string>fetch</string> <string>location</string> </array> However, the Background Mode option doesn't appear in my App ID to be enabled. And the build fails with the message: Provisioning profile "Ready Response ios_app_store ..." doesn't include the UIBackgroundModes entitlement. How can I enable this option in my App ID? Note: I'm using Android Studio and publishing through Codemagic.
2
0
473
Sep ’24
BGTask expiry is never called for the requested BGTask.
We have a push-to-talk client, Part of Push APNS, app never received the BG task expiry. The app is suspended. Received Push-To-Talk APNS Here requested a BGTask and it got successfully registered Since it is a PTT call path, it ended immediately(via code) due to internal restrictions Ex: DND mode for client specific. The client allowed BG time more than 30 seconds and looks client has been suspended but Never received a BG task expiration handler from OS In sys diagnose logs confirmed, BGTask registered successfully 2024-09-03 16:18:47.331890 +0530 default AT&T EPTT : Created background task . But never got fired expiration handler. Feedback - FB15145380
3
0
212
Oct ’24
Trouble with getting a background refresh task working
I am able to setup and schedule a background refresh task as well as manually trigger it via Xcode and the simulator tied to my iPhone 11 Pro test phone using the e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWithIdentifier: However, it won't execute on the app on it's own. And yes, the pinfo.list entries are correct and match! I know the scheduler is not exact on timing but it's just not executing on its own. Since I can trigger manually it I'm pretty sure the code is good but I must be missing something. I created an observable object for this code and the relevant parts look like this: class BackgroundTaskHandler: ObservableObject { static let shared = BackgroundTaskHandler() var taskState: BackgroundTaskState = .idle let backgroundAppRefreshTask = "com.opexnetworks.templateapp.shell.V1.appRefreshTask" func registerBackgroundTask() { BGTaskScheduler.shared.register(forTaskWithIdentifier: backgroundAppRefreshTask, using: nil) { task in self.handleAppRefresh(task: task as! BGAppRefreshTask) } self.updateTaskState(to: .idle, logMessage: "✅ Background app refresh task '\(backgroundAppRefreshTask)' registered.") BGTaskScheduler.shared.register(forTaskWithIdentifier: backgroundTaskIdentifier, using: nil) { task in self.handleProcessingTask(task: task as! BGProcessingTask) } self.updateTaskState(to: .idle, logMessage: "✅ Background task identifier '\(backgroundTaskIdentifier)' registered.") } // Handle the app refresh task private func handleAppRefresh(task: BGAppRefreshTask) { self.updateTaskState(to: .running, logMessage: "🔥 app refresh task is now running.") PostNotification.sendNotification(title: "Task Running", body: "App refresh task is now running.") let queue = OperationQueue() queue.maxConcurrentOperationCount = 1 let operation = BlockOperation { self.doSomeShortTaskWork() } task.expirationHandler = { self.updateTaskState(to: .expired, logMessage: "💀 App refresh task expired before completion.") PostNotification.sendNotification(title: "Task Expired", body: "App refresh task expired before completion \(self.formattedDate(Date())).") operation.cancel() } operation.completionBlock = { if !operation.isCancelled { self.taskState = .completed } task.setTaskCompleted(success: !operation.isCancelled) let completionDate = Date() UserDefaults.standard.set(completionDate, forKey: "LastBackgroundTaskCompletionDate") self.updateTaskState(to: .completed, logMessage: "🏁 App refresh task completed at \(self.formattedDate(completionDate)).") PostNotification.sendNotification(title: "Task Completed", body: "App refresh task completed at: \(completionDate)") self.scheduleAppRefresh() // Schedule the next one } queue.addOperation(operation) } func scheduleAppRefresh() { // Check for any pending task requests BGTaskScheduler.shared.getPendingTaskRequests { taskRequests in let refreshTaskIdentifier = self.backgroundAppRefreshTask let refreshTaskAlreadyScheduled = taskRequests.contains { $0.identifier == refreshTaskIdentifier } if refreshTaskAlreadyScheduled { self.updateTaskState(to: .pending, logMessage: "⚠️ App refresh task '\(refreshTaskIdentifier)' is already pending.") // Iterate over pending requests to get details for taskRequest in taskRequests where taskRequest.identifier == refreshTaskIdentifier { let earliestBeginDate: String if let date = taskRequest.earliestBeginDate { earliestBeginDate = self.formattedDate(date) } else { earliestBeginDate = "never" } self.updateTaskState(to: .pending, logMessage: "⚠️ Pending Task: \(taskRequest.identifier), Earliest Begin Date: \(earliestBeginDate)") } // Optionally, show a warning message to the user in your app PostNotification.sendNotification(title: "Pending Tasks", body: "App refresh task is already pending. Task scheduling cancelled.") return } else { // No pending app refresh task, so schedule a new one let request = BGAppRefreshTaskRequest(identifier: refreshTaskIdentifier) request.earliestBeginDate = Date(timeIntervalSinceNow: 15 * 60) // Earliest in 15 minutes do { try BGTaskScheduler.shared.submit(request) self.taskState = .scheduled self.updateTaskState(to: .scheduled, logMessage: "✅ App refresh task '\(refreshTaskIdentifier)' successfully scheduled for about 15 minutes later.") PostNotification.sendNotification(title: "Task Scheduled", body: "App refresh task has been scheduled to run in about 15 minutes.") } catch { print("Could not schedule app refresh: \(error)") self.taskState = .failed self.updateTaskState(to: .failed, logMessage: "❌ Failed to schedule app refresh task.") } } } } // Short task work simulation private func doSomeShortTaskWork() { print("Doing some short task work...") // Simulate a short background task (e.g., fetching new data from server) sleep(5) print("Short task work completed.") } In my AppDelegate I trigger the registerBackground task in the didFinishLaunchingWithOptions here: BackgroundTaskHandler.shared.registerBackgroundTask() And I scheduled it here in the launch view under a task when visible: .task { BackgroundTaskHandler.shared.scheduleAppRefresh() } I've also tried the last in the AppDelegate after registering. either way the task schedules but never executes.
4
0
326
Sep ’24
didFinishLaunchingWithOptions is called in background
Hello, Based on the application runtime logs, after switching to the background (possibly due to the user forcibly closing the application), the app sometimes restarts immediately or after several seconds and executes the didFinishLaunchingWithOptions method (at this point, UIApplicationState == UIApplicationStateBackground). The application itself has not requested background permissions, as shown in the attachment. I am puzzled about what could cause the application to restart in the background several seconds after being forcibly closed. Could you please help clarify the possible reasons for this behavior? (We have considered if it might be due to prewarming, but there is no prewarm flag during the startup.) Thank you.
3
0
287
Sep ’24
Handle background task (BGProcessingTask) in terminated app state
I am having an issue with scheduling daily background task (eg: nightly) when app is in terminated app state (user forcefully terminated the app from app switcher). If the app is in suspended state, I am able to schedule a daily background task. But is there a way to wake up the app nightly and register a BGTask when user forcefully terminates the app.
1
0
286
Sep ’24
AVSpeechSynthesizer don't speak on didReceive Notification Service Extension on Device(Background Mode)
My Code private let synthesizer = AVSpeechSynthesizer() override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { self.contentHandler = contentHandler bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent) do { try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playback) let utterance = AVSpeechUtterance(string: "Hello Sim") utterance.voice = AVSpeechSynthesisVoice(language: "th_TH") utterance.rate = 1.0 utterance.pitchMultiplier = 1.0 utterance.volume = 1.0 utterance.preUtteranceDelay = 0 self.synthesizer.usesApplicationAudioSession = false self.synthesizer.speak(utterance) } catch { print(error.localizedDescription) } if let bestAttemptContent = self.bestAttemptContent { contentHandler(bestAttemptContent) } } Info.plist enable UIBackgroundModes audio fetch processing remote-notification payloadNotification { "aps":{ "alert":{ "title":"title" "subtitle":"subtitle" "body":"body" } "mutable-content":1 "content-available":1 "sound":"tester.caf" } } This code can play in simulator but can't play in real device
1
0
236
Sep ’24
How to allow my app to receive BLE data from sensor while running in background?
I have a sensor that communicates via BLE periodically. The intention is for it to be a set it and forget it kind of thing. The user will check the app periodically but won't be doing so frequently. I need the app to be able to still receive the BLE data from the sensor even if it's running in the background so that when the user does check the app, they can see everything that's been happening. I've read a lot from 2020 - 2021 where it seems many developers are struggling with the same issue. Is there a supported way to do this now? How to have my app run in the background and still be able to receive BLE data?
1
0
218
Sep ’24
watchOS SwiftUI background task not working
I'm attempting to create a standalone watchOS app that fetches the prayer timings of my local mosque in JSON format via an API call. I want the app to fetch the prayer timings in the background, but only once per day, at the start of the day (when prayer timings change, i.e., midnight). I'm trying to implement this using SwiftUI's backgroundTask modifier as explained in the docs and in this WWDC22 video. I made sure to enable the Background Modes capability, and this is what my app's Info.plist looks like: However, I've been unable to get it to work. I would appreciate any assistance I can get and feedback for improvements I can make, even with the Info.plist if anything is incorrect about it. Thank you! This is what I have so far: // PrayerTimesCompanionApp.swift // PrayerTimesCompanion Watch App import SwiftUI import WatchKit @main struct PrayerTimesCompanion_Watch_AppApp: App { var body: some Scene { WindowGroup { ContentView() } .backgroundTask(.appRefresh("TIMINGS_REFRESH")) { print("Found matching task") scheduleNextBackgroundRefresh() } } } // Schedule the next background refresh func scheduleNextBackgroundRefresh() { let today = Calendar.current.startOfDay(for: .now) if let tomorrow = Calendar.current.date(byAdding: .day, value: 1, to: today) { WKApplication.shared().scheduleBackgroundRefresh(withPreferredDate: tomorrow, userInfo: "TIMINGS_REFRESH" as NSSecureCoding & NSObjectProtocol) { error in if error != nil { fatalError("*** An error occurred while scheduling the background refresh task. ***") } print("*** Scheduled! ***") } } } // ContentView.swift // PrayerTimesCompanion Watch App import SwiftUI struct ContentView: View { @StateObject var prayerTimeModel = PrayerTimesModel() var body: some View { List { VStack { VStack(spacing: 15) { // Table Header HStack { Text("Prayer") .bold() .frame(maxWidth: .infinity, alignment: .leading) // Align to the left Text("Iqamah") .bold() .frame(maxWidth: .infinity, alignment: .trailing) // Align to the right } .padding() // Table Rows (5 prayers) ForEach(prayerTimeModel.prayerTimes.data.iqamah, id: \.date) { iqamah in rowView(prayer: "Fajr", time: iqamah.fajr) rowView(prayer: "Zuhr", time: iqamah.zuhr) rowView(prayer: "Asr", time: iqamah.asr) rowView(prayer: "Maghrib", time: iqamah.maghrib) rowView(prayer: "Isha", time: iqamah.isha) } } .padding() } .padding() .onAppear { prayerTimeModel.fetch() } } .edgesIgnoringSafeArea(.top) } func rowView(prayer: String, time: String) -> some View { HStack { Text(prayer) .frame(maxWidth: .infinity, alignment: .leading) Text(time) .frame(maxWidth: .infinity, alignment: .trailing) } } } #Preview { ContentView() } // PrayerTimesModel.swift // PrayerTimesCompanion Watch App import Foundation import SwiftUI // Main struct for the response struct PrayerTimesResponse: Codable { let status: String var data: SalahData let message: [String] } // Struct for the data section struct SalahData: Codable { var salah: [Salah] var iqamah: [Iqamah] } // Struct for Salah times struct Salah: Codable { let date: String let hijriDate: String let hijriMonth: String let day: String var fajr: String let sunrise: String var zuhr: String var asr: String var maghrib: String var isha: String enum CodingKeys: String, CodingKey { case date, hijriDate = "hijri_date", hijriMonth = "hijri_month", day, fajr, sunrise, zuhr, asr, maghrib, isha } } // Struct for Iqamah times struct Iqamah: Codable { let date: String var fajr: String var zuhr: String var asr: String var maghrib: String var isha: String let jummah1: String let jummah2: String enum CodingKeys: String, CodingKey { case date, fajr, zuhr, asr, maghrib, isha, jummah1 = "jummah1", jummah2 = "jummah2" } } class PrayerTimesModel: ObservableObject { @Published var prayerTimes: PrayerTimesResponse = PrayerTimesResponse( status: "Unknown", data: SalahData( salah: [Salah(date: "", hijriDate: "", hijriMonth: "", day: "", fajr: "", sunrise: "", zuhr: "", asr: "", maghrib: "", isha: "")], iqamah: [Iqamah(date: "", fajr: "", zuhr: "", asr: "", maghrib: "", isha: "", jummah1: "", jummah2: "")]), message: ["No data available"] ) // fetches the local mosque's prayer timings via an API call func fetch() { guard let url = URL(string: "https://masjidal.com/api/v1/time/range?masjid_id=3OA87VLp") else { return } let task = URLSession.shared.dataTask(with: url) { [self] data, _, error in guard let data = data, error == nil else { return } // Convert to JSON do { var prayerTimes = try JSONDecoder().decode(PrayerTimesResponse.self, from: data) DispatchQueue.main.async { self.prayerTimes = prayerTimes } } catch { print(error) } } task.resume() } }
0
0
352
Sep ’24
BLE Scanning stops when phone is in locked mode
I have a solution where my application should scan the Bluetooth enabled Beacon devices in the foreground, background, locked mode for the iphone. Currently we have built the project, which is working fine in foreground mode. We have tried exploring multiple options to enable the feature in background and locked mode. As of now, we have come up with the solution which implements Picture in Picture mode in the application and once the application is minimized. The PIP window opens which solves our problem. But the problem stays with locked mode. The scanning is not working in locked mode. So can we know how the bluetooth scanning will work in background and locked mode. Please also mention the alternative solutions to the problem statement if background and locked mode scanning is not possible. I have attached the project source code for reference. This project is being built for Google, so it is bit urgent. Can I expect a quick response to this query?
4
0
417
Sep ’24
Regular step count fetch and upload to API
Hello all, I am quite new to iOS and Swift, and before venturing further, I feel it's better to ask for advice. I have build a Type I diabetes simulator running as a NodeJS application on a server. The clients authenticate via a browser using Fitbit/Google oauth2, set up a virtual patient, then take care of the patient 24/7. The app imports the users steps and heartrate, as these influence the blood sugar variations. (https://cgmsim.com) I designed a companion app with Expo, adding high/log blood glucose alerts with push notifications. If the user doesn't have a Fitbit tracker or doesn't use Google Fit, I'd like to send their HealthKit step counts to the backend. (Using sensor data directly in Android). It works using Expo's Background Fetch and TaskManager, but the uploads from the iOS device are very irregular. I set up silent push notifications from the backend to wake up the app in the background and trigger the step count upload. It works, but it is not reliable enough. I now wrote my first local native module for iOS, where a HKObserverQuery listening for new step events, making the upload and sending the count to the JS for rendering. I used enableBackgroundDelivery and BackgroundTask for uploading the results. All the entitlements and Info.plist entries should be ok. Still my app works well only in the foreground, and not upload at all happens when in the background. As we all do, I asked Claude, and it assured me th app should work. I have doubts though, as I noticed how strict iOS is about executing background tasks. So... should I even expect this to work ?
1
0
429
Sep ’24
Not getting User's location in Background Mode
We developed a app in which the I need the app to update the User's location even in background( even after terminating from the recent UI ), Currently I am receiving the location updates when the user has kept the app in open and if minimised, But I want that it should update the location even when it is removed from recent app (minimised UI)(after terminating the app) Is it possible to do so.???
3
0
488
2w
Crash on URLSession in background task
Hi, I try to implement the BackgroundTask handling from this WWDC2022 video: https://developer.apple.com/videos/play/wwdc2022/10142 But it always crashes with this error: *** Terminating app due to uncaught exception 'NSGenericException', reason: 'Completion handler blocks are not supported in background sessions. Use a delegate instead.' So, is the video updated or is this a bug?
3
0
328
Sep ’24
BGTaskScheduler with
I’m trying to use BGProcessingTaskRequest to fetch step data in the background and send it. However, when I combine BGProcessingTaskRequest, HKObserverQuery, and healthStore.enableBackgroundDelivery, the results sometimes return zero. When I don’t schedule the BGProcessingTaskRequest, the data retrieved using HKObserverQuery and HKSampleQueryDescriptor is correct. // Register Smart Walking Sync Task func registerSmartWalkingSync() { #if !targetEnvironment(simulator) BGTaskScheduler.shared.register(forTaskWithIdentifier: BGTaskIdentifier.smartwalking.rawValue, using: nil) { task in guard let task = task as? BGProcessingTask else { return } self.handleSmartWalkingSync(task: task) } #endif } func scheduleSmartWalkingSync(in seconds: TimeInterval? = nil, at date: Date? = nil) { let newRequest = BGProcessingTaskRequest(identifier: BGTaskIdentifier.smartwalking.rawValue) newRequest.requiresNetworkConnectivity = true newRequest.requiresExternalPower = false if let seconds = seconds { newRequest.earliestBeginDate = Date().addingTimeInterval(seconds) } else if let date = date { newRequest.earliestBeginDate = date } do { try BGTaskScheduler.shared.submit(newRequest) debugPrint("✅ [BGTasksManager] scheduled for Smart Walking Sync") } catch { FirebaseConnection.shared.recordException(error) debugPrint("❌ [BGTasksManager] error: \(error)") } } // Handle Smart Walking Sync Task func handleSmartWalkingSync(task: BGProcessingTask) { debugPrint("🔄 [BGTasksManager] sync \(task.identifier) sync started") scheduleSmartWalkingSync(in: SYNC_SMARTWALKING_TIME_INTERVAL) let queue = OperationQueue() let operation = HealthActivitiesOperation() operation.completionBlock = { Task { do { try await operation.sync() task.setTaskCompleted(success: !operation.isCancelled) debugPrint("✅ [BGTasksManager] sync \(task.identifier) completed successfully") } catch { FirebaseConnection.shared.recordException(error) task.setTaskCompleted(success: false) debugPrint("❌ [BGTasksManager] sync \(task.identifier) error: \(error)") } } } task.expirationHandler = { operation.cancel() } queue.addOperation(operation) } // MARK: - HealthKit Background Delivery internal func enableBackgroundDeliveryForAllTypes() async throws { for type in allTypes.filter({ type in type != HKQuantityType(.heartRate) }) { try await healthStore.enableBackgroundDelivery(for: type, frequency: .daily) } debugPrint("✅ [HealthKitManager] Enable Background Delivery") } internal func observeHealthKitQuery(predicate: NSPredicate?) async throws -> Set<HKSampleType> { let queryDescriptors: [HKQueryDescriptor] = allTypes .map { type in HKQueryDescriptor(sampleType: type, predicate: predicate) } return try await withCheckedThrowingContinuation { continuation in var hasResumed = false let query = HKObserverQuery(queryDescriptors: queryDescriptors) { query, updatedSampleTypes, completionHandler, error in if hasResumed { return } if let error = error { continuation.resume(throwing: error) } else { continuation.resume(returning: updatedSampleTypes ?? []) } hasResumed = true completionHandler() } healthStore.execute(query) } } internal func getHealthActivity(by date: Date, predicate: NSCompoundPredicate, sampleTypes: Set<HKSampleType>) async throws -> HealthActivityData { var data = HealthActivityData(steps: 0, calories: 0, distance: 0.0, distanceCycling: 0.0, totalDuration: 0, date: date, heartRate: nil) for sampleType in sampleTypes { guard let quantityType = sampleType as? HKQuantityType else { continue } switch quantityType { case HKQuantityType(.stepCount): let stepCount = try await getDescriptor( date: date, type: quantityType ).result(for: healthStore) .statistics(for: date)?.sumQuantity()?.doubleValue(for: HKUnit.count()) data.steps = stepCount ?? 0.0 // Calculate total duration using HKSampleQueryDescriptor let totalDurationDescriptor = HKSampleQueryDescriptor( predicates: [.quantitySample(type: quantityType, predicate: predicate)], sortDescriptors: [SortDescriptor(\.endDate, order: .reverse)] ) let stepSamples = try await totalDurationDescriptor.result(for: healthStore) data.totalDuration += stepSamples .reduce(0) { $0 + $1.endDate.timeIntervalSince($1.startDate) } / 60.0 default: debugPrint("Unknown quantity type") } } return data }
2
0
355
Aug ’24
SwiftData updates from CKSyncEngine (or any other background thread)
I'm currently managing two independent ModelContext instances in my app—one dedicated to CKSyncEngine and another for the Main/UI thread. While this setup works to some extent, I'm encountering a couple of issues: UI Updates: When SwiftData is updated via CKSyncEngine, the UI doesn't automatically refresh. To address this, I've had to implement .refreshable() and write imperative Swift code to (re)fetch data. This approach feels counterintuitive since it prevents me from fully leveraging SwiftUI's declarative nature, such as using @Query and user must explicitly trigger refresh. Deletion Logic: If users delete data via the UI, I have to manage a different delete code path. Specifically, I need to ensure that the object is removed from the UI's ModelContext without triggering a deletion in CKSyncEngine's ModelContext. This dual-path deletion logic feels unnecessarily complex. Also, I intend to later re-use CKSyncEngine part for Command Line tool app that will not have UI at all. What is the correct way to manage SwiftData in a background process like CKSyncEngine while maintaining a seamless and declarative approach in SwiftUI?
1
0
379
Aug ’24