Post

Replies

Boosts

Views

Activity

Reply to BGContinuedProcessingTask launchHandler invocation
the launchHandler is there to "tell" you the task has started and provide you the BGTask object you use to manage that work. No task type actually requires the work to occur inside the task. Thanks Kevin! So I need to think about this a little differently then. Instead of performing the work once you get a BGContinuedProcessingTask, just begin performing the work (the exact same way you do in iOS 18), if a BGContinuedProcessingTask starts persist it and update it as the work completes, and reset state when the work finishes or gets canceled. Basically, something like this: 1-6 I put together code to demonstrate this approach. Did I understand correctly, this should be all good with this simple counting demo? class ViewController: UIViewController { private let taskIdentifier = "\(Bundle.main.bundleIdentifier!).count_task" private let countToNumber: Int64 = 100 private var currentBackgroundContinuedProcessingTask: BGContinuedProcessingTask? private var shouldStopCounting = false @IBOutlet var progressLabel: UILabel! @IBAction func startCountingTapped(_ sender: UIButton) { performCountWork() // Register to support background continued processing // Ensure this is only registered once otherwise app crashes with exception: Launch handler for task with identifier has already been registered if !(UIApplication.shared.delegate as! AppDelegate).didRegisterCountBackgroundContinuedTask { (UIApplication.shared.delegate as! AppDelegate).didRegisterCountBackgroundContinuedTask = true BGTaskScheduler.shared.register(forTaskWithIdentifier: taskIdentifier, using: .main) { task in guard let task = task as? BGContinuedProcessingTask else { return } // The background continued processing task has started, use this task to manage the ongoing work self.currentBackgroundContinuedProcessingTask = task task.expirationHandler = { self.shouldStopCounting = true } } } // Request a background continued processing task start let request = BGContinuedProcessingTaskRequest( identifier: taskIdentifier, title: "Demo Task", subtitle: progressText(completedUnitCount: 0, totalUnitCount: countToNumber) ) request.strategy = .fail // Start the task immediately and fail if it cannot do { try BGTaskScheduler.shared.submit(request) } catch { // This should approximately never happen because the app doesn't submit any more tasks to exceed the system limit // But no big deal if it does not start, the user will just have to keep the app open to make progress print("Failed to submit task: \(error.localizedDescription)") } } @IBAction func stopCountingTapped(_ sender: UIButton) { shouldStopCounting = true } private func performCountWork() { Task { var countedToNumber: Int64 = 0 progressLabel.text = progressText(completedUnitCount: countedToNumber, totalUnitCount: countToNumber) currentBackgroundContinuedProcessingTask?.progress.completedUnitCount = countedToNumber currentBackgroundContinuedProcessingTask?.progress.totalUnitCount = Int64(countToNumber) while !shouldStopCounting && countedToNumber < countToNumber { try! await Task.sleep(nanoseconds: 1_000_000_000) countedToNumber += 1 progressLabel.text = progressText(completedUnitCount: countedToNumber, totalUnitCount: countToNumber) if let task = currentBackgroundContinuedProcessingTask { task.progress.completedUnitCount = countedToNumber task.updateTitle(task.title, subtitle: progressText(completedUnitCount: countedToNumber, totalUnitCount: countToNumber)) } } progressLabel.text = shouldStopCounting ? "Canceled" : "Success!" currentBackgroundContinuedProcessingTask?.setTaskCompleted(success: !shouldStopCounting) currentBackgroundContinuedProcessingTask = nil shouldStopCounting = false } } private func progressText(completedUnitCount: Int64, totalUnitCount: Int64) -> String { return "\(completedUnitCount) / \(totalUnitCount)" } } This seems to work, minus some behavior I did not expect: The Live Activity appears upon Start Counting while the app is in the foreground, I expected it to not appear until the user backgrounds the app. I'm using iPad Pro 26.0 (23A341). But on iPhone Air with 26.1 (23B5044l) the Live Activity does not appear until I close the app. Perhaps a bug that got resolved? The circular progress bar is spinning indeterminately in the Live Activity, not filling the circle as a percentage of completion (on both devices). the two strategies are "fail" (the default) and "queue" BGContinuedProcessingTaskRequest.strategy docs state queue is the default 😅
Sep ’25
Reply to SwiftUI's List backed by CoreData using @FetchRequest fails to update on iOS 26 when compiled with Xcode 26
I’m experiencing this issue with @FetchRequest in my app as well (using LazyVGrid instead of List). The above sample code replicates on iOS 26 beta 8 and 9 using the latest Xcode beta, though it seems to not replicate the first time you run the app only subsequent runs fail to update the UI upon changing a managed object a second time. I filed FB20029616 with a sysdiagnose and screen recording from when it replicated in my app.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Sep ’25
Reply to How to reduce cell height (vertical margins) when using UIListContentConfiguration
Thanks, I should note I want to reduce the vertical margins in the cell as opposed to setting an absolute fixed height dimension, in order to properly support dynamic type text sizes. This is the compositional layout I'm using: let layout = UICollectionViewCompositionalLayout { sectionIndex, environment in let config = UICollectionLayoutListConfiguration(appearance: .insetGrouped) return NSCollectionLayoutSection.list(using: config, layoutEnvironment: environment) }
Topic: UI Frameworks SubTopic: UIKit Tags:
Aug ’25
Reply to MKReverseGeocodingRequest and CNPostalAddress from MKMapItem
I would try to see if you can make MKAddressRepresentations work for your needs, and if you could present the customization options to your customers based that line up with what that class offers I'll pursue this route, thanks! Existing customers will need to change their settings to choose one of the predetermined formats that most closely matches their use case. As folks reach out to report what they can't achieve anymore, I can file feedback reports requesting more formats be added to MKAddressRepresentations. The only thing I'm struggling to come up with is a friendly name to show in the UI for selecting the predetermined format of "city with context" both the short and full variants. Best I have is City, City and State, or City and State and Region - the word "state" is probably not appropriate everywhere. 🤔 it is very easy to naively construct geographically incorrect place descriptions ... we want to discourage folks from doing these string concatenation techniques, and instead rely on the framework to provide you with the correctly formatted information through MKAddressRepresentations Makes sense! With the approach to select specific date components, I took inspiration from DateFormatter.setLocalizedDateFormatFromTemplate(_:) where you specify which components you want and you'll get an appropriately formatted localized string. I thought I achieved that fairly well by preserving the order of components in the postal address just filtering out undesired ones, but can certainly imagine there could be scenarios where the resulting string doesn't really work for different locations around the world. I did file FB8648023 (Template API desired to format addresses with different components, similar to DateFormatter.setLocalizedDateFormatFromTemplate) hoping to replace my solution with a native API, but maybe that's infeasible given address complexity?
Aug ’25
Reply to MKReverseGeocodingRequest and CNPostalAddress from MKMapItem
Hi Ed! The use case in my app is to get the address for where a photo was taken. The user selects which address component(s) they want included. So I look at each attribute from the full attributed address to see if the CNPostalAddressPropertyAttribute is a component the user selected if so I add it to an array. Once enumeration is complete I join the array with commas to separate the components. For examples, if they selected zip it would be just 92101, or if they selected street and city and state it’d be 3835 N Harbor Dr, San Diego, CA. (The selected attributes aren’t guaranteed to be in the final string and that is acknowledged.)
Aug ’25
Reply to BGContinuedProcessingTask launchHandler invocation
the launchHandler is there to "tell" you the task has started and provide you the BGTask object you use to manage that work. No task type actually requires the work to occur inside the task. Thanks Kevin! So I need to think about this a little differently then. Instead of performing the work once you get a BGContinuedProcessingTask, just begin performing the work (the exact same way you do in iOS 18), if a BGContinuedProcessingTask starts persist it and update it as the work completes, and reset state when the work finishes or gets canceled. Basically, something like this: 1-6 I put together code to demonstrate this approach. Did I understand correctly, this should be all good with this simple counting demo? class ViewController: UIViewController { private let taskIdentifier = "\(Bundle.main.bundleIdentifier!).count_task" private let countToNumber: Int64 = 100 private var currentBackgroundContinuedProcessingTask: BGContinuedProcessingTask? private var shouldStopCounting = false @IBOutlet var progressLabel: UILabel! @IBAction func startCountingTapped(_ sender: UIButton) { performCountWork() // Register to support background continued processing // Ensure this is only registered once otherwise app crashes with exception: Launch handler for task with identifier has already been registered if !(UIApplication.shared.delegate as! AppDelegate).didRegisterCountBackgroundContinuedTask { (UIApplication.shared.delegate as! AppDelegate).didRegisterCountBackgroundContinuedTask = true BGTaskScheduler.shared.register(forTaskWithIdentifier: taskIdentifier, using: .main) { task in guard let task = task as? BGContinuedProcessingTask else { return } // The background continued processing task has started, use this task to manage the ongoing work self.currentBackgroundContinuedProcessingTask = task task.expirationHandler = { self.shouldStopCounting = true } } } // Request a background continued processing task start let request = BGContinuedProcessingTaskRequest( identifier: taskIdentifier, title: "Demo Task", subtitle: progressText(completedUnitCount: 0, totalUnitCount: countToNumber) ) request.strategy = .fail // Start the task immediately and fail if it cannot do { try BGTaskScheduler.shared.submit(request) } catch { // This should approximately never happen because the app doesn't submit any more tasks to exceed the system limit // But no big deal if it does not start, the user will just have to keep the app open to make progress print("Failed to submit task: \(error.localizedDescription)") } } @IBAction func stopCountingTapped(_ sender: UIButton) { shouldStopCounting = true } private func performCountWork() { Task { var countedToNumber: Int64 = 0 progressLabel.text = progressText(completedUnitCount: countedToNumber, totalUnitCount: countToNumber) currentBackgroundContinuedProcessingTask?.progress.completedUnitCount = countedToNumber currentBackgroundContinuedProcessingTask?.progress.totalUnitCount = Int64(countToNumber) while !shouldStopCounting && countedToNumber < countToNumber { try! await Task.sleep(nanoseconds: 1_000_000_000) countedToNumber += 1 progressLabel.text = progressText(completedUnitCount: countedToNumber, totalUnitCount: countToNumber) if let task = currentBackgroundContinuedProcessingTask { task.progress.completedUnitCount = countedToNumber task.updateTitle(task.title, subtitle: progressText(completedUnitCount: countedToNumber, totalUnitCount: countToNumber)) } } progressLabel.text = shouldStopCounting ? "Canceled" : "Success!" currentBackgroundContinuedProcessingTask?.setTaskCompleted(success: !shouldStopCounting) currentBackgroundContinuedProcessingTask = nil shouldStopCounting = false } } private func progressText(completedUnitCount: Int64, totalUnitCount: Int64) -> String { return "\(completedUnitCount) / \(totalUnitCount)" } } This seems to work, minus some behavior I did not expect: The Live Activity appears upon Start Counting while the app is in the foreground, I expected it to not appear until the user backgrounds the app. I'm using iPad Pro 26.0 (23A341). But on iPhone Air with 26.1 (23B5044l) the Live Activity does not appear until I close the app. Perhaps a bug that got resolved? The circular progress bar is spinning indeterminately in the Live Activity, not filling the circle as a percentage of completion (on both devices). the two strategies are "fail" (the default) and "queue" BGContinuedProcessingTaskRequest.strategy docs state queue is the default 😅
Replies
Boosts
Views
Activity
Sep ’25
Reply to SwiftUI Slider will cause app to crash on macOS Tahoe RC
Oof this happens even with apps built using the Mac Catalyst 18 SDK. Production users are unable to use my app on macOS 26, Slider takes it down. Thanks for filing a bug, here’s to hoping it’s fixed quickly in 26.0.1.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Sep ’25
Reply to SwiftUI's List backed by CoreData using @FetchRequest fails to update on iOS 26 when compiled with Xcode 26
I’m experiencing this issue with @FetchRequest in my app as well (using LazyVGrid instead of List). The above sample code replicates on iOS 26 beta 8 and 9 using the latest Xcode beta, though it seems to not replicate the first time you run the app only subsequent runs fail to update the UI upon changing a managed object a second time. I filed FB20029616 with a sysdiagnose and screen recording from when it replicated in my app.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Sep ’25
Reply to iOS 26 Liquid Glass not showing
Check if the app was built using the iOS 26 SDK (run it from Xcode 26 beta, not any earlier version).
Topic: UI Frameworks SubTopic: General Tags:
Replies
Boosts
Views
Activity
Sep ’25
Reply to Dividers not appearing in menu bar on iPadOS 26
This bug was fixed at some point in the beta cycle.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Aug ’25
Reply to Different toolbar item placement for iPhone vs iPad
The latest beta positions the search bar at the top right on iPad by default, just like iPadOS 18. I tweaked the others based on user interface idiom to achieve the remaining desired positions on iPad.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Aug ’25
Reply to How to reduce cell height (vertical margins) when using UIListContentConfiguration
Setting directionalLayoutMargins top/bottom to a number less than 15 (the default value) has no effect (even negative numbers). A number greater than 15 does increase it beyond the default margins. Seems the system enforces minimum vertical margins :/
Topic: UI Frameworks SubTopic: UIKit Tags:
Replies
Boosts
Views
Activity
Aug ’25
Reply to How to reduce cell height (vertical margins) when using UIListContentConfiguration
Thanks, I should note I want to reduce the vertical margins in the cell as opposed to setting an absolute fixed height dimension, in order to properly support dynamic type text sizes. This is the compositional layout I'm using: let layout = UICollectionViewCompositionalLayout { sectionIndex, environment in let config = UICollectionLayoutListConfiguration(appearance: .insetGrouped) return NSCollectionLayoutSection.list(using: config, layoutEnvironment: environment) }
Topic: UI Frameworks SubTopic: UIKit Tags:
Replies
Boosts
Views
Activity
Aug ’25
Reply to MKReverseGeocodingRequest and CNPostalAddress from MKMapItem
I would try to see if you can make MKAddressRepresentations work for your needs, and if you could present the customization options to your customers based that line up with what that class offers I'll pursue this route, thanks! Existing customers will need to change their settings to choose one of the predetermined formats that most closely matches their use case. As folks reach out to report what they can't achieve anymore, I can file feedback reports requesting more formats be added to MKAddressRepresentations. The only thing I'm struggling to come up with is a friendly name to show in the UI for selecting the predetermined format of "city with context" both the short and full variants. Best I have is City, City and State, or City and State and Region - the word "state" is probably not appropriate everywhere. 🤔 it is very easy to naively construct geographically incorrect place descriptions ... we want to discourage folks from doing these string concatenation techniques, and instead rely on the framework to provide you with the correctly formatted information through MKAddressRepresentations Makes sense! With the approach to select specific date components, I took inspiration from DateFormatter.setLocalizedDateFormatFromTemplate(_:) where you specify which components you want and you'll get an appropriately formatted localized string. I thought I achieved that fairly well by preserving the order of components in the postal address just filtering out undesired ones, but can certainly imagine there could be scenarios where the resulting string doesn't really work for different locations around the world. I did file FB8648023 (Template API desired to format addresses with different components, similar to DateFormatter.setLocalizedDateFormatFromTemplate) hoping to replace my solution with a native API, but maybe that's infeasible given address complexity?
Replies
Boosts
Views
Activity
Aug ’25
Reply to MKReverseGeocodingRequest and CNPostalAddress from MKMapItem
Hi Ed! The use case in my app is to get the address for where a photo was taken. The user selects which address component(s) they want included. So I look at each attribute from the full attributed address to see if the CNPostalAddressPropertyAttribute is a component the user selected if so I add it to an array. Once enumeration is complete I join the array with commas to separate the components. For examples, if they selected zip it would be just 92101, or if they selected street and city and state it’d be 3835 N Harbor Dr, San Diego, CA. (The selected attributes aren’t guaranteed to be in the final string and that is acknowledged.)
Replies
Boosts
Views
Activity
Aug ’25
Reply to Issue with layoutMarginsGuide under iOS 26
Seems like a good bug report to me! I don’t see anything missing, or have an explanation for the different behavior, so seems it could be not working as expected.
Topic: UI Frameworks SubTopic: UIKit Tags:
Replies
Boosts
Views
Activity
Jul ’25
Reply to Different toolbar item placement for iPhone vs iPad
Thanks, but in this app I don’t have a split view. No sidebar and no plans to add one.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Jul ’25
Reply to How to hide scroll edge effect until scroll down
Found it! .scrollEdgeEffectHidden(scrollEdgeEffectHidden, for: .top) does the trick setting scrollEdgeEffectHidden via .onScrollGeometryChange(for: CGFloat.self) looking at the geometry.contentOffset.y
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Jul ’25
Reply to Why does a purchase result in success unverified?
+1 I too would like to know in what scenarios would it be successful but not verified. I’m ignoring that scenario in my app, not unlocking the content unless it’s a verified purchase.
Topic: App & System Services SubTopic: StoreKit Tags:
Replies
Boosts
Views
Activity
Jul ’25
Reply to AppIntent perform function is not invoked from ControlWidget
It seems perform is not invoked because the system does not support showing request value dialogs to ask the user which object they want to edit when using this intent in a ControlWidget. Not sure if that's documented somewhere.
Replies
Boosts
Views
Activity
Jul ’25