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

iOS 18 hit testing functionality differs from iOS 17
I created a Radar for this FB14766095, but thought I would add it here for extra visibility, or if anyone else had any thoughts on the issue. Basic Information Please provide a descriptive title for your feedback: iOS 18 hit testing functionality differs from iOS 17 What type of feedback are you reporting? Incorrect/Unexpected Behavior Description: Please describe the issue and what steps we can take to reproduce it: We have an issue in iOS 18 Beta 6 where hit testing functionality differs from the expected functionality in iOS 17.5.1 and previous versions of iOS. iOS 17: When a sheet is presented, the hit-testing logic considers subviews of the root view, meaning the rootView itself is rarely the hit view. iOS 18: When a sheet is presented, the hit-testing logic changes, sometimes considering the rootView itself as the hit view. Code: import SwiftUI struct ContentView: View { @State var isPresentingView: Bool = false var body: some View { VStack { Text("View One") Button { isPresentingView.toggle() } label: { Text("Present View Two") } } .padding() .sheet(isPresented: $isPresentingView) { ContentViewTwo() } } } #Preview { ContentView() } struct ContentViewTwo: View { @State var isPresentingView: Bool = false var body: some View { VStack { Text("View Two") } .padding() } } extension UIWindow { public override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { /// Get view from superclass. guard let hitView = super.hitTest(point, with: event) else { return nil } print("RPTEST rootViewController = ", rootViewController.hashValue) print("RPTEST rootViewController?.view = ", rootViewController?.view.hashValue) print("RPTEST hitView = ", hitView.hashValue) if let rootView = rootViewController?.view { print("RPTEST rootViewController's view memory address: \(Unmanaged.passUnretained(rootView).toOpaque())") print("RPTEST hitView memory address: \(Unmanaged.passUnretained(hitView).toOpaque())") print("RPTEST Are they equal? \(rootView == hitView)") } /// If the returned view is the `UIHostingController`'s view, ignore. print("MTEST: hitTest rootViewController?.view == hitView", rootViewController?.view == hitView) print("MTEST: -") return hitView } } Looking at the print statements from the provided sample project:
 iOS 17 presenting a sheet from a button tap on the ContentView(): RPTEST rootViewController's view memory address: 0x0000000120009200 RPTEST hitView memory address: 0x000000011fd25000 RPTEST Are they equal? false MTEST: hitTest rootViewController?.view == hitView false RPTEST rootViewController's view memory address: 0x0000000120009200 RPTEST hitView memory address: 0x000000011fd25000 RPTEST Are they equal? false MTEST: hitTest rootViewController?.view == hitView false iOS 17 dismiss from presented view: RPTEST rootViewController's view memory address: 0x0000000120009200 RPTEST hitView memory address: 0x000000011fe04080 RPTEST Are they equal? false MTEST: hitTest rootViewController?.view == hitView false RPTEST rootViewController's view memory address: 0x0000000120009200 RPTEST hitView memory address: 0x000000011fe04080 RPTEST Are they equal? false MTEST: hitTest rootViewController?.view == hitView false iOS 18 presenting a sheet from a button tap on the ContentView(): RPTEST rootViewController's view memory address: 0x000000010333e3c0 RPTEST hitView memory address: 0x0000000103342080 RPTEST Are they equal? false MTEST: hitTest rootViewController?.view == hitView false RPTEST rootViewController's view memory address: 0x000000010333e3c0 RPTEST hitView memory address: 0x000000010333e3c0 RPTEST Are they equal? true MTEST: hitTest rootViewController?.view == hitView true You can see here ☝️ that in iOS 18 the views have the same memory address on the second call and are evaluated to be the same. This differs from iOS 17. iOS 18 dismiss RPTEST rootViewController's view memory address: 0x000000010333e3c0 RPTEST hitView memory address: 0x0000000103e80000 RPTEST Are they equal? false MTEST: hitTest rootViewController?.view == hitView false RPTEST rootViewController's view memory address: 0x000000010333e3c0 RPTEST hitView memory address: 0x0000000103e80000 RPTEST Are they equal? false MTEST: hitTest rootViewController?.view == hitView false The question I want to ask: Is this an intended change, meaning the current functionality in iOS 18 is expected? Or is this a bug and it's something that needs to be fixed? As a user, I would expect that the hit testing functionality would remain the same from iOS 17 to iOS 18. Thank you for your time.
