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

Created

Exporting and restoring AttributedString in rich TextEditor (iOS 26)
I am working with the rich TextEditor introduced in iOS 26, but I am having trouble preserving AttributedString formatting when converting to/from RTF. Here is my exporting logic in my view model (AttributedString to RTF) let nsAttrStr = NSAttributedString(self.text) // text is an AttributedString (bound to the TextEditor input) let range = NSRange(location: 0, length: nsAttrStr.length) let options: [NSAttributedString.DocumentAttributeKey: Any] = [ .documentType: NSAttributedString.DocumentType.rtf ] guard let data = try? nsAttrStr.data(from: range, documentAttributes: options) else { return nil } let rtfBase64 = data.base64EncodedString() When I inspect the result, it seems to lose the font, size, boldness, etc which is being correctly rendered in the TextEditor. When I convert back from RTF to an AttributedString, it reverts to the default text formatting applied in the TextEditor. Any ideas what could be going wrong?
1
0
147
3w
UIMenuElementAttributesKeepsMenuPresented not working when Glass Grouping changes
I'm working on a UIBarButtonItem that is supposed to be a filter button - it shows a menu in which the user can (un)check menu items. Using the UIMenuElementAttributesKeepsMenuPresented attribute on the UIActions prevents the menu to hide after the user clicks an item. The button is put alongside another button as the leftBarButtonItems of my navigation item. In iOS 26 they are grouped into a single glass container automatically. Now when the user starts filtering, I want to highlight the UIBarButton item to signal to the user that the filter is active (similar to what Apple does in the Mail app). I do that by setting the UIBarButtonItemStyle to prominent. Now that works too, but it causes the automatic glass grouping to break up and the menu to hide. I'm fine with the grouping to break up, but the menu shouldn't hide. Is this a bug or can this be prevented somehow?
Topic: UI Frameworks SubTopic: UIKit Tags:
2
0
114
3w
Incorrect menu consistency warnings logged in Tahoe for NSStatusItem, performance issues related?
Is anyone else getting new warning about menu items with submenus when running on Tahoe? I'm getting big performance problems using my menu as well as seeing these messages and I'm wondering if there's a connection. My app is faceless with a NSStatusItem with an NSMenu. Specifically it's my own subclass of NSMenu where I have a lot of code to manage the menu's dynamic behavior. This code is directly in the menu subclass instead of in a controller because the app I forked had it this way, a little wacky but I don't see it being a problem. A nib defines the contents of the menu, and it's instantiated manually with code like: var nibObjects: NSArray? = [] guard let nib = NSNib(nibNamed: "AppMenu", bundle: nil) else { ... } guard nib.instantiate(withOwner: owner, topLevelObjects: &nibObjects) else { ... } guard let menu = nibObjects?.compactMap({ $0 as? Self }).first else { ... } Within that nib.instantiate call I see a warning logged that seems new to Tahoe, before the menu's awakeFromNib is called, that says (edited): Internal inconsistency in menus - menu <NSMenu: 0x6000034e5340> believes it has <My_StatusItem_App.AppMenu: 0x7f9570c1a440> as a supermenu, but the supermenu does not seem to have any item with that submenu My_StatusItem_App.AppMenu: 0x7f9570c1a440 is my menu belonging to the NSStatusItem, NSMenu: 0x6000034e5340 is the submenu of one of its menu items. At a breakpoint in the NSMenu subclass's awakeFromNib I print self and see clear evidence of the warning's incorrectness. Below is a snippet of the console including the full warning, only edited for clarity and brevity. It shows on line 32 menu item with placeholder title "prototype batch item" that indeed has that submenu. Internal inconsistency in menus - menu <NSMenu: 0x6000034e5340> Title: Supermenu: 0x7f9570c1a440 (My StatusItem App), autoenable: YES Previous menu: 0x0 (None) Next menu: 0x0 (None) Items: ( "<NSMenuItem: 0x6000010e4fa0 Do The Thing Again, ke mask='<none>'>", "<NSMenuItem: 0x6000010e5040 Customize\U2026, ke mask='<none>'>", "<NSMenuItem: 0x6000010e50e0, ke mask='<none>'>" ) believes it has <My_StatusItem_App.AppMenu: 0x7f9570c1a440> Title: My StatusItem App Supermenu: 0x0 (None), autoenable: YES Previous menu: 0x0 (None) Next menu: 0x0 (None) Items: ( ) as a supermenu, but the supermenu does not seem to have any item with that submenu (lldb) po self <My_StatusItem_App.AppMenu: 0x7f9570c1a440> Title: My StatusItem App Supermenu: 0x0 (None), autoenable: YES Previous menu: 0x0 (None) Next menu: 0x0 (None) Items: ( "<NSMenuItem: 0x6000010fd7c0 About My StatusItem App\U2026, ke mask='<none>', action: showAbout:, action image: info.circle>", "<NSMenuItem: 0x6000010fd860 Show Onboarding Window\U2026, ke mask='Shift', action: showIntro:>", "<NSMenuItem: 0x6000010fd900 Update Available\U2026, ke mask='<none>', action: installUpdate:, standard image: icloud.and.arrow.down, hidden>", "<NSMenuItem: 0x6000010e46e0, ke mask='<none>'>", "<NSMenuItem: 0x6000010e4780 Start The Thing, ke mask='<none>', action: startTheThing:>", "<NSMenuItem: 0x6000010e4dc0 \U2318-\U232b key detector item, ke mask='<none>', view: <My_StatusItem_App.KeyDetectorView: 0x7f9570c1a010>>", "<NSMenuItem: 0x6000010e4e60, ke mask='<none>'>", "<NSMenuItem: 0x6000010e4f00 saved batches heading item, ke mask='<none>', view: <NSView: 0x7f9570b4be10>, hidden>", "<My_StatusItem_App.BatchMenuItem: 0x6000016e02c0 prototype batch item, ke mask='<none>', action: replaySavedBatch:, submenu: 0x6000034e5340 ()>", "<NSMenuItem: 0x6000010f7d40, ke mask='<none>'>", "<My_StatusItem_App.ClipMenuItem: 0x7f956ef14fd0 prototype copy clip item, ke mask='<none>', action: copyClip:>", "<NSMenuItem: 0x6000010fa620 Settings\U2026, ke='Command-,', action: showSettings:>", "<NSMenuItem: 0x6000010fa6c0, ke mask='<none>'>", "<NSMenuItem: 0x6000010fa760 Quit My StatusItem App, ke='Command-Q', action: quit:>" ) Is this seemingly incorrect inconsistency message harmless? Am I only grasping at straws to think it has some connection to the performance issues with this menu?
3
2
303
3w
SwiftUI resultBuilder foreach
'm trying to write my own stack, and the issue I'm encountering is how to get the child content of a ForEach. // // ContentView.swift // test // // Created by cnsinda on 2025/10/18. // import SwiftUI public struct MyStack<Content: View>: View { var content: [Content] public init(@MyStackBuilder<Content> content: @escaping () -> [Content]) { self.content = content() } public var body: some View { VStack { // I expect to get 9, but it always returns 1. Text("count:\(content.count)") } } } @resultBuilder public enum MyStackBuilder<Value: View> { static func buildBlock() -> [Value] { [] } public static func buildBlock(_ components: Value...) -> [Value] { components } public static func buildBlock(_ components: [Value]...) -> [Value] { components.flatMap { $0 } } // hit public static func buildExpression(_ expression: Value) -> [Value] { [expression] } public static func buildArray(_ components: [[Value]]) -> [Value] { components.flatMap { $0 } } static func buildFinalResult(_ components: [Value]) -> [Value] { components } public static func buildExpression(_ expression: ForEach<[Int], Int, Value>) -> [Value] { expression.data.flatMap { index in [expression.content(index)] } } public static func buildEither(first: [Value]) -> [Value] { return first } public static func buildEither(second: [Value]) -> [Value] { return second } public static func buildIf(_ element: [Value]?) -> [Value] { return element ?? [] } } struct ContentView: View { var body: some View { ZStack { MyStack { ForEach([100, 110, 120, 130, 140, 150, 160, 170, 180], id: \.self) { item in Rectangle().frame(width: item, height: 20).padding(10) } } } .frame(width: 600, height: 600) } } My expectation is to get each individual Rectangle(), but the actual result is that the entire ForEach is treated as a single View. What should I do?
1
0
334
3w
I found a liquid glass bug
When I use rotation3DEffect to rorate a UI element with liquid glass, the liquid glass turns black and expands struct TestCardView: View { @State var rotation:CGFloat = 0.0 @State var vertical: Double = 0 @State var horizontal: Double = 0 var body: some View { ZStack { Image("paintImage") .resizable() .scaledToFill() .ignoresSafeArea() .blur(radius: 10) // Card container ZStack { // Add content here Image("paintImage") .resizable() .clipShape(RoundedRectangle(cornerRadius: 20)) .padding(10) VStack { Spacer() Text("Placeholder text Placeholder text Placeholder text Placeholder text ") .multilineTextAlignment(.center) .padding(12) .glassEffect(.clear, in: RoundedRectangle(cornerRadius: 12, style: .continuous)) .shadow(color: .black.opacity(0.2), radius: 8, x: 0, y: 4) .padding(.bottom, 8) } .padding(25) } .frame(width: 360, height: 600) .clipShape(RoundedRectangle(cornerRadius: 20)) .glassEffect(.clear, in: RoundedRectangle(cornerRadius: 20)) .rotation3DEffect(.degrees(vertical),axis: (x: 1, y: 0, z: 0)) .rotation3DEffect(.degrees(horizontal),axis: (x: 0, y: 1, z: 0)) .gesture( DragGesture(minimumDistance: 0) .onChanged { value in withAnimation{ vertical = min(max(Double(value.translation.height / 10), -20), 20) horizontal = min(max(Double(value.translation.width / 10), -15), 15) } } .onEnded { _ in withAnimation(.easeOut(duration: 0.5)) { vertical = 0 horizontal = 0 } } ) } } }
2
0
77
3w
NavigationPath.append but .navigationDestination Not Being Called
I am trying to do a bit of fancy navigation in SwiftUI using NavigationPath and am having a problem. I have a root view with includes a button: struct ClassListScreen: View { @Bindable private var router = AppRouter.shared @State private var addCourse: Bool = false ... var body: some View { ... Button("Add Class") { router.currentPath.append(addCourse) }.buttonStyle(.borderedProminent) ... .navigationDestination(for: Bool.self){ _ in ClassAddDialog { course in sortCourses() } } } } router.currentPath is the NavigationPath associated with the operative NavigationStack. (This app has a TabView and each Tab has its own NavigationStack and NavigationPath). Tapping the button correctly opens the ClassAddDialog. In ClassAddDialog is another button: struct ClassAddDialog: View { @Bindable private var router = AppRouter.shared @State private var idString: String = "" ... var body: some View { ... Button("Save") { let course = ... ... (save logic) idString = course.id.uuidString var path = router.currentPath path.removeLast() path.append(idString) router.currentPath = path }.buttonStyle(.borderedProminent) ... .navigationDestination(for: String.self) { str in if let id = UUID(uuidString: str), let course = Course.findByID(id, with: context) { ClassDetailScreen(course: course) } } } } My intent here is that tapping the Save button in ClassAddDialog would pop that view and move directly to the ClassDetailScreen (without returning to the root ClassListScreen). The problem is that the code inside the navigationDestination is NEVER hit. (I.e., a breakpoint on the if let ... statement) never fires. I just end up on a (nearly) blank view with a warning triangle icon in its center. (And yes, the back button takes me to the root, so the ClassAddDialog WAS removed as expected.) And I don't understand why. Can anyone share any insight here?
0
0
49
3w
SwiftUI Keyboard Toolbar not Displaying
I'm trying to display a toolbar with a done button on the keyboard. It works in isolation, but within the context of the app, the toolbar doesn't display. The app has Home Screen View with buttons for navigation to other Views within the app, and a controller to keep track of the current view. Each section of the app has its own Navigation Stack. If I skip the main menu, the keyboard toolbar displays, but if I go through the main menu view first, it doesn't. This seems like a bug in SwiftUI to me, but maybe there's something else going on that I'm missing. Any help is appreciated. Here's an extremely simplified example: import SwiftUI @Observable class RootViewController: CustomStringConvertible { var description: String { return switch(currentView) { case .home: "Home" case .formView: "Form View" } } enum Views { case home case formView } public var currentView: Views = .home // This prevents the toolbar from displaying. Change to .formView, and it works. } struct ContentView: View { @State private var rootViewController: RootViewController init(rootViewController: RootViewController) { self.rootViewController = rootViewController } var body: some View { switch rootViewController.currentView { case .formView: FormView() case .home: HomeView(rootViewController) } } } struct FormView: View { @State private var text: String = "" @FocusState private var isInputActive: Bool var body: some View { NavigationStack { Form { TextField("Text", text: $text) .keyboardType(.decimalPad) .focused($isInputActive) Text("Text: \(text)") } .navigationTitle("Keyboard Toolbar Test") .toolbar { ToolbarItemGroup(placement: .keyboard) { Spacer() Button("Close") { isInputActive = false } } } .padding() } } } struct HomeView: View { @State private var rootViewController: RootViewController init(_ rootViewController: RootViewController) { self.rootViewController = rootViewController } var body: some View { Button("Open Form") { rootViewController.currentView = .formView } } } #Preview { ContentView(rootViewController: RootViewController()) }
Topic: UI Frameworks SubTopic: SwiftUI
1
0
123
3w
Drag and Drop Question
This example is based on the latest version of Swift 6.2 for macOS. I have several classes that cannot conform to Codable for various reasons. This, unfortunately, prevents me from using Transferable. If I serialize a class instance into a Data blob and use that for drag-and-drop, it works perfectly — the drag operation succeeds. However, the destination has no way to distinguish between different types of Data blobs. All I’d need is a way to specify a unique identifier and type that I could reference in the drop handler to determine what kind of object I’m working with. Being restricted to Transferable feels quite limiting when your data models can’t conform to Codable. It’s honestly frustrating. Has anyone else run into this issue? Is there a reliable workaround? I tried creating a Transferable wrapper like this: struct CustomObjectTransfer: Codable, Transferable { var data: Data static var transferRepresentation: some TransferRepresentation { // Cannot use '.myGreatSettings' because Main actor–isolated static property 'myGreatSettings' cannot be referenced from a nonisolated context CodableRepresentation(contentType: .init(exportedAs: "com.yourProject.settings")) } } extension UTType { static let myGreatSettings: UTType = UTType("com.yourProject.settings")! } In my list view .draggable ( CustomObjectTransfer(data: myObjectData) ) The UI correctly recognizes the item as draggable. If I misspell the exportedAs identifier, it even throws an error, confirming that the exported type is being recognized by the system. However, the drop destination completely ignores this type: .dropDestination(for: CustomObjectTransfer.self) { items, location in dump(items) return true }isTargeted: { isTargeted in myDestinationIsTargeted = isTargeted } If I switch to using Data.self directly — wrapping the original object data manually — everything works. I can deserialize and validate the data as needed. The problem arises when handling multiple custom drag types. The drop target accepts any data, regardless of its intended type. You only find out the actual type after the drop occurs, during validation — which is too late. By then, isTargeted has already turned true, making the drop appear valid to the user when it actually isn’t. Again anyone else feel this pain? Or is there a workaround that I am missing?
4
0
140
3w
Change popover background color in iOS 26
Is it not possible to change the background color of popovers in iOS 26? The backgroundColor property of UIPopoverPresentationController seems to just get ignored when Liquid Glass is enabled. Here’s a minimal repro: let presentedVC = UIViewController() presentedVC.modalPresentationStyle = .popover presentedVC.view.backgroundColor = .clear let popover = presentedVC.popoverPresentationController popover?.sourceItem = button popover?.backgroundColor = .red present(presentedVC, animated: true) If the UIDesignRequiresCompatibility key is set to YES, then the popover background color works as expected.
Topic: UI Frameworks SubTopic: UIKit
5
0
140
3w
Confirmation dialog in NavigationStack toolbar button appears inconsistently or in wrong position
Hello, I’m encountering an issue with a confirmation dialog presented from a toolbar button within a NavigationStack. The dialog rarely appears, and when it does, it sometimes shows up in unexpected positions on the screen. The view is presented in a sheet. Environment: • Xcode 26.0.1 • iOS 26.0 (iPhone 17 Pro Simulator) Has anyone else experienced this behavior or found a reliable workaround? Here is the video of the issue: Video And the warning that occurs when I press the button: Dismissing a zoom transition to a view not in the view hierarchy will trigger a fallback transition. To correct the error, be sure to a provide a view that's visible and in a window. View: <_UINavigationBarPlatterGlassView: 0x1200e46d0> → <_UINavigationBarPlatterContentView: 0x1200e4510> → <_UINavigationBarPlatterAnimationView: 0x1200e4360> → <_UINavigationBarPlatterAnimationView: 0x1200e41b0> → <_UINavigationBarPlatterAnimationView: 0x1200e4000> → <_UINavigationBarPlatterAnimationView: 0x1200951f0> → <_UINavigationBarPlatterView: 0x1200e3d20> → <UIKit.NavigationBarPlatterContainer: 0x12028c850> → <UIKit.NavigationBarTransitionContainer: 0x12029c8b0> → <UIKit.NavigationBarContentView: 0x106b91400> → <SwiftUI.UIKitNavigationBar: 0x12029c600> → <UILayoutContainerView: 0x1202c05d0; name=UILayoutContainerView (SwiftUI.UIKitNavigationController)>
1
0
90
4w
In iOS26, UITableview can't display cell,but cells can be selected!
We have received several cases that our app can not display uitableview cell in iOS26, but users said that they can select cells with single tab and the uitableview didselectcell delegate can response! I have reported a feedback but no response. Does anyone have the same bugs with me? You guys can see that the page is blank, I have a video a user sent to me can proved that he can select cell with gesture. We cannot reproduce the bug and don't konw how to fixed, we think this is the bug with iOS26, so here for some help. This bug block our distribution of new version(support iOS26) This is the feedback https://feedbackassistant.apple.com/feedback/20677046
1
0
100
4w
Incorrect system color on popover view, and does not update while switching dark mode on iOS 26 beta 3
All system colors are displayed incorrectly on the popover view. Those are the same views present as a popover in light and dark mode. And those are the same views present as modal. And there is also a problem that when the popover is presented, switching to dark/light mode will not change the appearance. That affected all system apps. The following screenshot is already in dark mode. All those problem are occured on iOS 26 beta 3.
4
0
376
4w
How to hide supplementary column alone in three column split view
We are using three column split view as root of our app and wants to hide the supplementary column alone in some cases and behaves like two column split view. With the existing apis we are unable to achieve this since it hides primary column as well and not giving expected results. .hide(.supplementary) setViewController(nil, for: .supplementary) But seen this behavior in Native Notes app when using the View as List and Gallery option. is there any way to achieve this with maintaining three column split view itself ?
1
0
112
4w
How to temporarily hide another app's Dynamic Island?
Hello, I have a question regarding the control over the Dynamic Island UI when my app is in the foreground. Scenario: A user is playing a song on Apple Music, so its Live Activity is active and visible in the Dynamic Island. Then, the user opens my app. Desired Behavior: While my app is in the foreground, I would like to temporarily hide or dismiss the dynamic island from Apple Music to provide a more immersive experience. When the user navigates away from my app, it's perfectly fine for the Dynamic Island to show dynamic island again. Is there an API that allows an app to temporarily suppress a Live Activity that was initiated by another application? My understanding of the iOS sandbox model suggests this might not be possible for security and privacy reasons, but I wanted to confirm if there's an intended way to handle this, especially for full-screen apps like games or video players. Thank you!
2
0
55
4w