Post

Replies

Boosts

Views

Activity

Core Data, Swift 6, Concurrency and more
I have the following struct doing some simple tasks, running a network request and then saving items to Core Data. Per Xcode 26's new default settings (onisolated(nonsending) & defaultIsolation set to MainActor), the struct and its functions run on the main actor, which works fine and I can even safely omit the context.perform call because of it, which is great. struct DataHandler { func importGames(withIDs ids: [Int]) async throws { ... let context = PersistenceController.shared.container.viewContext for game in games { let newGame = GYGame(context: context) newGame.id = UUID() } try context.save() } } Now, I want to run this in a background thread to increase performance and responsiveness. So I followed this session (https://developer.apple.com/videos/play/wwdc2025/270) and believe the solution is to mark the struct as nonisolated and the function itself as @concurrent. The function now works on a background thread, but I receive a crash: _dispatch_assert_queue_fail. This happens whether I wrap the Core Data calls with context.perform or not. Alongside that I get a few new warnings which I have no idea how to work around. So, what am I doing wrong here? What's the correct way to solve this simple use case with Swift 6's new concurrency stuff and the default main actor isolation in Xcode 26? Curiously enough, when setting onisolated(nonsending) to false & defaultIsolation to non isolating, mimicking the previous behavior, the function works without crashing. nonisolated struct DataHandler { @concurrent func importGames(withIDs ids: [Int]) async throws { ... let context = await PersistenceController.shared.container.newBackgroundContext() for game in games { let newGame = GYGame(context: context) newGame.id = UUID() // Main actor-isolated property 'id' can not be mutated from a nonisolated context; this is an error in the Swift 6 language mode } try context.save() } }
2
0
178
Jun ’25
defaultIsolation option and Core Data
When creating a new project in Xcode 26, the default for defaultIsolation is MainActor. Core Data creates classes for each entity using code gen, but now those classes are also internally marked as MainActor, which causes issues when accessing managed object from a background thread like this. Is there a way to fix this warning or should Xcode actually mark these auto generated classes as nonisolated to make this better? Filed as FB13840800. nonisolated struct BackgroundDataHandler { @concurrent func saveItem() async throws { let context = await PersistenceController.shared.container.newBackgroundContext() try await context.perform { let newGame = Item(context: context) newGame.timestamp = Date.now // Main actor-isolated property 'timestamp' can not be mutated from a nonisolated context; this is an error in the Swift 6 language mode try context.save() } } } Turning code gen off inside the model and creating it manually, with the nonisolated keyword, gets rid of the warning and still works fine. So I guess the auto generated class could adopt this as well? public import Foundation public import CoreData public typealias ItemCoreDataClassSet = NSSet @objc(Item) nonisolated public class Item: NSManagedObject { }
1
0
103
Jun ’25
Context menus need option to disable morphing
For some controls it is desirable to not use the morphing transition when presenting a Menu. Instead, you might want to have the old behavior, where the menu is presented above or below the initiating view. This can be the case for any other control than toolbar items, but especially for bigger content cards, that should trigger a menu upon tapping it once. In those cases it looks weird and does not really help to keep context of what the action is doing. Is there some way to do this right now? In case it's not, I also filed a feedback. FB18413055
0
0
90
Jul ’25
New typed notifications for keyboards do not work?
@MainActor class KeyboardObserver { var token: NotificationCenter.ObservationToken! func registerObserver(screen: UIScreen) { let center = NotificationCenter.default token = center.addObserver(of: screen, for: .keyboardWillShow) { keyboardState in print("+++ Keyboard showed up!") } } } The notification is never called. The sample code from the sessions also does not work for me. let keyboardObserver = NotificationCenter.default.addObserver( of: UIScreen.self for: .keyboardWillShow ) { message in UIView.animate( withDuration: message.animationDuration, delay: 0, options: .flushUpdates ) { // Use message.endFrame to animate the layout of views with the keyboard let keyboardOverlap = view.bounds.maxY - message.endFrame.minY bottomConstraint.constant = keyboardOverlap } } @MainActor class KeyboardObserver { func registerObserver(screen: UIScreen) { let center = NotificationCenter.default let token = center.addObserver( of: screen, for: .keyboardWillShow ) { keyboardState in let startFrame = keyboardState.startFrame let endFrame = keyboardState.endFrame self.keyboardWillShow(startFrame: startFrame, endFrame: endFrame) } } func keyboardWillShow(startFrame: CGRect, endFrame: CGRect) {} }
Topic: UI Frameworks SubTopic: UIKit Tags:
3
0
139
Aug ’25
How to create an overlay with padding that ignores the safe area?
Was it always so tricky to ignore the bottom safe area? Seems like iOS 26 makes this much harder. I've tried many variations of ignoresSafeArea, safeAreaInset, safeAreaBar, etc. Nothing seems to work. As soon as I add padding, the bottom safe area crashes the party. This is what I want to achieve: This is what I get right now: struct ContentView: View { var body: some View { List { Text("Content") } .overlay(alignment: .bottom) { content } } var content: some View { VStack { Text("Custom Container") } .frame(maxWidth: .infinity) .frame(height: 400) .background(Color.gray, in: .rect(corners: .concentric, isUniform: true)) .padding(15) } }
3
0
127
Aug ’25
Concentric corners not working
I want the gray view to have concentric corners with the device border. That works. Then I want the blue rectangle to have concentric corners with the gray view. That does not work. Instead the blue rectangle is also concentric with the device border. Once I add other content like a Text element, the corner radius breaks. How can I make this work? .containerShape does not take a ConcentricContainerShape. struct ContentView: View { var body: some View { List { Text("Content") } .overlay(alignment: .bottom) { content } .ignoresSafeArea(.all, edges: .bottom) } var content: some View { VStack(alignment: .leading) { Rectangle() .foregroundStyle(.blue) .frame(width: 100, height: 100) .clipShape(.rect(corners: .concentric, isUniform: true)) Text("Custom Container") } .padding(20) .frame(maxWidth: .infinity, alignment: .leading) .background(Color.gray, in: .rect(corners: .concentric, isUniform: true)) .padding(15) } }
2
0
122
Sep ’25
App lifecycle on iPadOS 26
It appears from my testing that the following is true: If you close all windows of an app, the app terminates entirely. Minimizing the last window sends it into multitasking. This is different from previous behavior and might have implications on your app's logic. If you close the last window and quickly tap the app icon again, that same window will come back. Waiting a second before tapping the app icon will bring up the main window (likely because by that point the app was terminated and relaunched). Is this expected behavior? I did not see any announcement of this. I find this a bit counterintuitive and would presume that closing the last window would just send the app to multitasking, just like previously. Quitting the app should be reserved by swiping up on it in the multitasking UI or with a new context menu command.
Topic: UI Frameworks SubTopic: UIKit Tags:
0
0
93
Aug ’25
New window scenes on iPad always take the size of the activating window
I'm using multiple scenes in my iPad app. When I open a new scene from my main window, that new window is always the same size as the previous window. When I make the main window very small and then create a new scene, that new window is also tiny. When I make the main window very big, you guessed it. UIWindowScene.sizeRestrictions does not seem to help here. How can I give new windows a default size (it's okay if they're resizable after presenting)? This is such a weird behavior. Video of the problem in action: https://mastodon.social/@nicoreese/115033539035249909
Topic: UI Frameworks SubTopic: UIKit Tags:
1
0
149
Aug ’25
PSA: Call Screening breaks in a multitude of ways; no missed call notifications or badges; not lighting up screen; not visible when using focus;
Call Screening has serious issues right now leading to missing calls from genuine callers because the system does not acknowledge them with missed call notifications or badges in a lot of cases. I'm posting this in the hope of catching an engineer who can bring this to the attention of the teams working on this. Filed as FB20678829 — I ran the following tests with iOS 26.1 beta 3, but the issues have been occurring on iOS 26.0 as well. I used an iPhone, Apple Watch, iPad, and Mac for this. The iPhone has Call Screening enabled with the option „Ask Reason for Calling“ The iPhone has call forwarding enabled to all devices. Test 1: Active Focus Turn on a focus like Do not Disturb on all devices. Lock all devices. Make a phone call to the iPhone with an unknown number. Behavior: iPhone: displays Call Screening UI on the Lock Screen, but it will not light up the screen. You don’t know Call Screening is happening unless you activate the display just in that moment on devices without Always On Display. Watch: does nothing. Mac: does nothing. iPad: displays Call Screening UI on the Lock Screen, but it will not light up the screen. You don’t know Call Screening is happening unless you activate the display just in that moment. In this test the caller does not answer any of the Call Screening questions and just hangs up. The result is that only the Mac displays a missed call notification. iPhone, iPad, and Watch do not acknowledge the missed call (no phone app icon badge, no notification, no badge inside the Phone app itself), you can only see the call inside the Calls list when manually looking for it. Test 2: No Focus Turn off any focus like Do not Disturb on all devices. Lock all devices. Make a phone call to the iPhone with an unknown number. Behavior: iPhone: displays Call Screening UI on the Lock Screen, but it will not light up the screen. You don’t know Call Screening is happening unless you activate the display just in that moment on devices without Always On Display. Watch: does nothing. Mac: displays Call Screening UI when unlocked. iPad: displays Call Screening UI on the Lock Screen, but it will not light up the screen. You don’t know Call Screening is happening unless you activate the display just in that moment. In this test the caller does not answer any of the Call Screening questions and just hangs up. The result is that only the Mac displays a missed call notification. iPhone, iPad, and Watch do not acknowledge the missed call (no phone app icon badge, no notification, no badge inside the Phone app itself), you can only see the call inside the Calls list when manually looking for it. The only improvement here is that the Mac now shows the Call Screening UI. Test 3: Caller answers Call Screening questions An active focus does not matter. Lock all devices. Make a phone call to the iPhone with an unknown number. Once the caller answered the Call Screening questions, the following happens: All devices ring like expected When the caller hangs up or I don’t answer: Mac: Shows Missed Call notification without details iPhone: Shows Missed Call notification with transcript of Call Screening (also badges phone app icon) iPad: does nothing. Watch: Shows the mirrored iPhone notification. Things to note: When turning off call forwarding on iPhone to other Apple devices like iPad and Mac, the phone app icon is always badged for missed calls when Call Screening was active, but no notification is displayed regardless.
0
0
106
Oct ’25
Multiline Text not possible in accessoryRectangular widget on lock screen
Filed as FB20766506 I have a very simple use case for a rectangular widget on the iPhone lock screen: One Text element which should fill as much space as possible. However, it only ever does 2 per default and then eclipses the rest of the string. Three separate Text elements work fine, so does a fixedSize modifier hack (with that even four lines are possible!). Am I completely misunderstanding something or why is this not possible per default? Other apps' widgets like Health do it as well. My attempt (background added for emphasis) Health app widget var body: some View { VStack(alignment: .leading) { /// This should span three lines, but only spans 2 which eclipsed text. Text("This is a very long text which should span multiple lines.") // .fixedSize(horizontal: false, vertical: true) /// Using this fixes it as well, but that does not seem like a good default solution. /// Three separate `Text` elements work fine. // Text("This is a very long") // Text("text which should") // Text("span multiple lines.") } .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading) .background(Color.black) /// Added for emphasis of the widget frame }
2
0
149
Oct ’25
UITabBarController ignores UITab view controllers when in UITabGroup
When composing tabs like this and selecting them in the sidebar, only the group's view controller is ever displayed, even when selecting the individual first and second tabs. Their view controllers are just ignored. Am I immensely stupid here or is this a bug in iPadOS 26 beta 3? // First tab let firstTab = UITab( title: "First", image: UIImage(systemName: "heart"), identifier: "hello" ) { _ in UINavigationController(rootViewController: ViewController()) } // Second tab let secondTab = UITab( title: "Second", image: UIImage(systemName: "heart"), identifier: "hello2" ) { _ in UIViewController() } // Tab group let tabGroup = UITabGroup( title: "Stuff", image: nil, identifier: "stuff", children: [firstTab, secondTab] ) { _ in ViewController() } let tbc = UITabBarController(tabs: [tabGroup]) tbc.mode = .tabSidebar
Topic: UI Frameworks SubTopic: UIKit
3
0
213
Jul ’25
iPad menu bar and multiple windows
I'm trying to support the new menu bar in iPadOS 26. In AppDelegate I do this. I want to this to be a global command, which can work regardless of which view controller is currently visible, so I let the AppDelegate handle the selector (if there's a better way let me know). UIMainMenuSystem.shared.setBuildConfiguration(config) { builder in let createCollectionCommand = UIKeyCommand( title: String(localized: "Create Collection"), image: UIImage(systemName: "folder.badge.plus"), action: #selector(AppDelegate.showCreateCollectionViewController), input: "c", modifierFlags: .control ) builder.insertElements([createCollectionCommand], atEndOfMenu: .file) } This works mostly. A problem arrises when I have multiple windows open at the same time. I need a way to determine the currently active window scene from AppDelegate to display a sheet on that window's root view controller. There's stuff like this, but unfortunately all visible windows have activationState == .foregroundActive, so I cannot use that. guard let scene = UIApplication.shared.connectedScenes.first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene else { return } So, how do I do multi-window global commands? I'm basically looking for something like the "Create Playlist" command in the Music app.
Topic: UI Frameworks SubTopic: UIKit Tags:
2
0
146
Jul ’25
Replacing the Preferences item in a menu bar
Per default the menu bar on iPad includes an application menu named after your app which includes a Preferences action. That one opens the Settings app to your app settings page. I do not really populate that with options and instead have my own settings UI accessible in my app using toolbar items. What's the best approach to handle this with the menu bar? I've tried replacing the default Preferences item but that only works if I do not use its shortcut, which I would like to preserve. Another solution would be to append another Settings item for my UI, which would look weird and confusing, but seems to be the recommended way from the HIG. Reserve the YourAppName > Settings menu item for opening your app’s page in iPadOS Settings. If your app includes its own internal preferences area, link to it with a separate menu item beneath Settings in the same group. Place any other custom app-wide configuration options in this section as well. I take it there is no way to replace it then?
Topic: UI Frameworks SubTopic: UIKit Tags:
3
0
159
Jul ’25
UITabBarController, menu bar and first responder
I'm using a standard UITabBarController on iPad. When first selecting any tab, the corresponding menu bar items are grayed out for this view controller. It's only when I tap any button in that view controller, like in the toolbar, that the view controller truly becomes the first responder (you can see the sidebar selection turns to gray from blue), enabling those menu bar items. Am I doing something wrong here? A video of the issue can be found here: https://mastodon.social/@nicoreese/114949924393554961 AppDelegate: ... builder.insertChild(MenuController.viewModeMenu(), atStartOfMenu: .view) class func viewModeMenu() -> UIMenu { let listViewModeCommand = UICommand( title: String(localized: "As List"), image: UIImage(systemName: "list.bullet"), action: #selector(GamesViewController.setListViewMode), propertyList: SettingsService.ViewMode.list.rawValue ) ... let viewModeMenu = UIMenu( title: "", image: nil, identifier: .viewModeMenu, options: .displayInline, children: [listViewModeCommand...] ) return viewModeMenu } GamesViewController: @objc func setListViewMode() { updateViewMode(.list) } I can do this, but then the sidebar selection instantly turns gray, which looks odd and other system apps do not behave this way. override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) becomeFirstResponder() } override var canBecomeFirstResponder: Bool { return true }
Topic: UI Frameworks SubTopic: UIKit Tags:
5
0
236
Aug ’25