14
13
4.5k
Aug ’25
UISlider valueChanged has uninitialized UIEvent
This issue was in the first iOS 26 beta and it still there with Xcode 26 beta 6 (17A5305f). Feedback is FB18581605 and contains sample project to reproduce the issue. I assign a target and action to a UISlider for the UIControl.Event.valueChanged value: addTarget(self, action: #selector(sliderValueDidChange), for: .valueChanged) Here’s the function. @objc func sliderValueDidChange(_ sender: UISlider, event: UIEvent) { print(event) } When printing the event value, there is a crash. When checking the event value with lldb, it appears uninitialized.
Topic: UI Frameworks SubTopic: UIKit Tags:
12
6
1.1k
2d
Widget link broken by `.desaturated` image rendering mode
Using desaturated mode on an image in a widget will break any links or buttons that use the image as their 'label'. Using the following will just open the app as if there was no link at all - therefore just using the fallback userActivity handler, or any .widgetURL() urls provided. Link(destination: URL(string: "bug://never-works")!) { Image("puppy") .widgetAccentedRenderingMode(.desaturated) } The same goes for buttons: Button(intent: MyDemoIntent()) { Image("puppy") .widgetAccentedRenderingMode(.desaturated) } I've tried hacky solutions like putting the link behind the image using a ZStack, and disabling hit testing on the image, but they don't work. Anything else to try? Logged as Feedback #15152620.
8
5
818
2w
interactive glassEffect bug?
Applying glass effect, providing a shape isn't resulting in the provided shape rendering the interaction correctly. .glassEffect(.regular.tint(Color(event.calendar.cgColor)).interactive(), in: .rect(cornerRadius: 20)) results in properly drawn view but interactive part of it is off. light and shimmer appear as a capsule within the rect.
1
11
256
Jun ’25
Xcode 26 - Crashing Loading Custom TabBarViewController
When I build my app for iPad OS, either 26, or 18.5, as well as iOS on 16.5 from Xcode 26 with UIDesignRequiresCompatibility enabled my app is crashing as it loads the main UIViewController, a subclassed UITabBarController which is being loaded programatically from a Storyboard from another SplashScreen ViewController. On i(Pad)OS 18.5 I get this error: Thread 1: "Could not instantiate class named _TtGC5UIKit17UICoreHostingViewVCS_21ToolbarVisualProvider8RootView_ because no class named _TtGC5UIKit17UICoreHostingViewVCS_21ToolbarVisualProvider8RootView_ was found; the class needs to be defined in source code or linked in from a library (ensure the class is part of the correct target)" On iPadOS 26 I get this error: UIKitCore/UICoreHostingView.swift:54: Fatal error: init(coder:) has not been implemented There is no issue building from Xcode 16.4, regardless of targeted i(Pad)OS.
10
11
1.2k
Aug ’25
SwiftUI ScrollView performance in macOS 15
There seems to be a performance issue when scrolling using the track pad with SwiftUI scroll views in macOS 15. This issue is NOT present in macOS 14. When using the track pad the scrolling is not smooth, but "stutters". However scrolling using the scroll bars is very smooth. The "stuttering" is worse if the SwiftUI ScrollView is in the detail view of a NavigationSplitView. The problem is not noticeable in scroll views with a small number views, but when the more views inside the scroll view, the more prominent the problem becomes. I have a simple example app that illustrates the problem here (the example app is a simplification of my app Yammixer): https://github.com/danwaltin/SwiftUIScrollViewPerformance When running this example app on macOS 14 (Sonoma) on an Intel i7 Mac book pro from 2019 the scrolling is "buttery smooth". But on macOS 15 (Sequoia) on my Apple Silicon M1 Mac book pro the issue is very obvious. When using Instruments I see that on macOS 15 "flame graph" shows that 85% of the execution time is in a "_hitTestForEvent" method. If the test app does not use NavigationSplitView about 70% of execution time is in the _hitTestForEvent method.
Topic: UI Frameworks SubTopic: SwiftUI
16
11
2.3k
Feb ’25
iOS 26 Beta bug - keyboard toolbar with bottom safe area inset
Hello! I have experienced a weird bug in iOS 26 Beta (8) and previous beta versions. The safe area inset is not correctly aligned with the keyboard toolbar on real devices and simulators. When you focus a new textfield the bottom safe area is correctly placed aligned the keyboard toolbar. On real devices the safe area inset view is covered slightly by the keyboard toolbar, which is even worse than on the simulator. Here's a clip from a simulator: Here's the code that reproduced the bug I experienced in our app. #Preview { NavigationStack { ScrollView { TextField("", text: .constant("")) .padding() .background(Color.secondary) TextField("", text: .constant("")) .padding() .background(Color.green) } .padding() .safeAreaInset(edge: .bottom, content: { Color.red .frame(maxWidth: .infinity) .frame(height: 40) }) .toolbar { ToolbarItem(placement: .keyboard) { Button {} label: { Text("test") } } } } }
2
11
661
Sep ’25
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!
12
3
2.8k
Oct ’25
Xcode 15 Breaks Usage Of TextField.focused()
My usage of TextField.focused() works fine in Xcode 14.3.1 but is broken as of Xcode 15. I first noticed it in the second beta and it's still broken as of the 4th beta. Feedback / OpenRadar # FB12432084 import SwiftUI struct ContentView: View { @State private var text = "" @FocusState var isFocused: Bool var body: some View { ScrollView { TextField("Test", text: $text) .textFieldStyle(.roundedBorder) .focused($isFocused) Text("Text Field Is Focused: \(isFocused.description)") } } }
7
1
1.6k
Feb ’25
Keep ScrollView position when adding items on the top
I am using a LayzVStack embedded into a ScrollView. The list items are fetched from a core data store by using a @FetchResult or I tested it also with the new @Query command coming with SwiftData. The list has one hundred items 1, 2, 3, ..., 100. The user scrolled the ScrollView so that items 50, 51, ... 60 are visible on screen. Now new data will be fetched from the server and updates the CoreData or SwiftData model. When I add new items to the end of the list (e.g 101, 102, 103, ...) then the ScrollView is keeping its position. Opposite to this when I add new items to the top (0, -1, -2, -3, ...) then the ScrollView scrolls down. Is there a way with the new SwiftData and SwiftUI ScrollView modifiers to update my list model without scrolling like with UIKit where you can query and set the scroll offset pixel wise?
8
1
9.7k
May ’25
LazyVGrid (embedded in a List) does not resize automatically when content increases and layout changes
I have a List in a sidebar style which contains a LazyVGrid and a Section with a simple list contents. Every thing works well except when content increases and layout changes (from two columns to one column) for the LazyVGrid with editMode changing to .active ... LazyVGrid does not expand/resize when the content increases (the increased content gets clipped)...but does when user expands/folds on the section below :(. However LazyVGrid resizes to show the entire content when the content shrinks with editMode reverting to .inactive Note: If I replace the List with a ScrollView...lazyVGrid resizes perfectly when content increases in editMode = .active....but then I would lose all the Sidebar and List characteristics for the Section below :( Also, looks like .onMove is not supported in LazyVGrids Any pointers to solve the LazyVGrid (embedded in a List) not resizing or expanding when content increases ... will be deeply appreciated. var body: some View {         List {             LazyVGrid(columns: editMode?.wrappedValue == .active ? singleColumn : twoColumns, alignment: .leading, spacing: 10) {                 ForEach(editMode?.wrappedValue == .active ? allDashItems : selectedDashItems) { dashitem in                     DashItemCell(dashitem)                                         }                 .onMove(perform: moveDashItem)                 .environment(\.editMode, editMode)             }             Section(header: Text("Bottom Section")) {                     ForEach (sectionList)	{ item in                         ListItemCell(item)                     }                     .onDelete(perform: deleteFolder)                     .onMove(perform: moveFolder)                 }         }         .listStyle(SidebarListStyle()) }
1
1
1.7k
May ’25
Navigation broken in iOS 18.4
All of a sudden, after iOS 18.4 was released, I am having tons of navigation problems in my app in production. Buttons navigating to empty pages, views seeming to 'freeze', top navigation bar mismatched with the content of the page. It seems that iOS 18.4 broke a critical piece of UIKit + SwiftUI bridging functionality that my project relies on. My application is written with both UIKit and SwiftUI components. Here is a breakdown of my setup: UIApplicationDelegate > UIWindow > rootViewController of window is a UITabBarController > each tab is a UINavigationController rootViewController of nav controller is a UIHostingController > rootView of the hosting controller is a SwiftUI View In my SwiftUI views, I have been using NavigationLink for horizontal 'push' style navigation in my SwiftUI views. I do not use NavigationView, I only rely on the bridging capabilities of UINavigationController to action on my NavigationLinks. This has never been an issue, until iOS 18.4 was released. Now, when running iOS 18.4, I am having all sorts of unexpected behavior in the UI. I will break down 2 of these use cases here: Use case A: In one of my SwiftUI views, I have a ForEach for which each element's view is a NavigationLink. This is using the NavigationLink(_ destination:,label:) initializer. Navigating forward from here works/looks normal. However, once I try to navigate backward from that destination (tap the 'Back' button in top left), the view goes blank and the navigation bar at the top of the page (which is maintained by the UINavigationController instance) does not change. If I call popToRootViewController on that nav controller, the navigation bar at the top of the page returns to its normal state, but the view is still blank. It is not until after I have called popToRootViewController, and then navigate to a different tab of the UITabBarController and return to the initial tab, does the SwiftuI content view (the one with the ForEach) finally redraw and the view hierarchy is restored. Here is a warning that is logged in the console when I tap the 'Back ' button: Top view controller's view unexpectedly not in window for navigation transition. Skipping layout. nav = <UINavigationController: 0x1110bbe00>, topVC = <TtGC7SwiftUI19UIHostingControllerV5MyApp10MyPage: 0x106814e00> EDIT: If I replace the NavigationLink with a call to UINavigationController.pushViewController, I am still seeing the exact same behavior. Pressing back button makes the view empty > need to pop to root view controller and switch tabs in order to restore the view. Use case B Another instance of this issue happens whenever I try to use a NavigationLink inside of a view that itself was the destination of a NavigationLink in its parent view (i.e.: Root view > detail view > sub-detail view). For example, take the detail view destination in use case A. I have tapped a NavigationLink from the ForEach and landed on the detail view. Again, so far things work/look normal. Now, if I tap on another NavigationLink from that detail view, the view does not transition to the new page. The top navigation bar does transition, and shows the title and actions associated with this second destination. However, the view of this second destination is not displayed. It is worth noting that the same warning I mentioned above is also logged when I tap the NavigationLink to navigate to this second destination. Top view controller's view unexpectedly not in window for navigation transition. Skipping layout. nav = <UINavigationController: 0x109859400>, topVC = <TtGC7SwiftUI19UIHostingControllerVVS_19BridgedPresentation8RootView: 0x300ab8000> Strangely, if I switch to a different tab of the UITabBarController and back to the initial tab, this second destination's view is successfully rendered. It seems that switching tabs in this UITabBarController is calling something in either SwiftUI or UIKit that is redrawing my views. Conclusion This is a serious issue with UIKit + SwiftUI bridging support. I have never had problems like this until devices started running iOS 18.4, and there is nothing in the iOS 18.4 changelog that suggests this was an intentional change. All of a sudden, after updating to the latest iOS version, my app is totally broken. I want to be clear that I'm not using deprecated NavigationLink methods in these instances. My app's minimum deployment target is iOS 16. I know that there are more modern navigation APIs like navigation stack, etc. I am looking for answers about my use case: whether it is officially unsupported as of iOS 18.4, whether this setup should be supported and this is indeed some sort of bug in iOS, or anything in-between. I'm happy to provide formatted code if needed for discussion purposes. This is about my entire app's view hierarchy so there are a lot of disparate lines of code that make up this problem.
1
10
264
Apr ’25
[macOS Sequoia] Using RegisterEventHotkey with option and shift modifiers doesn't working anymore
Hello. In my app, I use RegisterEventHotkey to implement global keyboard shortcuts to trigger actions. Up until macOS Sequoia, I was able to use a keyboard shortcut with option and shift as the modifiers, like option shift 2 (⌥ ⇧ 2). Now, on macOS Sequoia, using RegisterEventHotkey to register a hotkey with those exact modifiers (option and shift), regardless of the key, fails with the error -9868 (eventInternalErr). Is this a documented and wanted change, or is this a bug? Other modifier keys (just command, command option, command shift, command control, control shift, etc), all work. Any insight into this would be appreciated. (Feedback filed: FB15163561) Thank you, Matthias
22
10
13k
Nov ’25
SwiftUI Popover Crash During Resizing in Stage Manager
SwiftUI Popover Crash on iPad During Resizing in Stage Manager with Exception. *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Trying to layout popover in the delegate callback popoverPresentationController:willRepositionPopoverToRect:inView: will lead to recursion. Do not force the popover's container view or an ancestor to layout in this callback.' (Occurred from iPadOS 18.1) struct ContentView: View { @State var showPopover: Bool = false var body: some View { VStack { Text("Hello, world!") Button(action: { showPopover = true }, label: { Text("Open Popover") }) } .padding() .popover(isPresented: $showPopover, attachmentAnchor: .point(.trailing), content: { VStack { Text("Popover Content") } }) } }
10
9
1.3k
Feb ’25
How can we performantly scroll to a target location using TextKit 2?
How can we performantly scroll to a target location using TextKit 2? Hi everyone, I'm building a custom text editor using TextKit 2 and would like to scroll to a target location efficiently. For instance, I would like to move to the end of a document seamlessly, similar to how users can do in standard text editors by using CMD + Down. Background: NSTextView and TextEdit on macOS can navigate to the end of large documents in milliseconds. However, after reading the documentation and experimenting with various ideas using TextKit 2's APIs, it's not clear how third-party developers are supposed to achieve this. My Code: Here's the code I use to move the selection to the end of the document and scroll the viewport to reveal the selection. override func moveToEndOfDocument(_ sender: Any?) { textLayoutManager.ensureLayout(for: textLayoutManager.documentRange) let targetLocation = textLayoutManager.documentRange.endLocation let beforeTargetLocation = textLayoutManager.location(targetLocation, offsetBy: -1)! textLayoutManager.textViewportLayoutController.layoutViewport() guard let textLayoutFragment = textLayoutManager.textLayoutFragment(for: beforeTargetLocation) else { return } guard let textLineFragment = textLayoutFragment.textLineFragment(for: targetLocation, isUpstreamAffinity: true) else { return } let lineFrame = textLayoutFragment.layoutFragmentFrame let lineFragmentFrame = textLineFragment.typographicBounds.offsetBy(dx: 0, dy: lineFrame.minY) scrollToVisible(lineFragmentFrame) } While this code works as intended, it is very inefficient because ensureLayout(_:) is incredibly expensive and can take seconds for large documents. Issues Encountered: In my attempts, I have come across the following two issues. Estimated Frames: The frames of NSTextLayoutFragment and NSTextLineFragment are approximate and not precise enough for scrolling unless the text layout fragment has been fully laid out. Laying out all text is expensive: The frames become accurate once NSTextLayoutManager's ensureLayout(for:) method has been called with a range covering the entire document. However, ensureLayout(for:) is resource-intensive and can take seconds for large documents. NSTextView, on the other hand, accomplishes the same scrolling to the end of a document in milliseconds. I've tried using NSTextViewportLayoutController's relocateViewport(to:) without success. It's unclear to me whether this function is intended for a use case like mine. If it is, I would appreciate some guidance on its proper usage. Configuration: I'm testing on macOS Sonoma 14.5 (23F79), Swift (AppKit), Xcode 15.4 (15F31d). I'm working on a multi-platform project written in AppKit and UIKit, so I'm looking for either a single solution that works in both AppKit and UIKit or two solutions, one for each UI framework. Question: How can third-party developers scroll to a target location, specifically the end of a document, performantly using TextKit 2? Steps to Reproduce: The issue can be reproduced using the example project (download from link below) by following these steps: Open the example project. Run the example app on a Mac. The example app shows an uneditable text view in a scroll view. The text view displays a long text. Press the "Move to End of Document" toolbar item. Notice that the text view has scrolled to the bottom, but this took several seconds (~3 seconds on my MacBook Pro 16-inch, 2021). The duration will be shown in Xcode's log. You can open the ExampleTextView.swift file and find the implementation of moveToEndOfDocument(_:). Comment out line 84 where the ensureLayout(_:) is called, rerun the app, and then select "Move to End of Document" again. This time, you will notice that the text view moves fast but does not end up at the bottom of the document. You may also open the large-file.json in the project, the same file that the example app displays, in TextEdit, and press CMD+Down to move to the end of the document. Notice that TextEdit does this in mere milliseconds. Example Project: The example project is located on GitHub: https://github.com/simonbs/apple-developer-forums/tree/main/how-can-we-performantly-scroll-to-a-target-location-using-textkit-2 Any advice or guidance on how to achieve this with TextKit 2 would be greatly appreciated. Thanks in advance! Best regards, Simon
10
9
2.6k
Aug ’25
AsyncImage - Cancelled Loading before View is Visible
I have been playing around with the new AsyncImage Api in SwiftUI I am using the initialiser that passes in a closure with the AsyncImagePhase, to view why an image may not load, when I looked at the error that is passed in if the phase is failure, the localised description of the error is "Cancelled" but this is happening before the view is being displayed. I am loading these images in a list, I imagine I am probably doing something which is causing the system to decide to cancel the loading, but I cannot see what. Are there any tips to investigate this further?
15
8
13k
Feb ’25