Explore the various UI frameworks available for building app interfaces. Discuss the use cases for different frameworks, share best practices, and get help with specific framework-related questions.

All subtopics
Posts under UI Frameworks topic

Post

Replies

Boosts

Views

Activity

Localization in Swift macOS console Apps.
Is it possible to build localization into console apps, developed in SwiftUI in Xcode26. I have created a catalog, (.xcstrings file) with an English and fr-CA string. I have tried to display the French text without success. I am using the console app to test a package which also has English/French text. English text works fine in both package and the console main, but I cannot generate the French. From what I can discover so far it's not possible without bundling it as a .app, (console app). Looking for anyone who has crossed this bridge.
7
0
275
2d
My app doesn't respond on iPhone Air iOS 26.1.
My app doesn't respond on iPhone Air iOS 26.1. After startup, my app shows the main view with a tab bar controller containing 4 navigation controllers. However, when a second-level view controller is pushed onto any navigation controller, the UI freezes and becomes unresponsive. The iPhone simulator running iOS 26.1 exhibits the same problem. The debug profile shows CPU usage at 100%. However, other devices and simulators do not have this problem.
7
3
539
3d
PDFView left-anchors to window edge instead of centering between sidebar and inspector (macOS Tahoe)
I'm building a document viewer on macOS Tahoe with a 3-column NSSplitViewController (sidebar | detail | inspector), trying to replicate how Preview displays PDFs with the page centered in the visible gap between the panels, with content bleeding under them when panning or zooming. I'm using the approach from Build an AppKit app with the new design (WWDC25): detailItem.automaticallyAdjustsSafeAreaInsets = true safeAreaInsets reports the correct values (e.g. left: 208, right: 240), and the frame does extend under both panels. But PDFView with autoScales = true anchors the page to the left edge of the window instead of centering it in the visible gap between the sidebar and inspector. I can get the page to center correctly by constraining PDFView to view.safeAreaLayoutGuide, but then content no longer extends under the panels when panning or zooming, which defeats the whole purpose. What's the correct way to center PDFView content within the visible gap while keeping the frame full-width so content bleeds under the panels? I've attached pictures of how Preview does it.
Topic: UI Frameworks SubTopic: AppKit
0
0
60
3d
SwiftUI Chart scrolling on macOS
I'm running macOS 26.3 and using Xcode 26.4. I'm trying to create a SwiftUI Chart that can scroll horizontally. In the SwiftUI Preview, and also running the app on macOS, the chart displays a scrollbar, but the scrollbar does not respond to mouse interaction (dragging the scrollbar, or clicking in the gutters on either side of the scrollbar). Here's the sample code: import SwiftUI import Charts private struct DataPoint: Identifiable { let id: Int let x: Double let value: Double } struct ContentView: View { private let points: [DataPoint] = (0..<60).map { index in let wave = sin(Double(index) * 0.28) * 18 let trend = Double(index) * 0.35 return DataPoint(id: index, x: Double(index), value: 60 + wave + trend) } var body: some View { Chart(points) { point in BarMark( x: .value("Data Point", point.x), y: .value("Value", point.value) ) .foregroundStyle(.blue.gradient) } .chartScrollableAxes(.horizontal) // Doesn't work: // .scrollIndicators(.hidden) // .never also does not work .chartXVisibleDomain(length: 20) .padding() } } #Preview { ContentView() }
3
0
105
3d
UIScrollView Fast Scrolling have it scroll to the beginning when i press dpad to left while vertical scrolling
I'm triaging the issue with the fast scrolling on UIScrollView and I'm really upset how little to no info this component is on the internet. Like i disabled scrolling and yet after holding the dpad down to scroll downward eventually the fast scroll mechanism is used. The issue I have is that I have a setup where the scrollview scrolling is disabled and whenever cells are focused it'll scroll to the cell's position for that cells to focused on top left side of the scrollview. I start off with the cell placed at position x of 1000. I scroll down enough to enable fast scrolling. While fast scrolling vertically, i press left a couple of time and it somewhat scroll horizontally. Actual scrollView index is suddenly placed to x:0 instead of let say x:950-1000 Expected should be scrolled to the left of cell at position x 1000. Attached the stack trace and the log showcasing it and run it on simulator tvos 26.2. Initial properties of the scrollview we set up scroll = [UIScrollView new]; scroll.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; scroll.automaticallyAdjustsScrollIndicatorInsets = false; [scroll setDirectionalLockEnabled:TRUE]; [scroll setContentInset:UIEdgeInsetsMake(0, 0, 0, 0)]; scroll.bounces = FALSE; scroll.delaysContentTouches = FALSE; scroll.showsVerticalScrollIndicator = FALSE; scroll.showsHorizontalScrollIndicator = FALSE; The plan for me at least is to somehow disable the horizontal scrolling interaction of it when fast scrolling is enabled, without accessing the private components of it.
0
0
53
3d
NavigationLink selection in DisclosureGroup not working with .draggable modifier
NavigationLink selection in DisclosureGroup not working with .draggable modifier This was recently also posted here: https://stackoverflow.com/questions/79914290/ I am playing around with a tree data structure with folders and entries.I would like to add dragging of entries and folders between folders, using .draggable and dropDestination. In my current code, dragging works, but selection of entries no longer works, except if I click outside of the Text If I comment out .draggable(subfolder.name) in func FolderRow(), selection works as expected. How can I make sure both selection and drag and drop works for both folders and entries? I also tried using Transferable and Codable, but I get the same result. Here is an MRE: import SwiftData import SwiftUI @Model final class Folder { @Attribute(.unique) var name: String // Parent var parentFolder: Folder? // Child folders @Relationship(deleteRule: .cascade, inverse: \Folder.parentFolder) var subfolders: [Folder] = [] // Leaf entries @Relationship(deleteRule: .cascade, inverse: \Entry.folder) var entries: [Entry] = [] init(name: String, parentFolder: Folder? = nil) { self.name = name self.parentFolder = parentFolder } } @Model final class Entry { @Attribute(.unique) var name: String var detail: String var folder: Folder? // recursive relationship init(name: String, detail: String) { self.name = name self.detail = detail } } @main struct TestMacApp: App { var body: some Scene { WindowGroup { SidebarView() .modelContainer(for: Folder.self) } } } struct SidebarView: View { @Environment(\.modelContext) private var context @Query(filter: #Predicate<Folder> { $0.parentFolder == nil }) private var rootFolders: [Folder] var body: some View { NavigationSplitView { List { ForEach(rootFolders) { folder in FolderRow(folder: folder) .draggable(folder.name) } } } detail: { Text("detail") } .onAppear { seed() } } } struct FolderRow: View { @Environment(\.modelContext) private var context var folder: Folder @State private var isExpanded: Bool = true var body: some View { DisclosureGroup(isExpanded: $isExpanded) { // Subfolders ForEach(folder.subfolders) { subfolder in FolderRow(folder: subfolder) .draggable(subfolder.name) // disabling this line fixes the selection } // Entries (leaf nodes) ForEach(folder.entries) { entry in NavigationLink(destination: EntryDetail(entry: entry)) { EntryRow(entry: entry) } .draggable(entry.name) } } label: { Label(folder.name, systemImage: "folder") } .dropDestination(for: String.self) { names, _ in return handleDrop(of: names) } } } struct EntryRow: View { var entry: Entry var body: some View { Text(entry.name) } } struct EntryDetail: View { var entry: Entry var body: some View { Text(entry.detail) } } extension FolderRow { private func handleDrop(of names: [String]) -> Bool { do { for name in names { if let droppedEntry = try context.fetchFilteredModel(filter: #Predicate<Entry> { x in x.name == name }) { droppedEntry.folder = folder print("dropped \(droppedEntry.name) on \(folder.name)") } else if let droppedFolder = try context.fetchFilteredModel(filter: #Predicate<Folder> { x in x.name == name }) { if droppedFolder.parentFolder != nil && droppedFolder != folder { droppedFolder.parentFolder = folder print("dropped \(droppedFolder.name) on \(folder.name)") } } } return true } catch { debugPrint(error.localizedDescription) return false } } } extension SidebarView { private func seed() { do { // delete current models for folder: Folder in try context.fetchAllModels() { context.delete(folder) } try context.save() let rootFolder = Folder(name: "Root") let entry1 = Entry(name: "One", detail: "Detail One") let entry2 = Entry(name: "Two", detail: "Detail Two") rootFolder.entries.append(contentsOf: [entry1, entry2]) let subFolder1 = Folder(name: "Sub1", parentFolder: rootFolder) let entry3 = Entry(name: "Three", detail: "Detail Three") let entry4 = Entry(name: "Four", detail: "Detail Four") subFolder1.entries.append(contentsOf: [entry3, entry4]) let subFolder2 = Folder(name: "Sub2", parentFolder: rootFolder) let entry5 = Entry(name: "Five", detail: "Detail Five") let entry6 = Entry(name: "Six", detail: "Detail Six") subFolder2.entries.append(contentsOf: [entry5, entry6]) context.insert(rootFolder) } catch { debugPrint(error) } } } extension ModelContext { // convenience methods func fetchAllModels<M>() throws -> [M] where M: PersistentModel { let fetchDescriptor = FetchDescriptor<M>() return try fetch(fetchDescriptor) } func fetchFilteredModels<M>(filter: Predicate<M>) throws -> [M] where M: PersistentModel { let fetchDescriptor = FetchDescriptor<M>(predicate: filter) return try fetch(fetchDescriptor) } func fetchFilteredModel<M>(filter: Predicate<M>) throws -> M? where M: PersistentModel { return try fetchFilteredModels(filter: filter).first } }
Topic: UI Frameworks SubTopic: SwiftUI
1
0
168
3d
Combining NavigationSplitView and TabView in iOS 18
Hi folks, I've used a NavigationSplitView within one of the tabs of my app since iOS 16, but with the new styling in iOS 18 the toolbar region looks odd. In other tabs using e.g. simple stacks, the toolbar buttons are horizontally in line with the new tab picker, but with NavigationSplitView, the toolbar leaves a lot of empty space at the top (see below). Is there anything I can do to adjust this, or alternatively, continue to use the old style? Thanks!
13
3
3.0k
3d
Migrating to the UIKit scene-based life cycle
I got this debuglog in Xcode26. "UIScene lifecycle will soon be required. Failure to adopt will result in an assert in the future." I haven't included any UIScene lifecycle code. I read the article on TN3187: Migrating to the UIKit scene-based life cycle. Does this mean that when iOS27 iPhone is released, the app will crash after startup? If Xcode26/iOS27 crashes, is there a quick fix I can use?
Topic: UI Frameworks SubTopic: UIKit
2
0
160
3d
Scene resizing on iPad breaks UIPageViewController's setViewControllers
The following is verbatim of a feedback report (FB22367951) I submitted, shared here as someone else might be interested to see it. I have reproduced this bug on iPadOS 26.3.1 (a) and 26.4. During scene resizing on iPad, UIPageViewController's setViewControllers method fails to do its work. The navigation starts and for a brief moment you can see the new view controller coming from the expected direction, but shortly after it fails and stays on the same [current] view controller. It doesn't even call the completion handler when it fails. When the navigation succeeds (due to not resizing a scene during the navigation) after previously failing at least once, the completion handler is sometimes called more than once. I have created a demo project, which I have pushed to this repo: https://github.com/galijot/SceneResize-Breaks-UIPageViewController I have also attached a zip of the project to this report.
0
0
36
3d
On macOS Settings window navigation bar item is in the center
Hi, Overview I have a Mac app with a settings window. When I add a button it is added to the center. I want it on the trailing edge, I even tried adding it as confirmationAction but doesn’t work. Screenshot Feedback FB21374186 Steps to reproduce Run the project on mac Open the app's settings by pressing ⌘ , Notice that the Save button is in the center instead of the trailing edge Code App import SwiftUI @main struct SettingsToolbarButtonBugApp: App { var body: some Scene { WindowGroup { ContentView() } Settings { SettingsView() .frame(width: 300, height: 400) } } } SettingsView import SwiftUI struct SettingsView: View { var body: some View { NavigationStack { Form { Text("Settings window") } .toolbar { ToolbarItem(placement: .confirmationAction) { // Save button is the center instead of trailing edge Button("Save") {} } } .navigationTitle("Settings") } } }
Topic: UI Frameworks SubTopic: SwiftUI
1
0
176
4d
UIView + CATiledLayer + SwiftUI Hosting + iOS 26 = Crash?
Our app uses a UIView backed by a CATiledLayer that is embedded in a UIScrollView, to represent a large document viewer. (PDF data, actually.) It needs to be big - far too big to allocate a single layer, and it needs to be able to reveal more detail as you zoom in. This is the exact use case for a CATiledLayer. CATiledLayer does its drawing on a background thread, as you know, and we've always taken care to make our draw method thread-safe. It has worked great for us, for over a decade now. However, starting with iOS 26, we've been having some surprising crashes. It looks like our CATiledLayer (I think?) is trying to trigger a layout on the background thread as well. This is frustrating because it doesn't have any subviews or sublayers - there's no reason for it. I'm suspecting the CATiledLayer because it does its drawing on a thread, so maybe it would also do other things there, but honestly, I'm not sure - it's hard to tell. Here's the crash. Normally with a crash like this, the solution is to bounce your layout call out to the main thread, but in our case, I'm not the one calling the layout function. The system (Core Animation) is doing it, and I can't figure out what I might be doing that is triggering it. Everything I am doing is on the main thread, and there's none of my code in this stack trace. It's possible this may have something to do with the SwiftUI hosting view, as well? There's definitely one of those involved here - our custom PDF viewer is embedded in one. (That's another reason to suspect the CATiledLayer - whatever is crashing here is in a SwiftUI hosting view, and the PDF viewer is just about the only UIKit on the screen, here, embedded in a hosting view.) I also have a test app that is pure UIKit, where I have not been able to reproduce the crash. I've tried subclassing CATiledLayer and having an empty implementation of updateSublayers, and some other, similar hacks along those lines, but nothing I do seems to help. I'm tempted to try moving from CATiledLayer to simple UIViews, and tiling those myself, but that's a lot of work. I want to be sure there's not some other solution before I try something like that. Is CATiledLayer still a supported mechanism or should I be moving away from it? If it is something entirely different that is crashing here, I don't want to do a bunch of rework of the PDF viewer only to end up with the same results. It really smells like a UIKit bug to me, or at least UIKit making some concurrency assumptions that CATiledLayer is breaking. But all I can really do is guess. *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Modifications to the layout engine must not be performed from a background thread after it has been accessed from the main thread.' *** First throw call stack: ( 0 CoreFoundation 0x00000001804f7348 __exceptionPreprocess + 172 1 libobjc.A.dylib 0x000000018009c094 objc_exception_throw + 72 2 CoreAutoLayout 0x000000022d3cc13c __36-[NSISEngine rebuildFromConstraints]_block_invoke + 0 3 CoreAutoLayout 0x000000022d3cbee0 -[NSISEngine _optimizeWithoutRebuilding] + 68 4 CoreAutoLayout 0x000000022d3cbe14 -[NSISEngine optimize] + 92 5 CoreAutoLayout 0x000000022d3c8744 -[NSISEngine performPendingChangeNotifications] + 100 6 UIKitCore 0x00000001869c7e7c -[UIView(Hierarchy) layoutSubviews] + 132 7 SwiftUI 0x00000001ddb40318 $s7SwiftUI14_UIHostingViewC14layoutSubviewsyyF + 68 8 SwiftUI 0x00000001ddb40358 $s7SwiftUI14_UIHostingViewC14layoutSubviewsyyFTo + 32 9 UIKitCore 0x0000000185642d34 block_destroy_helper.13 + 10136 10 UIKitCore 0x00000001856430c8 block_destroy_helper.13 + 11052 11 UIKitCore 0x00000001869d6ff4 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 2656 12 QuartzCore 0x000000018c8fd194 _ZN2CA5Layer15perform_update_EPS0_P7CALayerjNS_17LayerUpdateReasonEPNS_11TransactionE + 452 13 QuartzCore 0x000000018c8fc9e4 _ZN2CA5Layer17update_if_needed_EPNS_11TransactionENS_17LayerUpdateReasonE + 600 14 QuartzCore 0x000000018c908674 _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 152 15 QuartzCore 0x000000018c81d914 _ZN2CA7Context18commit_transactionEPNS_11TransactionEdPd + 544 16 QuartzCore 0x000000018c84da48 _ZN2CA11Transaction6commitEv + 636 17 QuartzCore 0x000000018c89ea8c _ZL21CAImageProviderThreadPjb + 1004 18 libdispatch.dylib 0x00000001033d59dc _dispatch_client_callout + 12 19 libdispatch.dylib 0x00000001033bf728 _dispatch_continuation_pop + 740 20 libdispatch.dylib 0x00000001033f3344 _dispatch_async_redirect_invoke + 700 21 libdispatch.dylib 0x00000001033cf470 _dispatch_root_queue_drain + 356 22 libdispatch.dylib 0x00000001033cffc4 _dispatch_worker_thread2 + 272 23 libsystem_pthread.dylib 0x0000000103276b50 _pthread_wqthread + 228 24 libsystem_pthread.dylib 0x000000010327598c start_wqthread + 8 ) libc++abi: terminating due to uncaught exception of type NSException
Topic: UI Frameworks SubTopic: UIKit
2
0
166
4d
MapKit in SwiftUI
Anyone worked with MapKit's MapCameraPosition in SwiftUI? I'm building a navigation app and ran into a limitation I can't find a clean solution for when using .userLocation(followsHeading: true) MapKit takes full control of the camera, smooth heading tracking, follows the user automatically. Perfect. But there's no way to set a custom pitch (tilt) on it. The only initializer available is... .userLocation(followsHeading: true, fallback: .automatic) No pitch, no distance parameters.... The workaround I found is setting .camera(MapCamera(..., pitch: 60)) first, waiting 200ms, then switching to .userLocation(followsHeading: true), MapKit inherits the pitch from the rendered camera state before handing off to user tracking.... It works, but it's clearly exploiting an undocumented behaviour in MapKit's state machine rather than a proper API Has anyone found a cleaner way to achieve this? Or is UIViewRepresentable wrapping MKMapView the only proper solution? It would be awesome to have something like this cameraPosition = .userLocation( followsHeading: true, pitch: 60, distance: 800, fallback: .automatic )
1
0
117
4d
Left navigation bar items become invisible after rotating device and presenting detail view in split view
A user of my app, whose main view is a split view, reported an issue which causes the left navigation bar items to disappear without apparent reason if they rotate the device and later show the detail view, preventing them from using the back button to show the root view again. Am I doing something wrong or is it a bug? I can reproduce the issue with the following steps: Create a new document-based iOS app (as it uses scenes by default, as opposed to a regular app). Paste the code below. In the target build settings, delete "Launch Screen Interface File Base Name" and set "Launch Screen (Generation)" to YES. Without this step, for some reason, the issue doesn't happen. Launch the app in iPhone Simulator. Tap the top left button to show the root view, then the “detail” button to show the detail view. The left navigation bar button is still visible. Rotate the Simulator window right, then left again. Tap the top left button to show the root view, then the “detail” button to show the detail view. Now the left navigation bar button is invisible. Rotating the device right and left again solves the issue. I filed FB22363118. class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { window = UIWindow(windowScene: scene as! UIWindowScene) let split = SplitViewController() window!.rootViewController = split window!.makeKeyAndVisible() split.showDetail() } } class SplitViewController: UISplitViewController, UISplitViewControllerDelegate { var detailNavigationViewController: UINavigationController! init() { super.init(nibName: nil, bundle: nil) detailNavigationViewController = UINavigationController(rootViewController: DetailViewController()) viewControllers = [UINavigationController(rootViewController: RootViewController())] } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } func showDetail() { showDetailViewController(detailNavigationViewController, sender: nil) } func showRoot() { (viewControllers.first as? UINavigationController)?.popViewController(animated: true) } } class RootViewController: UIViewController { override func loadView() { navigationItem.title = "root" let button = UIButton(primaryAction: UIAction(handler: { [self] _ in (splitViewController as! SplitViewController).showDetail() })) button.setTitle("detail", for: .normal) view = button } } class DetailViewController: UIViewController { override func loadView() { navigationItem.title = "detail" view = UIView() registerForTraitChanges([UITraitHorizontalSizeClass.self]) { (self: Self, previousTraitCollection) in if previousTraitCollection.horizontalSizeClass != self.traitCollection.horizontalSizeClass { self.updateBarButtons() } } updateBarButtons() } private func updateBarButtons() { navigationItem.leftBarButtonItem = UIBarButtonItem(primaryAction: UIAction(image: UIImage(systemName: "sidebar.leading")) { [self] _ in (self.splitViewController as! SplitViewController).showRoot() }) navigationItem.rightBarButtonItem = UIBarButtonItem(title: "right") } }
Topic: UI Frameworks SubTopic: UIKit Tags:
0
0
51
4d
NSBrowser -deselectAll: broken on macOS Tahoe 26.4
So if I have a selection in NSBrowser. I hit Option+Command+A to invoke "Deselect" the selection in the parent for the last column drops its selections, as expected. But the column doesn't drop off the browser. The delegate method (void)browser:(NSBrowser *)browser didChangeLastColumn:(NSInteger)oldLastColumn toColumn:(NSInteger)column NS_SWIFT_UI_ACTOR; Never fires (since the column isn't dropped off). But we have. dangling last column with no selection in the previous column. Now if there's enough room for me to deselect by clicking the background, the last column drops off, as expected. This seems to be fairly new? Anyone else experiencing this? These 26point updates seem to keep punching me in the face. And yes. deselect all seems somewhat broken in Column view in the Finder as well, but in a seemingly different way. In Finder it just seems to change the selection color like it deactivated the window but doesn't drop the selection. For me, the selection IS dropped but the column remains visible. Maybe they are using Cocoa bindings or something that resyncs the selection after the mess up. I dk.
0
0
124
5d
Wrong position of searchable component on first render
Hey all, I found a weird behaviour with the searchable component. I created a custom bottom nav bar (because I have custom design in my app) to switch between screens. On one screen I display a List component with the searchable component. Whenever I enter the search screen the first time, the searchable component is displayed at the bottom. This is wrong. It should be displayed at the top under the navigationTitle. When I enter the screen a second time, everything is correct. This behaviour can be reproduced on all iOS 26 versions on the simulator and on a physical device with debug and release build. On iOS 18 everything works fine. Steps to reproduce: Cold start of the app Click on Search TabBarIcon (searchable wrong location) Click on Home TabBarIcon Click on Search TabBarIcon (searchable correct location) Simple code example: import SwiftUI struct ContentView: View { @State var selectedTab: Page = Page.main var body: some View { NavigationStack { ZStack { VStack { switch selectedTab { case .main: MainView() case .search: SearchView() } } VStack { Spacer() VStack(spacing: 0) { HStack(spacing: 0) { TabBarIcon(iconName: "house", selected: selectedTab == .main, displayName: "Home") .onTapGesture { selectedTab = .main } TabBarIcon(iconName: "magnifyingglass", selected: selectedTab == .search, displayName: "Search") .onTapGesture { selectedTab = .search } } .frame(maxWidth: .infinity) .frame(height: 55) .background(Color.gray) } .ignoresSafeArea(.all, edges: .bottom) } } } } } struct TabBarIcon: View { let iconName: String let selected: Bool let displayName: String var body: some View { ZStack { VStack { Image(systemName: iconName) .resizable() .renderingMode(.template) .aspectRatio(contentMode: .fit) .foregroundColor(Color.black) .frame(width: 22, height: 22) Text(displayName) .font(Font.system(size: 10)) } } .frame(maxWidth: .infinity) } } enum Page { case main case search } struct MainView: View { var body: some View { VStack { Image(systemName: "globe") .imageScale(.large) .foregroundStyle(.tint) Text("Hello, world!") } .padding() .navigationTitle("Home") } } struct SearchView: View { @State private var searchText = "" let items = [ "Apple", "Banana", "Pear", "Strawberry", "Orange", "Peach", "Grape", "Mango" ] var filteredItems: [String] { if searchText.isEmpty { return items } else { return items.filter { $0.localizedCaseInsensitiveContains(searchText) } } } var body: some View { List(filteredItems, id: \.self) { item in Text(item) } .navigationTitle("Fruits") .searchable(text: $searchText, placement: .navigationBarDrawer(displayMode: .always), prompt: "Search") } }
4
0
245
5d
NavigationSplitView no longer pops back to the root view when selection = nil in iOS 26.4 (with a nested TabView)
In iOS 26.4 (iPhone, not iPad), when a NavigationSplitView is combined with a nested TabView, it no longer pops back to the root sidebar view when the List selection is set to nil. This has been working fine for at least a few years, but has just stopped working in iOS 26.4. Here's a minimal working example: import SwiftUI struct ContentView: View { @State var articles: [Article] = [Article(articleTitle: "Dog"), Article(articleTitle: "Cat"), Article(articleTitle: "Mouse")] @State private var selectedArticle: Article? = nil var body: some View { NavigationSplitView { TabView { Tab { List(articles, selection: $selectedArticle) { article in Button { selectedArticle = article } label: { Text(article.title) } } } label: { Label("Explore", systemImage: "binoculars") } } } detail: { Group { if let selectedArticle { Text(selectedArticle.title) } else { Text("No selected article") } } .navigationBarBackButtonHidden(true) .toolbar { ToolbarItem(placement: .topBarTrailing) { Button("Close", systemImage: "xmark") { selectedArticle = nil } } } } } } struct Article: Identifiable, Hashable { let id: String let title: String init(articleTitle: String) { self.id = articleTitle self.title = articleTitle } } First, I'm aware that nesting a TabView inside a NavigationSplitView is frowned upon: Apple seems to prefer NavigationSplitView nested inside a Tab. However, for my app, that leads to a very confusing user experience. Users quickly get lost because they end up with different articles open in different tabs and it doesn't align well with my core distinction between two "modes": article selection mode and article reading mode. When the user is in article selection mode (sidebar view), they can pick between different ways of selecting an article (Explore, Bookmarks, History, Search), which are implemented as "tabs". When they pick an article from any tab they jump into article reading mode (the detail view). Second, I'm using .navigationBarBackButtonHidden(true) to remove the auto back button that pops back to the sidebar view. This button does still work in iOS 26.4, even with the nested TabView. However, I can't use the auto back button because my detail view is actually a WebView with its own back/forward logic and UI. Therefore, I need a separate close button to exit from the detail view. My close button sets selectedArticle to nil, which (pre-iOS 26.4) would trigger the NavigationSplitView to pop back to the sidebar view. For some reason, in iOS 26.4 the NavigationSplitView doesn't seem to bind correctly to the List's selection parameter, specifically when there's a TabView nested between them. Or, rather, it binds, but fails to pop back when selection becomes nil. One option is to replace NavigationSplitView with NavigationStack (on iPhone). NavigationStack still works with a nested TabView, but it creates other downstream issues for me (as well as forcing me to branch for iPhone and iPad), so I'd prefer to continue using NavigationSplitView. Does anyone have any ideas about how to work around this problem? Is there some way of explicitly telling NavigationSplitView to pop back to the sidebar view on iPhone? (I've tried setting the column visibility but nothing seems to work). Thanks for any help!
0
0
33
5d
onDisappear not called when closing a document on macOS (Designed for iPad), works on iPad
When running a SwiftUI DocumentGroup app on macOS designed for iPad, onDisappear is not called when closing a document, and deinit of state objects owned by a ContentView is not invoked. This behavior works as expected on iPad. @main struct MyApp: App { var body: some Scene { DocumentGroup(newDocument: MyDocument()) { file in ContentView(document: file.$document) .onDisappear { print("This isn't called on macOS Designed For iPad, but is on iPad when closing a document.") } } } } It is my understanding that for a macOS designed for iPad these lifecycle events would behave the same - otherwise there appears to be no way to detect if a document has closed on macOS.
1
0
74
6d
UITabBarController crashes when editing the items
I'm using one UITabBarController which leads to 6 NavigationController. Therefore the user will get 4 icons displayed and one icon with three points to see the rest of the Navigation Controller. If the user now tries to edit the list and moves one item from the hidden area towards the TabBar at the bottom, the App crashes with the error: Exception NSException * "Can't add self as subview" 0x0000600000d16040 I can see this effect at least on both my apps. If the same compilation is run on a older iOS version, there is no crash. Is there anything I have to take care of the configuration of the TabBar, when it comes to iOS26?
Topic: UI Frameworks SubTopic: UIKit
18
1
847
6d
iPadOS 26 Crash when num pad with floating keyboard in presented view
Build the sample code below, type something in the textfield (make sure the num pad is a popup and that the text keyboard is floating). And tap multiple times outside of the textfield in the sheet. That will lead to the crash: *** Terminating app due to uncaught exception 'NSGenericException', reason: 'Unable to activate constraint with anchors <NSLayoutYAxisAnchor:0x60000179cec0 "UIView:0x103c52fe0.top"> and <NSLayoutYAxisAnchor:0x6000017e0800 "_UIRemoteKeyboardPlaceholderView:0x103baa240.bottom"> because they have no common ancestor. Does the constraint or its anchors reference items in different view hierarchies? That's illegal.' terminating due to uncaught exception of type NSException CoreSimulator 1051.17.8 - Device: iPad Pro 13-inch (M5) (655000D7-41BC-4B13-BD07-BBA80D892E97) - Runtime: iOS 26.2 (23C54) - DeviceType: iPad Pro 13-inch (M5) Does anyone have the slightest idea of a workaround? I can't find one. import SwiftUI struct ContentView: View { var body: some View { Text("Content") .sheet(isPresented: .constant(true)) { PresentedView() } } } struct PresentedView: View { @State private var text = "" var body: some View { ScrollView { VStack { TextField("Placeholder", text: $text) .keyboardType(.numberPad) } .padding(80) } } } See here for discussion and video to reproduce: https://stackoverflow.com/questions/79905933/ipados-26-crash-when-floating-num-pad-in-presented-view
0
1
21
1w
Localization in Swift macOS console Apps.
Is it possible to build localization into console apps, developed in SwiftUI in Xcode26. I have created a catalog, (.xcstrings file) with an English and fr-CA string. I have tried to display the French text without success. I am using the console app to test a package which also has English/French text. English text works fine in both package and the console main, but I cannot generate the French. From what I can discover so far it's not possible without bundling it as a .app, (console app). Looking for anyone who has crossed this bridge.
Replies
7
Boosts
0
Views
275
Activity
2d
My app doesn't respond on iPhone Air iOS 26.1.
My app doesn't respond on iPhone Air iOS 26.1. After startup, my app shows the main view with a tab bar controller containing 4 navigation controllers. However, when a second-level view controller is pushed onto any navigation controller, the UI freezes and becomes unresponsive. The iPhone simulator running iOS 26.1 exhibits the same problem. The debug profile shows CPU usage at 100%. However, other devices and simulators do not have this problem.
Replies
7
Boosts
3
Views
539
Activity
3d
PDFView left-anchors to window edge instead of centering between sidebar and inspector (macOS Tahoe)
I'm building a document viewer on macOS Tahoe with a 3-column NSSplitViewController (sidebar | detail | inspector), trying to replicate how Preview displays PDFs with the page centered in the visible gap between the panels, with content bleeding under them when panning or zooming. I'm using the approach from Build an AppKit app with the new design (WWDC25): detailItem.automaticallyAdjustsSafeAreaInsets = true safeAreaInsets reports the correct values (e.g. left: 208, right: 240), and the frame does extend under both panels. But PDFView with autoScales = true anchors the page to the left edge of the window instead of centering it in the visible gap between the sidebar and inspector. I can get the page to center correctly by constraining PDFView to view.safeAreaLayoutGuide, but then content no longer extends under the panels when panning or zooming, which defeats the whole purpose. What's the correct way to center PDFView content within the visible gap while keeping the frame full-width so content bleeds under the panels? I've attached pictures of how Preview does it.
Topic: UI Frameworks SubTopic: AppKit
Replies
0
Boosts
0
Views
60
Activity
3d
SwiftUI Chart scrolling on macOS
I'm running macOS 26.3 and using Xcode 26.4. I'm trying to create a SwiftUI Chart that can scroll horizontally. In the SwiftUI Preview, and also running the app on macOS, the chart displays a scrollbar, but the scrollbar does not respond to mouse interaction (dragging the scrollbar, or clicking in the gutters on either side of the scrollbar). Here's the sample code: import SwiftUI import Charts private struct DataPoint: Identifiable { let id: Int let x: Double let value: Double } struct ContentView: View { private let points: [DataPoint] = (0..<60).map { index in let wave = sin(Double(index) * 0.28) * 18 let trend = Double(index) * 0.35 return DataPoint(id: index, x: Double(index), value: 60 + wave + trend) } var body: some View { Chart(points) { point in BarMark( x: .value("Data Point", point.x), y: .value("Value", point.value) ) .foregroundStyle(.blue.gradient) } .chartScrollableAxes(.horizontal) // Doesn't work: // .scrollIndicators(.hidden) // .never also does not work .chartXVisibleDomain(length: 20) .padding() } } #Preview { ContentView() }
Replies
3
Boosts
0
Views
105
Activity
3d
UIScrollView Fast Scrolling have it scroll to the beginning when i press dpad to left while vertical scrolling
I'm triaging the issue with the fast scrolling on UIScrollView and I'm really upset how little to no info this component is on the internet. Like i disabled scrolling and yet after holding the dpad down to scroll downward eventually the fast scroll mechanism is used. The issue I have is that I have a setup where the scrollview scrolling is disabled and whenever cells are focused it'll scroll to the cell's position for that cells to focused on top left side of the scrollview. I start off with the cell placed at position x of 1000. I scroll down enough to enable fast scrolling. While fast scrolling vertically, i press left a couple of time and it somewhat scroll horizontally. Actual scrollView index is suddenly placed to x:0 instead of let say x:950-1000 Expected should be scrolled to the left of cell at position x 1000. Attached the stack trace and the log showcasing it and run it on simulator tvos 26.2. Initial properties of the scrollview we set up scroll = [UIScrollView new]; scroll.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; scroll.automaticallyAdjustsScrollIndicatorInsets = false; [scroll setDirectionalLockEnabled:TRUE]; [scroll setContentInset:UIEdgeInsetsMake(0, 0, 0, 0)]; scroll.bounces = FALSE; scroll.delaysContentTouches = FALSE; scroll.showsVerticalScrollIndicator = FALSE; scroll.showsHorizontalScrollIndicator = FALSE; The plan for me at least is to somehow disable the horizontal scrolling interaction of it when fast scrolling is enabled, without accessing the private components of it.
Replies
0
Boosts
0
Views
53
Activity
3d
NavigationLink selection in DisclosureGroup not working with .draggable modifier
NavigationLink selection in DisclosureGroup not working with .draggable modifier This was recently also posted here: https://stackoverflow.com/questions/79914290/ I am playing around with a tree data structure with folders and entries.I would like to add dragging of entries and folders between folders, using .draggable and dropDestination. In my current code, dragging works, but selection of entries no longer works, except if I click outside of the Text If I comment out .draggable(subfolder.name) in func FolderRow(), selection works as expected. How can I make sure both selection and drag and drop works for both folders and entries? I also tried using Transferable and Codable, but I get the same result. Here is an MRE: import SwiftData import SwiftUI @Model final class Folder { @Attribute(.unique) var name: String // Parent var parentFolder: Folder? // Child folders @Relationship(deleteRule: .cascade, inverse: \Folder.parentFolder) var subfolders: [Folder] = [] // Leaf entries @Relationship(deleteRule: .cascade, inverse: \Entry.folder) var entries: [Entry] = [] init(name: String, parentFolder: Folder? = nil) { self.name = name self.parentFolder = parentFolder } } @Model final class Entry { @Attribute(.unique) var name: String var detail: String var folder: Folder? // recursive relationship init(name: String, detail: String) { self.name = name self.detail = detail } } @main struct TestMacApp: App { var body: some Scene { WindowGroup { SidebarView() .modelContainer(for: Folder.self) } } } struct SidebarView: View { @Environment(\.modelContext) private var context @Query(filter: #Predicate<Folder> { $0.parentFolder == nil }) private var rootFolders: [Folder] var body: some View { NavigationSplitView { List { ForEach(rootFolders) { folder in FolderRow(folder: folder) .draggable(folder.name) } } } detail: { Text("detail") } .onAppear { seed() } } } struct FolderRow: View { @Environment(\.modelContext) private var context var folder: Folder @State private var isExpanded: Bool = true var body: some View { DisclosureGroup(isExpanded: $isExpanded) { // Subfolders ForEach(folder.subfolders) { subfolder in FolderRow(folder: subfolder) .draggable(subfolder.name) // disabling this line fixes the selection } // Entries (leaf nodes) ForEach(folder.entries) { entry in NavigationLink(destination: EntryDetail(entry: entry)) { EntryRow(entry: entry) } .draggable(entry.name) } } label: { Label(folder.name, systemImage: "folder") } .dropDestination(for: String.self) { names, _ in return handleDrop(of: names) } } } struct EntryRow: View { var entry: Entry var body: some View { Text(entry.name) } } struct EntryDetail: View { var entry: Entry var body: some View { Text(entry.detail) } } extension FolderRow { private func handleDrop(of names: [String]) -> Bool { do { for name in names { if let droppedEntry = try context.fetchFilteredModel(filter: #Predicate<Entry> { x in x.name == name }) { droppedEntry.folder = folder print("dropped \(droppedEntry.name) on \(folder.name)") } else if let droppedFolder = try context.fetchFilteredModel(filter: #Predicate<Folder> { x in x.name == name }) { if droppedFolder.parentFolder != nil && droppedFolder != folder { droppedFolder.parentFolder = folder print("dropped \(droppedFolder.name) on \(folder.name)") } } } return true } catch { debugPrint(error.localizedDescription) return false } } } extension SidebarView { private func seed() { do { // delete current models for folder: Folder in try context.fetchAllModels() { context.delete(folder) } try context.save() let rootFolder = Folder(name: "Root") let entry1 = Entry(name: "One", detail: "Detail One") let entry2 = Entry(name: "Two", detail: "Detail Two") rootFolder.entries.append(contentsOf: [entry1, entry2]) let subFolder1 = Folder(name: "Sub1", parentFolder: rootFolder) let entry3 = Entry(name: "Three", detail: "Detail Three") let entry4 = Entry(name: "Four", detail: "Detail Four") subFolder1.entries.append(contentsOf: [entry3, entry4]) let subFolder2 = Folder(name: "Sub2", parentFolder: rootFolder) let entry5 = Entry(name: "Five", detail: "Detail Five") let entry6 = Entry(name: "Six", detail: "Detail Six") subFolder2.entries.append(contentsOf: [entry5, entry6]) context.insert(rootFolder) } catch { debugPrint(error) } } } extension ModelContext { // convenience methods func fetchAllModels<M>() throws -> [M] where M: PersistentModel { let fetchDescriptor = FetchDescriptor<M>() return try fetch(fetchDescriptor) } func fetchFilteredModels<M>(filter: Predicate<M>) throws -> [M] where M: PersistentModel { let fetchDescriptor = FetchDescriptor<M>(predicate: filter) return try fetch(fetchDescriptor) } func fetchFilteredModel<M>(filter: Predicate<M>) throws -> M? where M: PersistentModel { return try fetchFilteredModels(filter: filter).first } }
Topic: UI Frameworks SubTopic: SwiftUI
Replies
1
Boosts
0
Views
168
Activity
3d
Combining NavigationSplitView and TabView in iOS 18
Hi folks, I've used a NavigationSplitView within one of the tabs of my app since iOS 16, but with the new styling in iOS 18 the toolbar region looks odd. In other tabs using e.g. simple stacks, the toolbar buttons are horizontally in line with the new tab picker, but with NavigationSplitView, the toolbar leaves a lot of empty space at the top (see below). Is there anything I can do to adjust this, or alternatively, continue to use the old style? Thanks!
Replies
13
Boosts
3
Views
3.0k
Activity
3d
Migrating to the UIKit scene-based life cycle
I got this debuglog in Xcode26. "UIScene lifecycle will soon be required. Failure to adopt will result in an assert in the future." I haven't included any UIScene lifecycle code. I read the article on TN3187: Migrating to the UIKit scene-based life cycle. Does this mean that when iOS27 iPhone is released, the app will crash after startup? If Xcode26/iOS27 crashes, is there a quick fix I can use?
Topic: UI Frameworks SubTopic: UIKit
Replies
2
Boosts
0
Views
160
Activity
3d
Scene resizing on iPad breaks UIPageViewController's setViewControllers
The following is verbatim of a feedback report (FB22367951) I submitted, shared here as someone else might be interested to see it. I have reproduced this bug on iPadOS 26.3.1 (a) and 26.4. During scene resizing on iPad, UIPageViewController's setViewControllers method fails to do its work. The navigation starts and for a brief moment you can see the new view controller coming from the expected direction, but shortly after it fails and stays on the same [current] view controller. It doesn't even call the completion handler when it fails. When the navigation succeeds (due to not resizing a scene during the navigation) after previously failing at least once, the completion handler is sometimes called more than once. I have created a demo project, which I have pushed to this repo: https://github.com/galijot/SceneResize-Breaks-UIPageViewController I have also attached a zip of the project to this report.
Replies
0
Boosts
0
Views
36
Activity
3d
On macOS Settings window navigation bar item is in the center
Hi, Overview I have a Mac app with a settings window. When I add a button it is added to the center. I want it on the trailing edge, I even tried adding it as confirmationAction but doesn’t work. Screenshot Feedback FB21374186 Steps to reproduce Run the project on mac Open the app's settings by pressing ⌘ , Notice that the Save button is in the center instead of the trailing edge Code App import SwiftUI @main struct SettingsToolbarButtonBugApp: App { var body: some Scene { WindowGroup { ContentView() } Settings { SettingsView() .frame(width: 300, height: 400) } } } SettingsView import SwiftUI struct SettingsView: View { var body: some View { NavigationStack { Form { Text("Settings window") } .toolbar { ToolbarItem(placement: .confirmationAction) { // Save button is the center instead of trailing edge Button("Save") {} } } .navigationTitle("Settings") } } }
Topic: UI Frameworks SubTopic: SwiftUI
Replies
1
Boosts
0
Views
176
Activity
4d
UIView + CATiledLayer + SwiftUI Hosting + iOS 26 = Crash?
Our app uses a UIView backed by a CATiledLayer that is embedded in a UIScrollView, to represent a large document viewer. (PDF data, actually.) It needs to be big - far too big to allocate a single layer, and it needs to be able to reveal more detail as you zoom in. This is the exact use case for a CATiledLayer. CATiledLayer does its drawing on a background thread, as you know, and we've always taken care to make our draw method thread-safe. It has worked great for us, for over a decade now. However, starting with iOS 26, we've been having some surprising crashes. It looks like our CATiledLayer (I think?) is trying to trigger a layout on the background thread as well. This is frustrating because it doesn't have any subviews or sublayers - there's no reason for it. I'm suspecting the CATiledLayer because it does its drawing on a thread, so maybe it would also do other things there, but honestly, I'm not sure - it's hard to tell. Here's the crash. Normally with a crash like this, the solution is to bounce your layout call out to the main thread, but in our case, I'm not the one calling the layout function. The system (Core Animation) is doing it, and I can't figure out what I might be doing that is triggering it. Everything I am doing is on the main thread, and there's none of my code in this stack trace. It's possible this may have something to do with the SwiftUI hosting view, as well? There's definitely one of those involved here - our custom PDF viewer is embedded in one. (That's another reason to suspect the CATiledLayer - whatever is crashing here is in a SwiftUI hosting view, and the PDF viewer is just about the only UIKit on the screen, here, embedded in a hosting view.) I also have a test app that is pure UIKit, where I have not been able to reproduce the crash. I've tried subclassing CATiledLayer and having an empty implementation of updateSublayers, and some other, similar hacks along those lines, but nothing I do seems to help. I'm tempted to try moving from CATiledLayer to simple UIViews, and tiling those myself, but that's a lot of work. I want to be sure there's not some other solution before I try something like that. Is CATiledLayer still a supported mechanism or should I be moving away from it? If it is something entirely different that is crashing here, I don't want to do a bunch of rework of the PDF viewer only to end up with the same results. It really smells like a UIKit bug to me, or at least UIKit making some concurrency assumptions that CATiledLayer is breaking. But all I can really do is guess. *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Modifications to the layout engine must not be performed from a background thread after it has been accessed from the main thread.' *** First throw call stack: ( 0 CoreFoundation 0x00000001804f7348 __exceptionPreprocess + 172 1 libobjc.A.dylib 0x000000018009c094 objc_exception_throw + 72 2 CoreAutoLayout 0x000000022d3cc13c __36-[NSISEngine rebuildFromConstraints]_block_invoke + 0 3 CoreAutoLayout 0x000000022d3cbee0 -[NSISEngine _optimizeWithoutRebuilding] + 68 4 CoreAutoLayout 0x000000022d3cbe14 -[NSISEngine optimize] + 92 5 CoreAutoLayout 0x000000022d3c8744 -[NSISEngine performPendingChangeNotifications] + 100 6 UIKitCore 0x00000001869c7e7c -[UIView(Hierarchy) layoutSubviews] + 132 7 SwiftUI 0x00000001ddb40318 $s7SwiftUI14_UIHostingViewC14layoutSubviewsyyF + 68 8 SwiftUI 0x00000001ddb40358 $s7SwiftUI14_UIHostingViewC14layoutSubviewsyyFTo + 32 9 UIKitCore 0x0000000185642d34 block_destroy_helper.13 + 10136 10 UIKitCore 0x00000001856430c8 block_destroy_helper.13 + 11052 11 UIKitCore 0x00000001869d6ff4 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 2656 12 QuartzCore 0x000000018c8fd194 _ZN2CA5Layer15perform_update_EPS0_P7CALayerjNS_17LayerUpdateReasonEPNS_11TransactionE + 452 13 QuartzCore 0x000000018c8fc9e4 _ZN2CA5Layer17update_if_needed_EPNS_11TransactionENS_17LayerUpdateReasonE + 600 14 QuartzCore 0x000000018c908674 _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 152 15 QuartzCore 0x000000018c81d914 _ZN2CA7Context18commit_transactionEPNS_11TransactionEdPd + 544 16 QuartzCore 0x000000018c84da48 _ZN2CA11Transaction6commitEv + 636 17 QuartzCore 0x000000018c89ea8c _ZL21CAImageProviderThreadPjb + 1004 18 libdispatch.dylib 0x00000001033d59dc _dispatch_client_callout + 12 19 libdispatch.dylib 0x00000001033bf728 _dispatch_continuation_pop + 740 20 libdispatch.dylib 0x00000001033f3344 _dispatch_async_redirect_invoke + 700 21 libdispatch.dylib 0x00000001033cf470 _dispatch_root_queue_drain + 356 22 libdispatch.dylib 0x00000001033cffc4 _dispatch_worker_thread2 + 272 23 libsystem_pthread.dylib 0x0000000103276b50 _pthread_wqthread + 228 24 libsystem_pthread.dylib 0x000000010327598c start_wqthread + 8 ) libc++abi: terminating due to uncaught exception of type NSException
Topic: UI Frameworks SubTopic: UIKit
Replies
2
Boosts
0
Views
166
Activity
4d
MapKit in SwiftUI
Anyone worked with MapKit's MapCameraPosition in SwiftUI? I'm building a navigation app and ran into a limitation I can't find a clean solution for when using .userLocation(followsHeading: true) MapKit takes full control of the camera, smooth heading tracking, follows the user automatically. Perfect. But there's no way to set a custom pitch (tilt) on it. The only initializer available is... .userLocation(followsHeading: true, fallback: .automatic) No pitch, no distance parameters.... The workaround I found is setting .camera(MapCamera(..., pitch: 60)) first, waiting 200ms, then switching to .userLocation(followsHeading: true), MapKit inherits the pitch from the rendered camera state before handing off to user tracking.... It works, but it's clearly exploiting an undocumented behaviour in MapKit's state machine rather than a proper API Has anyone found a cleaner way to achieve this? Or is UIViewRepresentable wrapping MKMapView the only proper solution? It would be awesome to have something like this cameraPosition = .userLocation( followsHeading: true, pitch: 60, distance: 800, fallback: .automatic )
Replies
1
Boosts
0
Views
117
Activity
4d
Left navigation bar items become invisible after rotating device and presenting detail view in split view
A user of my app, whose main view is a split view, reported an issue which causes the left navigation bar items to disappear without apparent reason if they rotate the device and later show the detail view, preventing them from using the back button to show the root view again. Am I doing something wrong or is it a bug? I can reproduce the issue with the following steps: Create a new document-based iOS app (as it uses scenes by default, as opposed to a regular app). Paste the code below. In the target build settings, delete "Launch Screen Interface File Base Name" and set "Launch Screen (Generation)" to YES. Without this step, for some reason, the issue doesn't happen. Launch the app in iPhone Simulator. Tap the top left button to show the root view, then the “detail” button to show the detail view. The left navigation bar button is still visible. Rotate the Simulator window right, then left again. Tap the top left button to show the root view, then the “detail” button to show the detail view. Now the left navigation bar button is invisible. Rotating the device right and left again solves the issue. I filed FB22363118. class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { window = UIWindow(windowScene: scene as! UIWindowScene) let split = SplitViewController() window!.rootViewController = split window!.makeKeyAndVisible() split.showDetail() } } class SplitViewController: UISplitViewController, UISplitViewControllerDelegate { var detailNavigationViewController: UINavigationController! init() { super.init(nibName: nil, bundle: nil) detailNavigationViewController = UINavigationController(rootViewController: DetailViewController()) viewControllers = [UINavigationController(rootViewController: RootViewController())] } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } func showDetail() { showDetailViewController(detailNavigationViewController, sender: nil) } func showRoot() { (viewControllers.first as? UINavigationController)?.popViewController(animated: true) } } class RootViewController: UIViewController { override func loadView() { navigationItem.title = "root" let button = UIButton(primaryAction: UIAction(handler: { [self] _ in (splitViewController as! SplitViewController).showDetail() })) button.setTitle("detail", for: .normal) view = button } } class DetailViewController: UIViewController { override func loadView() { navigationItem.title = "detail" view = UIView() registerForTraitChanges([UITraitHorizontalSizeClass.self]) { (self: Self, previousTraitCollection) in if previousTraitCollection.horizontalSizeClass != self.traitCollection.horizontalSizeClass { self.updateBarButtons() } } updateBarButtons() } private func updateBarButtons() { navigationItem.leftBarButtonItem = UIBarButtonItem(primaryAction: UIAction(image: UIImage(systemName: "sidebar.leading")) { [self] _ in (self.splitViewController as! SplitViewController).showRoot() }) navigationItem.rightBarButtonItem = UIBarButtonItem(title: "right") } }
Topic: UI Frameworks SubTopic: UIKit Tags:
Replies
0
Boosts
0
Views
51
Activity
4d
NSBrowser -deselectAll: broken on macOS Tahoe 26.4
So if I have a selection in NSBrowser. I hit Option+Command+A to invoke "Deselect" the selection in the parent for the last column drops its selections, as expected. But the column doesn't drop off the browser. The delegate method (void)browser:(NSBrowser *)browser didChangeLastColumn:(NSInteger)oldLastColumn toColumn:(NSInteger)column NS_SWIFT_UI_ACTOR; Never fires (since the column isn't dropped off). But we have. dangling last column with no selection in the previous column. Now if there's enough room for me to deselect by clicking the background, the last column drops off, as expected. This seems to be fairly new? Anyone else experiencing this? These 26point updates seem to keep punching me in the face. And yes. deselect all seems somewhat broken in Column view in the Finder as well, but in a seemingly different way. In Finder it just seems to change the selection color like it deactivated the window but doesn't drop the selection. For me, the selection IS dropped but the column remains visible. Maybe they are using Cocoa bindings or something that resyncs the selection after the mess up. I dk.
Replies
0
Boosts
0
Views
124
Activity
5d
Wrong position of searchable component on first render
Hey all, I found a weird behaviour with the searchable component. I created a custom bottom nav bar (because I have custom design in my app) to switch between screens. On one screen I display a List component with the searchable component. Whenever I enter the search screen the first time, the searchable component is displayed at the bottom. This is wrong. It should be displayed at the top under the navigationTitle. When I enter the screen a second time, everything is correct. This behaviour can be reproduced on all iOS 26 versions on the simulator and on a physical device with debug and release build. On iOS 18 everything works fine. Steps to reproduce: Cold start of the app Click on Search TabBarIcon (searchable wrong location) Click on Home TabBarIcon Click on Search TabBarIcon (searchable correct location) Simple code example: import SwiftUI struct ContentView: View { @State var selectedTab: Page = Page.main var body: some View { NavigationStack { ZStack { VStack { switch selectedTab { case .main: MainView() case .search: SearchView() } } VStack { Spacer() VStack(spacing: 0) { HStack(spacing: 0) { TabBarIcon(iconName: "house", selected: selectedTab == .main, displayName: "Home") .onTapGesture { selectedTab = .main } TabBarIcon(iconName: "magnifyingglass", selected: selectedTab == .search, displayName: "Search") .onTapGesture { selectedTab = .search } } .frame(maxWidth: .infinity) .frame(height: 55) .background(Color.gray) } .ignoresSafeArea(.all, edges: .bottom) } } } } } struct TabBarIcon: View { let iconName: String let selected: Bool let displayName: String var body: some View { ZStack { VStack { Image(systemName: iconName) .resizable() .renderingMode(.template) .aspectRatio(contentMode: .fit) .foregroundColor(Color.black) .frame(width: 22, height: 22) Text(displayName) .font(Font.system(size: 10)) } } .frame(maxWidth: .infinity) } } enum Page { case main case search } struct MainView: View { var body: some View { VStack { Image(systemName: "globe") .imageScale(.large) .foregroundStyle(.tint) Text("Hello, world!") } .padding() .navigationTitle("Home") } } struct SearchView: View { @State private var searchText = "" let items = [ "Apple", "Banana", "Pear", "Strawberry", "Orange", "Peach", "Grape", "Mango" ] var filteredItems: [String] { if searchText.isEmpty { return items } else { return items.filter { $0.localizedCaseInsensitiveContains(searchText) } } } var body: some View { List(filteredItems, id: \.self) { item in Text(item) } .navigationTitle("Fruits") .searchable(text: $searchText, placement: .navigationBarDrawer(displayMode: .always), prompt: "Search") } }
Replies
4
Boosts
0
Views
245
Activity
5d
NavigationSplitView no longer pops back to the root view when selection = nil in iOS 26.4 (with a nested TabView)
In iOS 26.4 (iPhone, not iPad), when a NavigationSplitView is combined with a nested TabView, it no longer pops back to the root sidebar view when the List selection is set to nil. This has been working fine for at least a few years, but has just stopped working in iOS 26.4. Here's a minimal working example: import SwiftUI struct ContentView: View { @State var articles: [Article] = [Article(articleTitle: "Dog"), Article(articleTitle: "Cat"), Article(articleTitle: "Mouse")] @State private var selectedArticle: Article? = nil var body: some View { NavigationSplitView { TabView { Tab { List(articles, selection: $selectedArticle) { article in Button { selectedArticle = article } label: { Text(article.title) } } } label: { Label("Explore", systemImage: "binoculars") } } } detail: { Group { if let selectedArticle { Text(selectedArticle.title) } else { Text("No selected article") } } .navigationBarBackButtonHidden(true) .toolbar { ToolbarItem(placement: .topBarTrailing) { Button("Close", systemImage: "xmark") { selectedArticle = nil } } } } } } struct Article: Identifiable, Hashable { let id: String let title: String init(articleTitle: String) { self.id = articleTitle self.title = articleTitle } } First, I'm aware that nesting a TabView inside a NavigationSplitView is frowned upon: Apple seems to prefer NavigationSplitView nested inside a Tab. However, for my app, that leads to a very confusing user experience. Users quickly get lost because they end up with different articles open in different tabs and it doesn't align well with my core distinction between two "modes": article selection mode and article reading mode. When the user is in article selection mode (sidebar view), they can pick between different ways of selecting an article (Explore, Bookmarks, History, Search), which are implemented as "tabs". When they pick an article from any tab they jump into article reading mode (the detail view). Second, I'm using .navigationBarBackButtonHidden(true) to remove the auto back button that pops back to the sidebar view. This button does still work in iOS 26.4, even with the nested TabView. However, I can't use the auto back button because my detail view is actually a WebView with its own back/forward logic and UI. Therefore, I need a separate close button to exit from the detail view. My close button sets selectedArticle to nil, which (pre-iOS 26.4) would trigger the NavigationSplitView to pop back to the sidebar view. For some reason, in iOS 26.4 the NavigationSplitView doesn't seem to bind correctly to the List's selection parameter, specifically when there's a TabView nested between them. Or, rather, it binds, but fails to pop back when selection becomes nil. One option is to replace NavigationSplitView with NavigationStack (on iPhone). NavigationStack still works with a nested TabView, but it creates other downstream issues for me (as well as forcing me to branch for iPhone and iPad), so I'd prefer to continue using NavigationSplitView. Does anyone have any ideas about how to work around this problem? Is there some way of explicitly telling NavigationSplitView to pop back to the sidebar view on iPhone? (I've tried setting the column visibility but nothing seems to work). Thanks for any help!
Replies
0
Boosts
0
Views
33
Activity
5d
onDisappear not called when closing a document on macOS (Designed for iPad), works on iPad
When running a SwiftUI DocumentGroup app on macOS designed for iPad, onDisappear is not called when closing a document, and deinit of state objects owned by a ContentView is not invoked. This behavior works as expected on iPad. @main struct MyApp: App { var body: some Scene { DocumentGroup(newDocument: MyDocument()) { file in ContentView(document: file.$document) .onDisappear { print("This isn't called on macOS Designed For iPad, but is on iPad when closing a document.") } } } } It is my understanding that for a macOS designed for iPad these lifecycle events would behave the same - otherwise there appears to be no way to detect if a document has closed on macOS.
Replies
1
Boosts
0
Views
74
Activity
6d
UITabBarController crashes when editing the items
I'm using one UITabBarController which leads to 6 NavigationController. Therefore the user will get 4 icons displayed and one icon with three points to see the rest of the Navigation Controller. If the user now tries to edit the list and moves one item from the hidden area towards the TabBar at the bottom, the App crashes with the error: Exception NSException * "Can't add self as subview" 0x0000600000d16040 I can see this effect at least on both my apps. If the same compilation is run on a older iOS version, there is no crash. Is there anything I have to take care of the configuration of the TabBar, when it comes to iOS26?
Topic: UI Frameworks SubTopic: UIKit
Replies
18
Boosts
1
Views
847
Activity
6d
QLThumbnailGenerator macOS 26.4 No Longer Honors Users 'Folder Color' Preference When Making Icons for Folders
I use QLThumbnailGenerator to generate icons. After updating to macOS Tahoe 26.4 the folder color preference of the user is no longer respected. It just makes the icon default 'light blue.'
Replies
6
Boosts
0
Views
132
Activity
1w
iPadOS 26 Crash when num pad with floating keyboard in presented view
Build the sample code below, type something in the textfield (make sure the num pad is a popup and that the text keyboard is floating). And tap multiple times outside of the textfield in the sheet. That will lead to the crash: *** Terminating app due to uncaught exception 'NSGenericException', reason: 'Unable to activate constraint with anchors <NSLayoutYAxisAnchor:0x60000179cec0 "UIView:0x103c52fe0.top"> and <NSLayoutYAxisAnchor:0x6000017e0800 "_UIRemoteKeyboardPlaceholderView:0x103baa240.bottom"> because they have no common ancestor. Does the constraint or its anchors reference items in different view hierarchies? That's illegal.' terminating due to uncaught exception of type NSException CoreSimulator 1051.17.8 - Device: iPad Pro 13-inch (M5) (655000D7-41BC-4B13-BD07-BBA80D892E97) - Runtime: iOS 26.2 (23C54) - DeviceType: iPad Pro 13-inch (M5) Does anyone have the slightest idea of a workaround? I can't find one. import SwiftUI struct ContentView: View { var body: some View { Text("Content") .sheet(isPresented: .constant(true)) { PresentedView() } } } struct PresentedView: View { @State private var text = "" var body: some View { ScrollView { VStack { TextField("Placeholder", text: $text) .keyboardType(.numberPad) } .padding(80) } } } See here for discussion and video to reproduce: https://stackoverflow.com/questions/79905933/ipados-26-crash-when-floating-num-pad-in-presented-view
Replies
0
Boosts
1
Views
21
Activity
1w