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

Replacement for ToolbarItems with .bottomBar placement in iOS 26 TabView?
Prior to iOS 26, ToolbarItems with .bottomBar placement were convenient for tab-specific frequent actions. With iOS 26’s new tab layering now obscuring such ToolbarItems, it’s unclear whether .tabViewBottomAccessory is the intended replacement or if another pattern (like persistent floating buttons) is encouraged instead. What’s the recommended way to support quick, tab-specific actions under the new system? I’ve tried conditionally rendering a .tabViewBottomAccessory based on the active tab, but this causes a crash, which I’ve reported as FB18479195.
4
2
358
Jul ’25
Source item disappears after swipe-back with .navigationTransition(.zoom)
[Submitted as FB21078443] When using .matchedTransitionSource with .navigationTransition(.zoom), swiping back from the left edge to return from a detail view causes the source item to disappear once the transition finishes. It’s only a visual issue—the item is still there and can be tapped to open again. This doesn’t happen when using the Back button; only the swipe-back gesture triggers it. Also, it only reproduces on a physical device, not in Simulator. SYSTEM INFO Xcode 26.1.1 (17B100) macOS 26.1 (25B78) iOS 26.1 (23B85) iOS 26.2 (23C5044b) REPRO STEPS Run the code below on a physical device, tap an image, then swipe from the left edge to dismiss the detail view. ACTUAL The image zooms back to its origin, then disappears once the animation settles. EXPECTED The image card remains visible. SCREENSHOTS CODE import SwiftUI struct Item: Identifiable, Hashable { let id = UUID() let imageName: String let title: String } struct ContentView: View { @Namespace private var namespace let items = [ Item(imageName: "SampleImage", title: "Sample Card 1"), Item(imageName: "SampleImage2", title: "Sample Card 2") ] var body: some View { NavigationStack { ScrollView { VStack(spacing: 16) { ForEach(items) { item in NavigationLink(value: item) { CardView(item: item) .matchedTransitionSource(id: item.id, in: namespace) } .buttonStyle(.plain) } } .padding() } .navigationTitle("Zoom Transition Issue") .navigationSubtitle("Tap image, then swipe back from left edge") .navigationDestination(for: Item.self) { item in DetailView(item: item, namespace: namespace) .navigationTransition(.zoom(sourceID: item.id, in: namespace)) } } } } struct CardView: View { let item: Item var body: some View { GeometryReader { geometry in ZStack(alignment: .bottom) { Image(item.imageName) .resizable() .scaledToFill() .frame(width: geometry.size.width, height: geometry.size.height) .clipped() } } .frame(height: 200) .clipShape(RoundedRectangle(cornerRadius: 16)) } } struct DetailView: View { let item: Item let namespace: Namespace.ID var body: some View { Image(item.imageName) .resizable() .scaledToFill() .clipped() } }
Topic: UI Frameworks SubTopic: SwiftUI
2
2
119
Nov ’25
iOS 26 RC: Scope button in stacked UISearchBar block touches
This is really odd. If you setup a UISearchController with a preferredSearchBarPlacement of .stacked and you setup the search bar with scope buttons, then when the view controller is initially displayed, the currently hidden scope buttons block touch events from reaching the main view just below the search bar. But once the search is activated and dismissed, then the freshly hidden scope buttons no longer cause an issue. This is easily demonstrated by putting a UITableViewController in a UINavigationController. Setup the table view to show a few simple rows. Then setup a search controller using the following code: func setupSearch() { // Setup a stacked search bar with scope buttons // Before the search is ever activated, the hidden scope buttons block any touches in the main view controller // in the area just below the search bar. // Once the search is activated and dismissed, the problem goes away. It seems that displaying and hiding the // scope buttons at least once fixes the issue that exists beforehand. // This issue only exists in iOS/iPadOS 26, not iOS/iPadOS 18 or earlier. let search = UISearchController(searchResultsController: UIViewController()) search.hidesNavigationBarDuringPresentation = true search.obscuresBackgroundDuringPresentation = true search.scopeBarActivation = .onSearchActivation // Ensure button appear immediately let searchBar = search.searchBar searchBar.scopeButtonTitles = [ "One", "Two", "Three" ] self.navigationItem.searchController = search self.navigationItem.hidesSearchBarWhenScrolling = false // Issue appears even if this is true self.navigationItem.preferredSearchBarPlacement = .stacked } When first shown, before any attempt is made to activate the search, any attempt to tap on the upper 2/3 of the first row in the table view (which is just below the search bar) fails. If you tap on the lower 1/3 of the first row it works fine. If you then activate the search (now the scope buttons appear) and then dismiss the search (now the scope buttons are hidden again), then there is no issue tapping anywhere on the first row of the table. But if you restart the app, the problem starts over again. This problem happens on any iPhone or iPad, real or simulated, running iOS/iPadOS 26 RC. This is a regression from iOS 18 or earlier.
3
2
513
Nov ’25
Show main window of SwiftUI app on macOS Sequoia after auto start
It seems like it is no longer possible to open the main window of an app after the app has been launched by the system if the "Auto Start" functionality has been enabled. I am using SMAppService.mainApp to enable to auto start of my app. It is shown in the macOS system settings and the app is automatically started - but the main window is not visible. How can I change this behaviour so the main window of the app is always visible when started automatically? I have not noticed this behaviour before the release of macOS Sequoia. My app is using Swift 6 and the latest version of macOS and Xcode. Regards
Topic: UI Frameworks SubTopic: SwiftUI
7
2
853
Apr ’25
UITextView crash on iOS 18.4 beta
UITextView crash when setting attributed text that contains substring ffi and attributedText contains NSFontAttributeName, NSForegroundColorAttributeName Reproducible case: UITextView *textView = [[UITextView alloc] init]; textView.attributedText = [[NSAttributedString alloc] initWithString:@"ffi" attributes:@{ NSParagraphStyleAttributeName: [self createParagraphOfLineHeight:20], NSFontAttributeName: [UIFont systemFontOfSize:fontSize weight:UIFontWeightRegular], NSForegroundColorAttributeName: UIColor.black }];
Topic: UI Frameworks SubTopic: UIKit Tags:
9
2
2.2k
May ’25
Picking image in iOS-first app when running it on macOS 26
An app that is capable of running on iPad can be usually run on Mac if properly designed and that's great. Recently I've tried to launch one of my old apps on macOS 26 in "Designed for iPad" mode and noticed that image picker behaves oddly. Images are barely selectable, you have to click several times and yet it might select image and might not. On iPhone and on iPad any kind of image picking works fine. I've tried all kinds of native pickers (PhotosPicker, PHPickerViewController, UIImagePickerController), but the result is almost the same. So how should I nowadays do image picking in (mostly) iOS app when it is run on macOS? Below is the most canonical and modern code I've tried. The issue is reproduced even with such bare minimum of code with the label not being put to a Form/List or any other factors. import SwiftUI import PhotosUI struct ContentView: View { @State private var selectedItem: PhotosPickerItem? @State private var selectedImage: UIImage? var body: some View { VStack { if let selectedImage { Image(uiImage: selectedImage) .resizable() .scaledToFit() } // Most modern photo library picker, not `PHPickerViewController`, not `UIImagePickerController` based pickerPhotosPicker( selection: $selectedItem, matching: .images ) { Label("Select Photo", systemImage: "photo") } .onChange(of: selectedItem) { newItem inTask { if let data = try? await newItem?.loadTransferable(type: Data.self), let uiImage = UIImage(data: data) { selectedImage = uiImage } } } } } }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
3
0
90
Nov ’25
Menu's primaryAction:{} is broken on latest iOS 26 beta
The following shows minimal example to reproduce the issue: Menu { Button("Test"){} } label: { Text("Menu") } primaryAction: { // Some action } primaryAction modifier will not be called when pressing the menu button/view on iOS 26 beta, long pressing it will open the menu. Was tested on latest iOS 26 beta 8
Topic: UI Frameworks SubTopic: SwiftUI
5
2
301
Nov ’25
TextEditor with a fixedSize and scroll disabled is completely broken
I am trying to build a text editor that shrinks to its content size. The closest I have been able to get has been to add the .scrollDisabled(true) and .fixedSize(horizontal: false, vertical: true) modifiers. This almost achieves what I need. There are two problems though: long single line text gets cut off at the end creating line breaks causes the text editor to grow vertically as expected (uncovering the cut off text in point 1 above). However, when you delete the line breaks, the TextEditor does not shrink again. I have had a radar open for some time: FB13292506. Hopefully opening a thread here will get more visibility. And here is some sample code to easily reproduce the issue: import SwiftUI struct ContentView: View { @State var text = "[This is some long text that will be cut off at the end of the text editor]" var body: some View { TextEditor(text: $text) .scrollDisabled(true) .fixedSize(horizontal: false, vertical: true) } } #Preview { ContentView() } Here is a gif of the behavior:
2
2
1.5k
Mar ’25
Button Glass Style Incorrect in Sheet + ScrollView on Mac Catalyst 26
Hi everyone! I've encountered an issue when using Sheet + ScrollView on Mac Catalyst: the buttons in the toolbar appear with an abnormal gray color. import SwiftUI struct ContentView: View { var body: some View { VStack { } .sheet(isPresented: .constant(true)) { Sheet() } } } struct Sheet: View { var body: some View { NavigationStack { ScrollView { // <-- no issue if use List } .toolbar { Button(action: {}) { // <-- 👀 weird gray color Image(systemName: "checkmark") } } } } } Steps to Reproduce: On macOS 26.0 beta 9, use Xcode 26.0 beta 7 to create an iOS project and enable Mac Catalyst. Paste the code above. Select the Mac Catalyst scheme and run the project. The buttons in the toolbar show a strange gray appearance. If you change the ScrollView to a List in the code, the issue does not occur. FB20120285
2
0
432
Oct ’25
What is the difference between .safeAreaInset and the new .safeAreaBar?
I've been trying out the new .safeAreaBar modifier for iOS 26, but I cannot seem to notice any difference between that and .safeAreaInset? The documentation says: the bar modifier configures the content to support views to automatically extend the edge effect of any scroll view’s the bar adjusts safe area of. But I can't seem to see that in action.
1
2
285
Jul ’25
macOS 26: retain cycle detected when navigation link label contains a Swift Chart
I'm running into an issue where my application will hang when switching tabs. The issue only seems to occur when I include a Swift Chart in a navigation label. The application does not hang If I replace the chart with a text field. This appears to only hang when running on macOS 26. When running on iOS (simulator) or visionOS (simulator, on-device) I do not observe a hang. The same code does not hang on macOS 15. Has any one seen this behavior? The use case is that my root view is a TabView where the first tab is a summary of events that have occurred. This summary is embedded in a NavigationStack and has a graph of events over the last week. I want the user to be able to click that graph to get additional information regarding the events (ie: a detail page or break down of events). Initially, the summary view loads fine and displays appropriately. However, when I switch to a different tab, the application will hang when I switch back to the summary view tab. In Xcode I see the following messages === AttributeGraph: cycle detected through attribute 162104 === === AttributeGraph: cycle detected through attribute 162104 === === AttributeGraph: cycle detected through attribute 162104 === === AttributeGraph: cycle detected through attribute 162104 === === AttributeGraph: cycle detected through attribute 162104 === A simple repro is the following import SwiftUI import Charts @main struct chart_cycle_reproApp: App { var body: some Scene { WindowGroup { TabView { Tab("Chart", systemImage: "chart.bar") { NavigationStack { NavigationLink { Text("this is an example of clicking the chart") } label: { Chart { BarMark( x: .value("date", "09/03"), y: .value("birds", 3) ) // additional marks trimmed } .frame(minHeight: 200, maxHeight: .infinity) } } } Tab("List", systemImage: "list.bullet") { Text("This is an example") } } } } }
3
2
249
Nov ’25
Accessibility Permission In Sandbox For Keyboard
Hello! My question is about 1) if we can use any and or all accessibility features within a sandboxed app and 2) what steps we need to take to do so. Using accessibility permissions, my app was working fine in Xcode. It used NSEvent.addGlobalMonitorForEvents and localMoniter, along with CGEvent.tapCreate. However, after downloading the same app from the App Store, the code was not working. I believe this was due to differences in how permissions for accessibility are managed in Xcode compared to production. Is it possible for my app to get access to all accessibility features, while being distributed on the App Store though? Do I need to add / request any special entitlements like com.apple.security.accessibility? Thanks so much for the help. I have done a lot of research on this online but found some conflicting information, so wanted to post here for a clear answer.
8
0
455
Oct ’25
SpriteKit/RealityKit + SwiftUI Performance Regression on iOS 26
Hi, Toggling a SwiftUI menu in iOS 26 significantly reduces the framerate of an underlying SKView or ARView. Below are test cases for SpriteKit and RealityKit. I ran these tests on iOS 26.1 Beta using an iPhone 13 (A15 chip). Results were similar on iOS 26.0.1. Both scenes consist of circles and balls bouncing on the ground. The restitution of the physics bodies is set for near-perfect elasticity, so they keep bouncing indefinitely. In both SKView and ARView, the framerate drops significantly whenever the SwiftUI menu is toggled. The menu itself is simple and uses standard SwiftUI animations and styling. SpriteKit import SpriteKit import SwiftUI class SKRestitutionScene: SKScene { override func didMove(to view: SKView) { view.contentMode = .center size = view.bounds.size scaleMode = .resizeFill backgroundColor = .darkGray anchorPoint = CGPoint(x: 0.5, y: 0.5) let groundWidth: CGFloat = 300 let ground = SKSpriteNode(color: .gray, size: CGSize(width: groundWidth, height: 10)) ground.physicsBody = SKPhysicsBody(rectangleOf: ground.size) ground.physicsBody?.isDynamic = false addChild(ground) let circleCount = 5 let spacing: CGFloat = 60 let totalWidth = CGFloat(circleCount - 1) * spacing let startX = -totalWidth / 2 for i in 0..<circleCount { let circle = SKShapeNode(circleOfRadius: 18) circle.fillColor = .systemOrange circle.lineWidth = 0 circle.physicsBody = SKPhysicsBody(circleOfRadius: 18) circle.physicsBody?.restitution = 1 circle.physicsBody?.linearDamping = 0 let x = startX + CGFloat(i) * spacing circle.position = CGPoint(x: x, y: 150) addChild(circle) } } override func willMove(from view: SKView) { self.removeAllChildren() } } struct SKRestitutionView: View { var body: some View { ZStack { SpriteView(scene: SKRestitutionScene(), preferredFramesPerSecond: 120) .ignoresSafeArea() VStack { Spacer() Menu { Button("Edit", systemImage: "pencil") {} Button("Share", systemImage: "square.and.arrow.up") {} Button("Delete", systemImage: "trash") {} } label: { Text("Menu") } .buttonStyle(.glass) } .padding() } } } #Preview { SKRestitutionView() } RealityKit import RealityKit import SwiftUI struct ARViewPhysicsRestitution: UIViewRepresentable { let arView = ARView() func makeUIView(context: Context) -> some ARView { arView.contentMode = .center arView.cameraMode = .nonAR arView.automaticallyConfigureSession = false arView.environment.background = .color(.gray) // MARK: Root let anchor = AnchorEntity() arView.scene.addAnchor(anchor) // MARK: Camera let camera = Entity() camera.components.set(PerspectiveCameraComponent()) camera.position = [0, 1, 4] camera.look(at: .zero, from: camera.position, relativeTo: nil) anchor.addChild(camera) // MARK: Ground let groundWidth: Float = 3.0 let ground = Entity() let groundMesh = MeshResource.generateBox(width: groundWidth, height: 0.1, depth: groundWidth) let groundModel = ModelComponent(mesh: groundMesh, materials: [SimpleMaterial(color: .white, roughness: 1, isMetallic: false)]) ground.components.set(groundModel) let groundShape = ShapeResource.generateBox(width: groundWidth, height: 0.1, depth: groundWidth) let groundCollision = CollisionComponent(shapes: [groundShape]) ground.components.set(groundCollision) let groundPhysicsBody = PhysicsBodyComponent( material: PhysicsMaterialResource.generate(friction: 0, restitution: 0.97), mode: .static ) ground.components.set(groundPhysicsBody) anchor.addChild(ground) // MARK: Balls let ballCount = 5 let spacing: Float = 0.4 let totalWidth = Float(ballCount - 1) * spacing let startX = -totalWidth / 2 let radius: Float = 0.12 let ballMesh = MeshResource.generateSphere(radius: radius) let ballMaterial = SimpleMaterial(color: .systemOrange, roughness: 1, isMetallic: false) let ballShape = ShapeResource.generateSphere(radius: radius) for i in 0..<ballCount { let ball = Entity() let ballModel = ModelComponent(mesh: ballMesh, materials: [ballMaterial]) ball.components.set(ballModel) let ballCollision = CollisionComponent(shapes: [ballShape]) ball.components.set(ballCollision) var ballPhysicsBody = PhysicsBodyComponent( material: PhysicsMaterialResource.generate(friction: 0, restitution: 0.97), /// 0.97 for near perfect elasticity mode: .dynamic ) ballPhysicsBody.linearDamping = 0 ballPhysicsBody.angularDamping = 0 ball.components.set(ballPhysicsBody) let shadow = GroundingShadowComponent(castsShadow: true) ball.components.set(shadow) let x = startX + Float(i) * spacing ball.position = [x, 1, 0] anchor.addChild(ball) } return arView } func updateUIView(_ uiView: UIViewType, context: Context) { } } struct PhysicsRestitutionView: View { var body: some View { ZStack { ARViewPhysicsRestitution() .ignoresSafeArea() .background(.black) VStack { Spacer() Menu { Button("Edit", systemImage: "pencil") {} Button("Share", systemImage: "square.and.arrow.up") {} Button("Delete", systemImage: "trash") {} } label: { Text("Menu") } .buttonStyle(.glass) } .padding() } } } #Preview { PhysicsRestitutionView() }
2
0
257
Oct ’25
How to prevent VoiceOver from reading text INSIDE an image?
In the example below, VoiceOver (in both iOS 18 and 26) reads the text contained within the image after the .accessibilityLabel, introduced by a “beep.” VoiceOver: Purple rounded square with the word 'Foo' in white letters. Image [beep] foo. I’d like it to only read the accessibility label. As a developer focused on accessibility, I make sure every image already has an appropriate label, so having iOS read the image text is redundant. Sample Code import SwiftUI struct ContentView: View { var body: some View { Image("TextInImage") .resizable() .scaledToFit() .frame(width: 64, height: 64) .accessibilityLabel("Purple rounded square with the word 'Foo' in white letters.") } } Sample Image Drop this image in to Assets.xcassets and confirm it's named TextInImage.
4
0
273
Oct ’25
Concentricity not working
This line in the WWDC25: Build a SwiftUI app with the new design talk, Doesn't work. no .rect is not member and neither corner a parameter or containerConcentric listed. Help .background(.tint, in: .rect(corner: .containerConcentric))
Topic: UI Frameworks SubTopic: SwiftUI
2
2
186
Jul ’25
ForEach with binding seems to be broken in iOS 18.3.1 and iOS 18.4
Super easy to reproduce. Swiping to delete on the last remaining item in the list causes an index out of bounds exception. If you have 2 items in your list, it will only happen when you delete the last remaining item. From my testing, this issue occurs on 18.3.1 and onward (the RC it happens). I didn't test 18.3.0 so it might happen there as well. The only workarounds I have found is to add a delay before calling my delete function: OR to comment out the Toggle. So it seems as though iOS 18.3.x added a race condition in the way the ForEach accesses the values in its binding. Another thing to note, this also happens with .swipeActions, EditMode, etc... any of the built in ways to delete an item from a list. import SwiftUI struct ContentView: View { @StateObject var viewModel = ContentViewModel() var body: some View { List { ForEach($viewModel.items) { $item in HStack { Image(systemName: "globe") .imageScale(.large) .foregroundStyle(.tint) Text($item.text.wrappedValue) Spacer() Toggle(String(""), isOn: $item.isActive) .labelsHidden() } } .onDelete(perform: delete) } } func delete(at offsets: IndexSet) { // uncomment task to make code not crash // Task { viewModel.deleteItem(at: offsets) // } } } struct MyItem: Identifiable { var id: UUID = UUID() var text: String var isActive: Bool } class ContentViewModel: ObservableObject { @Published var items: [MyItem] = [MyItem(text: "Hello, world!", isActive: false)] func deleteItem(at offset: IndexSet) { items.remove(atOffsets: offset) } }
1
2
122
Mar ’25
iOS 26 (beta 7) setting .searchFocused programmatically does not work
Already filed a feedback in case this is a bug, but posting here in case I'm doing something wrong? I'd like the search field to automatically be displayed with the keyboard up when the view appears. This sample code works in iOS 18, but it does not work in iOS 26 beta 7 I also tried adding a delay to setting searchIsFocused = true but that did not help struct ContentView: View { var body: some View { NavigationStack { NavigationLink(destination: ListView()) { Label("Go to list", systemImage: "list.bullet") } } .ignoresSafeArea() } } struct ListView: View { @State private var searchText: String = "" @State private var searchIsPresented: Bool = false @FocusState private var searchIsFocused: Bool var body: some View { ScrollView { Text("Test") } .searchable(text: $searchText, isPresented: $searchIsPresented, placement: .automatic, prompt: "Search") .searchFocused($searchIsFocused) .onAppear { searchIsFocused = true } } }
5
1
174
Oct ’25