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

NSLayoutManager Bug -- layout manager re-laying out overlapping text into the same container.
I've posted a couple times now about major issues I'm having with NSLayoutManager and have written to Apple for code-level support, but no one at Apple has responded to me in more than two weeks. So I'm turning to the community again for any help whatsoever. I'm fairly certain it's a real bug in TextKit. If I'm right about that, I'd love for anyone at Apple to take an interest. And better yet, if I'm wrong (and I hope I am), I'd be incredibly grateful to anyone who can point out where my mistake lies! I've been stuck with this bug for weeks on end. The crux of the issue is that I'm getting what seemed to be totally incompatible results from back to back calls to textContainer(forGlyphAt:effectiveRange:) and lineFragmentRect(forGlyphAt:effectiveRange:withoutAdditionalLayout:)... I'd lay out my text into a fairly tall container of standard page width and then query the layout manager for the text container and line fragment rect for a particular glyph (a glyph that happens to fall after many newlines). Impossibly, the layout manager would report that that glyph was in said very tall container, but that the maxY of its lineFragmentRect was only at 14 points (my NSTextView's isFlipped is true, so that's 14 points measuring from the top down). After investigating, it appears that what is happening under the hood is NSLayoutManager is for some reason laying out text back into the first container in my series of containers, rather than overflowing it into the next container(s) and/or giving me a nil result for textContainer(forGlyphAt:...) I've created a totally stripped down version of my project that recreates this issue reliably and I'm hoping literally anyone at Apple will respond to me. In order to recreate the bug, I've had to build a very specific set of preview data - namely some NSTextStorage content and a unique set of NSTextViews / NSTextContainers. Because of the unique and particular setup required to recreate this bug, the code is too much to paste here (my preview data definition is a little unwieldy but the code that actually processes/parses it is not). I can share the project if anyone is able and willing to look into this with me. It seems I'm not able to share a .zip of the project folder here but am happy to email or share a dropbox link.
7
0
305
May ’25
tabViewBottomAccessory in 26.1: View's @State is lost when switching tabs
Any view that is content for the tabViewBottomAccessory API fails to retain its state as of the last couple of 26.1 betas (and RC). The loss of state happens (at least) when the currently selected tab is switched (filed as FB20901325). Here's code to reproduce the issue: struct ContentView: View { @State private var selectedTab = TabSelection.one enum TabSelection: Hashable { case one, two } var body: some View { TabView(selection: $selectedTab) { Tab("One", systemImage: "1.circle", value: .one) { BugExplanationView() } Tab("Two", systemImage: "2.circle", value: .two) { BugExplanationView() } } .tabViewBottomAccessory { AccessoryView() } } } struct AccessoryView: View { @State private var counter = 0 // This guy's state gets lost (as of iOS 26.1) var body: some View { Stepper("Counter: \(counter)", value: $counter) .padding(.horizontal) } } struct BugExplanationView: View { var body: some View { ScrollView { VStack(alignment: .leading, spacing: 16) { Text("(1) Manipulate the counter state") Text("(2) Then switch tabs") Text("BUG: The counter state gets unexpectedly reset!") } .multilineTextAlignment(.leading) } } }
6
4
617
2w
UIDocumentPickerViewController does not allow picking folders on connected servers on iOS26
Hey there, I have an app that allows picking any folder via UIDocumentPickerViewController. Up until iOS18 users were able to pick folders from connected servers (servers connected in the Files app) as well. On iOS26, the picker allows for browsing into the connected servers, but the Select button is greyed out and does nothing when tapped. Is this a known issue? This breaks the whole premise of my file syncronization application.
6
0
261
Nov ’25
Screenshot preventing
I’d like to know if Apple currently supports any public API or entitlement for blocking in-app screenshots on iOS. If no such API exists, what is the officially recommended approach for App Store apps to prevent or react to screenshots of sensitive content in a banking app? I have tried using a hidden UITextField with isSecureTextEntry = true and observing UIApplication.userDidTakeScreenshotNotification, but these methods do not block the initial screenshot. Could you please advise how to block screenshots in my app?
Topic: UI Frameworks SubTopic: UIKit
6
0
160
Jun ’25
NSRulerView's background color and transparency (macOS 26)
When I compiled my legacy project with Tahoe's macOS 26 SDK, NSRulerViews are showing a very different design: Under prior macOS versions the horizontal and verrical ruler's background were blurring the content view, which was extending under the rulers, showing through their transparency. With Tahoe the horizontal ruler is always reflecting the scrollview's background color, showing the blurred content view beneath. And the vertical ruler is always completely transparent (without any blurring), showing the content together with the ruler's markers and ticks. It's difficult to describe, I'll try to replicate this behavior with a minimal test project, and probably file a bug report / enhancement request. But before I take next steps, can anyone confirm this observation? Maybe it is an intentional design decision by Apple?
6
0
396
Nov ’25
TextKit 2 calls NSTextLayoutFragment's draw method too often
The following is verbatim of a feedback report (FB19809442) I submitted, shared here as someone else might be interested to see it (I hate the fact that we can't see each other's feedbacks). On iOS 16, TextKit 2 calls NSTextLayoutFragment's draw(at:in:) method once for the first paragraph, but for every other paragraph, it calls it continuously on every scroll step in the UITextView. (The first paragraph is not cached; its draw is called again when it is about to be displayed again, but then it is again called only once per its lifecycle.) On iOS 17, the behavior is similar; the draw method gets called once for the 1st and 2nd paragraph, and for every other paragraph it again gets called continuously as a user scrolls a UITextView. On iOS 18 (and iOS 26 beta 4), TextKit 2 calls the layout fragment's draw(at:in:) on every scroll step in the UITextView, for all paragraphs. This results in terrible performance. TextKit 2 is promised to bring many performance benefits by utilizing the viewport - a new concept that represents the visible area of a text view, along with a small overscroll. However, having the draw method being constantly called almost negates all the performance benefits that viewport brings. Imagine what could happen if someone needs to add just a bit of logic to that draw method. FPS drops significantly and UX is terribly degraded. I tried optimizing this by only rendering those text line fragments which are in the viewport, by using NSTextViewportLayoutController.viewportBounds and converting NSTextLineFragment.typographicBounds to the viewport-relative coordinate space (i.e. the coordinate space of the UITextView itself). However, this patch only works on iOS 18 where the draw method is called too many times, as the viewport changes. (I may have some other problems in my implementation, but I gave up on improving those, as this can't work reliably on all OS versions since the underlying framework isn't calling the method consistently.) Is this expected? What are our options for improving performance in these areas?
6
0
266
Aug ’25
Should SwiftUI view models in Swift 6 be both @Observable and @MainActor?
Hi, In the WWDC25 session Elevate an app with Swift concurrency (timestamps: 8:04 and later), the StickerViewModel is shown annotated with @Observable but not @MainActor. The narration mentions that updates happen on the main thread, but that guarantee is left implicit in the calling code. In Swift 6, though, one of the major benefits is stronger compiler enforcement against data races and isolation rules. If a view model were also annotated with @MainActor, then the compiler could enforce that observable state is only updated on the main actor, preventing accidental background mutations or updates that can cause data races between nonisolated and main actor-isolated uses. Since @Observable already signals that state changes are intended to be observed (and in practice, usually by views), it seems natural that such types should also be main-actor isolated. Otherwise, we’re left with an implicit expectation that updates will always come from the main thread, but without the compiler’s help in enforcing that rule. This also ties into the concept of local reasoning that was emphasized in other Swift 6 talks (e.g. Beyond the basics of structured concurrency). With @MainActor, I can look at a view model and immediately know that all of its state is main-actor isolated. With only @Observable, that guarantee is left out, which feels like it weakens the clarity that Swift 6 is trying to promote. Would it be considered a best practice in Swift 6 to use both @Observable and @MainActor for UI-facing view models? Or is the intention that SwiftUI developers should rely on calling context to ensure main-thread updates, even if that means the compiler cannot enforce isolation? Thanks!
6
0
294
Aug ’25
Modal Presentation in UIKit Adds Solid Background in iOS 26
Hello, I have a number of UIViewControllers that are presented as follows: vc.modalPresentationStyle = UIModalPresentationStyle.popover vc.modalTransitionStyle = UIModalTransitionStyle.coverVertical self.present(vc, animated: true, completion: nil) The VC is designed from a Storyboard where I set the 'view' of the VC to have a .clear 'backgroundColor', I have a smaller 'Alert View' added as a subview which is what the user interacts with. In iOS 13 - iOS 18 this would present modally, not take up the entire screen and allow the user to see relevant context from the screen underneath. In iOS 26 Beta 5 and every beta prior the system injects a 'UIDropShadowView' in the View Hierarchy, this view has a solid color backdrop, either white/black depending on light/dark mode. This causes all underlying content to be blocked and essentially forces a full screen modal presentation despite the existing design. I am looking for a way to remove this solid color. I'm not sure if it's intentional or a bug / oversight. I have been able to remove it in a hacky way, I cycle the view hierarchy to find 'UIDropShadowView' and set it's backdrop to transparent. However when you swipe down to partially dismiss the view it turns to Liquid Glass when it is around 75% dismissed and then resets the background color to white/black. I tried creating a custom UIViewControllerTransitioningDelegate so that I could re-implement the existing behaviour but it's incredibly difficult to mimic the partial dismiss swipe down effect on the VC. I have also tried changing my presentation to: vc.modalPresentationStyle = UIModalPresentationStyle.overFullScreen vc.modalTransitionStyle = UIModalTransitionStyle.crossDissolve This works but then the user loses the ability to interactively swipe to dismiss. Any help would be appreciated. Thank you!
Topic: UI Frameworks SubTopic: UIKit Tags:
6
2
444
Aug ’25
Can I tell when my iOS Widget is running on MacOS (when Use IPhone Widgets is on)
I have an iOS Widget that also can load on the Mac when the Use iPhone Widgets setting is turned on on the Mac in Desktop & Dock. I want to use a different url scheme to open video clips from the widget if it is being clicked on iOS or the Mac. I tried using ProcessInfo.processInfo.isiOSAppOnMac but it always thinks it is on iOS. I also tried looking for the user document path to see if it was /var/mobile/ or /Users/. but it always thinks it is /var/mobile. I assume this is as it is not really a catalyst app but a WidgetKit extension from the phone. Is there anyway I can figure out when the widget is running on the mac? Thanks!
6
0
660
Jun ’25
iOS 26 regression: Slider does not respect step parameter
In iOS 26, the Slider control no longer respects the step parameter. For example, import SwiftUI struct ContentView: View { @State private var sliderValue: CGFloat = 16 var body: some View { Slider( value: $sliderValue, in: 0...100, step: 5, onEditingChanged: { editing in print(sliderValue) } ) } } In iOS 18, this prints values like 5, 35, 60, 95, etc. In iOS 26.0 (release version), this prints floats that are not rounded to the nearest 5, and the slider does not snap to values ending in 5. Feedback report number: FB20320542
Topic: UI Frameworks SubTopic: SwiftUI
6
4
373
Nov ’25
How to get the frame or insets of the new iPadOS 26 window control buttons (close, minimize, fullscreen)?
In iPadOS 26, Apple introduced macOS-style window control buttons (close, minimize, fullscreen) for iPad apps running in a floating window. I'm working on a custom toolbar (UIView) positioned near the top of the window, and I'd like to avoid overlapping with these new controls. However, I haven't found any public API that exposes the frame, layout margins, or safe area insets related to this new UI region. I've checked the window's safeAreaInsets, additionalSafeAreaInsets, and UIWindowSceneDelegate APIs, but none of them seem to reflect the area occupied by these buttons. Is there an officially supported way to: Get the layout information (frame, insets, or margins) of the window control buttons on iPadOS 26? Or, is there a system-defined guideline or padding value we should use to avoid overlapping this new UI? Any clarification or guidance would be appreciated!
6
1
661
Aug ’25
How to animate `UIHostingController.view` frame when my View's size changes?
I have a UIHostingController on which I have set: hostingController.sizingOptions = [.intrinsicContentSize] The size of my SwiftUI content changes with animation (I update a @Published property on an ObservableObject inside a withAnimation block). However, I notice that my hostingController.view just jumps to the new frame without animating the change. Question: how can I animate the frame changes in UIHostingController that are caused by sizingOptions = [.intrinsicContentSize]
6
1
308
3w
Force NSDocument save panel to select most specific type in format popup button
My app supports different plain text file formats, including the standard .txt and Markdown. When creating a new document, my app already asks which format it should have, so when saving it, I would expect that the save panel already selects that format in the popup button, but currently it always selects "Plain Text". For example, I would expect for a Markdown document that it selects "Markdown" instead of "Plain Text". Is there a way to force it to select the most specific format matching the document format?
Topic: UI Frameworks SubTopic: AppKit Tags:
6
1
168
Jul ’25
Animation does not work with List, while works with ScrollView + ForEach
Why there is a working animation with ScrollView + ForEach of items removal, but there is none with List? ScrollView + ForEach: struct ContentView: View { @State var items: [String] = Array(1...5).map(\.description) var body: some View { ScrollView(.vertical) { ForEach(items, id: \.self) { item in Text(String(item)) .frame(maxWidth: .infinity, minHeight: 50) .background(.gray) .onTapGesture { withAnimation(.linear(duration: 0.1)) { items = items.filter { $0 != item } } } } } } } List: struct ContentView: View { @State var items: [String] = Array(1...5).map(\.description) var body: some View { List(items, id: \.self) { item in Text(String(item)) .frame(maxWidth: .infinity, minHeight: 50) .background(.gray) .onTapGesture { withAnimation(.linear(duration: 0.1)) { items = items.filter { $0 != item } } } } } }```
6
1
238
Feb ’26
NSTextLineFragment crash - how to debug
We have crash reports as shown below that we haven't yet been able to repro and could use some help deubgging. My guess is that the app is giving a label or text view an attributed string with an invalid attribute range, but attributed strings are used in many places throughout the app, and I don't know an efficient way to track this down. I'm posting the stack trace here in hopes that someone more familiar with the internals of the system frameworks mentioned will be able to provide a clue to help narrow where I should look. Fatal Exception: NSRangeException NSMutableRLEArray objectAtIndex:effectiveRange:: Out of bounds 0 CoreFoundation 0x2d5fc __exceptionPreprocess 1 libobjc.A.dylib 0x31244 objc_exception_throw 2 Foundation 0x47130 blockForLocation 3 UIFoundation 0x2589c -[NSTextLineFragment _defaultRenderingAttributesAtCharacterIndex:effectiveRange:] 4 UIFoundation 0x25778 __53-[NSTextLineFragment initWithAttributedString:range:]_block_invoke 5 CoreText 0x58964 TLine::DrawGlyphsWithAttributeOverrides(TLineDrawContext const&, __CFDictionary const* (long, CFRange*) block_pointer, TDecoratorObserver*) const 6 CoreText 0x58400 CTLineDrawWithAttributeOverrides 7 UIFoundation 0x25320 _NSCoreTypesetterRenderLine 8 UIFoundation 0x24b10 -[NSTextLineFragment drawAtPoint:graphicsContext:] 9 UIFoundation 0x3e634 -[NSTextLineFragment drawAtPoint:inContext:] 10 UIFoundation 0x3e450 -[NSTextLayoutFragment drawAtPoint:inContext:] 11 UIKitCore 0x3e3098 __38-[_UITextLayoutFragmentView drawRect:]_block_invoke 12 UIKitCore 0x3e31cc _UITextCanvasDrawWithFadedEdgesInContext 13 UIKitCore 0x3e3040 -[_UITextLayoutFragmentView drawRect:] 14 UIKitCore 0xd7a98 -[UIView(CALayerDelegate) drawLayer:inContext:] 15 QuartzCore 0x109340 CABackingStoreUpdate_ 16 QuartzCore 0x109224 invocation function for block in CA::Layer::display_() 17 QuartzCore 0x917f0 -[CALayer _display] 18 QuartzCore 0x90130 CA::Layer::layout_and_display_if_needed(CA::Transaction*) 19 QuartzCore 0xe50c4 CA::Context::commit_transaction(CA::Transaction*, double, double*) 20 QuartzCore 0x5bd8c CA::Transaction::commit() 21 UIKitCore 0x9f3f0 _UIApplicationFlushCATransaction 22 UIKitCore 0x9c89c __setupUpdateSequence_block_invoke_2 23 UIKitCore 0x9c710 _UIUpdateSequenceRun 24 UIKitCore 0x9f040 schedulerStepScheduledMainSection 25 UIKitCore 0x9cc5c runloopSourceCallback 26 CoreFoundation 0x73f4c __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ 27 CoreFoundation 0x73ee0 __CFRunLoopDoSource0 28 CoreFoundation 0x76b40 __CFRunLoopDoSources0 29 CoreFoundation 0x75d3c __CFRunLoopRun 30 CoreFoundation 0xc8284 CFRunLoopRunSpecific 31 GraphicsServices 0x14c0 GSEventRunModal 32 UIKitCore 0x3ee674 -[UIApplication _run] 33 UIKitCore 0x14e88 UIApplicationMain also filed as FB16905066
6
1
512
Jan ’26
List rows partially obscured by navigation bar briefly render fully opaque when switching tabs (iOS 26)
Overview In iOS 26, a List embedded in a NavigationStack inside a TabView exhibits a visual glitch when switching tabs. When the list is scrolled such that some rows are partially obscured by the navigation bar, the system correctly applies a fade/opacity effect to those rows. However, if the user switches to another tab while rows are in this partially obscured (faded) state, those rows briefly flash at full opacity during the tab transition before disappearing. This flash is visually distracting and appears to be inconsistent with the intended scroll-edge opacity behavior. The issue occurs only for rows partially obscured by the navigation bar. Rows partially obscured by the tab bar do not exhibit this flashing behavior. Steps to Reproduce: Run the attached minimal reproduction on iOS 26. Open the first tab. Scroll the list so that some rows are partially hidden behind the navigation bar (showing the native faded appearance). While rows are in this partially faded state, switch to the second tab. Observe that the faded rows briefly render fully opaque during the tab switch. Expected Behavior: Rows that are partially obscured by the navigation bar should maintain consistent opacity behavior during tab transitions, without flashing to full opacity. import SwiftUI @main struct NavBarReproApp: App { /// Minimal repro for iOS 26: /// - TabView with two tabs /// - First tab: NavigationStack + List /// - Scroll so some rows are partially behind the nav bar (faded) /// - Switch tabs: those partially-faded rows briefly flash fully opaque. Partially faded rows under the tab bar do not flash private let items = Array(0..<200).map { "Row \($0)" } var body: some Scene { WindowGroup { TabView { NavigationStack { List { ForEach(items, id: \.self) { item in Text(item) } } .navigationTitle("One") .navigationBarTitleDisplayMode(.inline) } .tabItem { Label("One", systemImage: "1.circle") } NavigationStack { Text("Second tab") .navigationTitle("Two") .navigationBarTitleDisplayMode(.inline) } .tabItem { Label("Two", systemImage: "2.circle") } } } } }
6
0
172
Jan ’26
Change tint of back button in UINavigationItem on iOS 26
I am struggling to change the tint of the back button in an UINavigationItem. In iOS 18.6 it looks like this while on iOS 26 the same looks like this I can live without the Dictionary but I'd like to get the blue color back. In viewDidLoad() I have tried navigationItem.backBarButtonItem?.tintColor = .link but this did not work since navigationItem.backBarButtonItem is nil. My second attempt was navigationController?.navigationBar.tintColor = .link but this didn't work either. I have even set the Global Tint to Link Color but this had no effect either. Does anyone have an idea how to change the tint of the back button in an UINavigationItem on iOS 26?
Topic: UI Frameworks SubTopic: UIKit Tags:
6
1
447
Jan ’26
App Shortcuts: Invalid parameter type. AppEntity and AppEnum are the only allowed types...
Hi! So while Date is supported for @Parameter in an App Intent, I just discovered that Xcode will not let me use use it in a parametrized App Shortcut phrase. In my case, I would like to give the option to say "today", tomorrow", or "day after tomorrow" for the date. Am I missing something? Any hints on the best way to approach this?
6
1
1.1k
Oct ’25
On iPadOS 26 beta, the navigation bar can appear inset underneath the status bar (FB18241928)
On iPadOS 26 beta, the navigation bar can appear inset underneath the status bar (FB18241928) This bug does not happen on iOS 18. This bug occurs when a full screen modal view controller without a status bar is presented, the device orientation changes, and then the full screen modal view controller is dismissed. This bug appears to happen only on iPad, and not on iPhone. This bug happens both in the simulator and on the device. Thank you for investigating this issue.
6
0
514
Aug ’25