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

How to Start with Default Apple Maps Functionality in iOS 18+
Hi everyone, I’m building an iOS 18+ app in Xcode where Apple Maps is central. My goal is to start with the default Apple Maps experience (map view, search bar, pins, directions sheet, etc.) and then customize it for my project. I tried coding it from scratch using MapKit and SwiftUI, but I wasn’t able to get full parity with the basic features of the Maps app. My questions: Is there any sample project, template, or reference that provides the default Apple Maps functionality (views + interactions) as a baseline? Can I copy these into my Xcode project and then extend/customize them? If not, what’s the recommended best practice to get as close as possible to the native Maps app before adding my own features? Any guidance, sample code, or documentation links would be greatly appreciated.
1
0
92
3w
iOS 26, SwiftUI .sheet Background Color has Gray/Green Tint on iPad
On iPadOS 26 (up to beta 7), .sheet backgrounds have a dark green tint on Dark Mode and a gray tint on Light Mode. This is clearly noticeable on both the Canvas/Simulator and a physical device. Here's a sample View that shows the issue: import SwiftUI struct ContentView: View { @State private var isPresenting: Bool = false var body: some View { VStack { Image(systemName: "globe") .imageScale(.large) .foregroundStyle(.tint) Text("Hello, world!") Button("Show Sheet") { isPresenting.toggle() } } .sheet(isPresented: $isPresenting) { VStack { HStack { Spacer() Button("Cancel", systemImage: "xmark.circle.fill") { } .foregroundStyle(.secondary) .labelStyle(.iconOnly) .buttonStyle(.plain) .contentShape(.circle) } TabView { Tab("Tab 1", systemImage: "cart") { Text("Hello, tab 1") } Tab("Tab 2", systemImage: "cart") { Text("Hello, tab 2") } } } .scenePadding() } .padding() .preferredColorScheme(.dark) } } #Preview { ContentView() } Is this the expected behavior with the new OS? Anyone else seeing this?
Topic: UI Frameworks SubTopic: SwiftUI
1
0
157
3w
How to reduce cell height (vertical margins) when using UIListContentConfiguration
The default cell height is 44pt in iOS 18 and 52pt in iOS 26. I'm trying to reduce the height back to 44pt in one screen that needs to fit as much content on screen as possible. How do you do that when using UIListContentConfiguration? I expected this would do the trick but alas it doesn't reduce the cell height. let cellRegistration = UICollectionView.CellRegistration<UICollectionViewListCell, Item> { cell, indexPath, item in cell.contentConfiguration = { var config = UIListContentConfiguration.valueCell() config.text = "Title" config.secondaryText = "Value" // This only removes horizontal margins, does not change vertical margins config.axesPreservingSuperviewLayoutMargins = [] config.directionalLayoutMargins = .zero return config }() }
Topic: UI Frameworks SubTopic: UIKit Tags:
4
0
110
3w
How can I connect NSTableCellView.textField to a SwiftUI view?
When using NSTableView or NSOutlineView, if you use an NSTableCellView and wire up the .imageView and .textField properties then you get some "free" behaviour with respect to styling and sizing of those fields. (ex: They reflect the user's preferred "Sidebar Icon Size" as selected in Settings. ) If I'm using a SwiftUI View inside an NSTableCellView, is there any way to connect a Text or Image to those properties? Consider the following pseudo code: struct MyCellView: View { let text: String let url: URL? var body: some View { HStack { Image(...) // How to indicate this is .imageView? Text(...) // How to indicate this is .textField? } } } final class MyTableCellView: NSTableCellView { private var hostingView: NSHostingView<MyCellView>! init() { self.hostingView = NSHostingView(rootView: MyCellView(text: "", url: nil)) self.addSubview(self.hostingView) } func configureWith(text: String, url: URL) { let rootView = MyCellView(text: text, url: url) hostingView.rootView = rootView // How can I make this connection? self.textField = rootView.??? self.imageView = rootView.??? } } I'm ideally looking for a solution that works on macOS 15+.
2
0
85
3w
[iOS 26] UIVideoEditorController preview's top bar is overlapping with parent view controller
Applicaiton is built with WebKit and native camera view controller . Issue is seen always when presenting a UIVideoEditorController class on top of MainVC(webKit). Please refer the attached image Code: self.videoEditor.modalPresentationStyle = UIModalPresentationFullScreen; [viewController presentViewController:self.videoEditor animated: YES completion:nil];
3
0
95
3w
CarPlay CPGridTemplate – buttons show in a row, and limited to 9 buttons
Hi, I’m working with CPGridTemplate in CarPlay. According to the documentation, it supports up to 9 CPGridButton objects and should display them in a grid (up to 3×3). However, I’ve run into two issues: Row instead of grid When I add 4–6 buttons, they don’t appear in a 2×2 or 2×3 grid. Instead, they are shown in a single horizontal row. Even 9 buttons do not appear in a 3x3 grid. More than 9 buttons My use case requires more than 9 icons, but it looks like CPGridTemplate ignores any additional buttons beyond the first 9. Is there any supported way to display more than 9 buttons in a grid, or is pagination/multiple templates the only option? Thanks in advance!
1
0
57
3w
Recommended Approach for Handling Multiple UIButton Events: Single Handler vs Multiple Selectors?
I’m working with UIButton and finding different examples for event handling. Currently, I have a single action method like this, which receives the sender and the UIEvent: @objc func buttonHandler(_ sender: UIButton, forEvent event: UIEvent) { if let touches = event.allTouches, let touch = touches.first { switch touch.phase { case .began: print("TouchDown") case .ended: if sender.bounds.contains(touch.location(in: sender)) { print("TouchUpInside") } else { print("TouchUpOutside") } case .cancelled: print("TouchCancel") default: break } } if event.type == .presses { print("PrimaryActionTriggered") } } Is this considered best/recommended practice in UIKit, or should I use separate selector methods for each event type (e.g. .touchDown, .touchUpInside, .touchUpOutside) using addTarget(_:action:for:)? Are there any advantages or disadvantages to using a single handler with UIEvent versus multiple selectors for UIControlEvents? Thanks in advance!
Topic: UI Frameworks SubTopic: UIKit Tags:
0
0
47
3w
How to identify which UIControl.Event triggered a common selector for UIButton?
I’m working with UIButton and I’d like to register multiple UIControl.Events (e.g. .touchUpInside, .touchDown, .touchCancel, .primaryActionTriggered) using the same selector. For example: button.addTarget(self, action: #selector(handleButtonEvent(_:forEvent:)), for: [.touchUpInside, .touchDown, .touchCancel, .primaryActionTriggered]) @objc func handleButtonEvent(_ sender: UIButton, forEvent event: UIEvent) { // How do I tell which UIControl.Event triggered this? } From my understanding: If I use the single-parameter version (@objc func handleButtonEvent(_ sender: UIButton)), I can’t distinguish which event fired. If I use the two-parameter version with UIEvent, I can inspect touch.phase or event.type, but that feels indirect. Questions: Is there a recommended way to directly know which UIControl.Event caused the selector to fire? Is sharing a single selector across multiple control events considered a good practice, or is it more common to register separate selectors per event? Would appreciate guidance on what Apple recommends here.
Topic: UI Frameworks SubTopic: UIKit Tags:
1
0
39
3w
Recommended way to detect double-tap on UIButton and scope of UIControl.Event
I’m trying to detect a double-tap action on a UIButton. There seem to be two possible approaches: Using a UITapGestureRecognizer with numberOfTapsRequired = 2. Using the .touchDownRepeat event of UIControl.Event. What is the recommended approach for reliably handling double-taps on UIButton? Are there any practical differences in terms of behavior, performance, or best practices between these two methods? Additionally, I noticed that UIControl.Event defines a large set of events (like .editingChanged, .valueChanged, etc.). Can all these events be applied to any UIControl subclass such as UIButton, or are they only valid for specific controls like UITextField, UISlider, etc.? If not all events are supported by all controls, what is the rationale behind exposing them under a shared UIControl.Event enum? Thanks in advance!
Topic: UI Frameworks SubTopic: UIKit Tags:
3
0
59
3w
Keyboard Toolbar Padding iOS26
When I create a SwiftUI toolbar item with placement of .keyboard on iOS 26, the item appears directly on top of and in contact with the keyboard. This does not look good visually nor does it match the behavior seen in Apple's apps, such as Reminders. Adding padding to the contents of the toolbar item only expands the size of the item but does not separate the capsule background of the item from the keyboard. How can I add vertical padding or spacing to separate the toolbar item capsule from the keyboard?
Topic: UI Frameworks SubTopic: SwiftUI
3
3
249
3w
DocumentBrowser toolbar behavior in SwiftUI apps
I’m building a document-based SwiftData app (iPhone/iPad/Mac). Here’s a minimal example of how I’m using DocumentGroup. DocumentGroup(editing: Trip.self, contentType: .trips) { ContentView() } if #available(iOS 18.0, *) { DocumentGroupLaunchScene { NewDocumentButton("New Trip") } } I’m struggling with the toolbar behavior in DocumentGroup apps. My content view uses a TabView, and each tab contains a NavigationSplitView. After I select a document in the document browser, I see my tabs. Regardless of which tab is selected, there’s a navigation bar showing the document name and a back button to the document browser. However, only the first tab shows the disclosure button to rename the document. I’d expect to be able to rename the document anywhere the name is shown. When I navigate to the detail view of my NavigationSplitView (or when using NavigationView/NavigationStack), I still see that back button to the document browser. When the user taps it, they expect to go back to the previous view, not to the document browser. What’s really odd is that even sheet or fullScreenCover presentations include these document UI elements in the navigation bar. I can’t get rid of them. Even if I set a title via the toolbar or navigationTitle, the rename disclosure button remains visible. Do DocumentGroup apps intentionally show their specific navigation bar everywhere? Is this a bug or expected behavior? And is it expected that the rename disclosure button appears only on the first tab of a TabView?
4
0
160
3w
NSStatusIcon mysteriously vanishes from menu bar
I have an app who's entire UI is a menu attached to a NSStatusIcon and after doing things in my app that largely work well, sometimes the icon is mysteriously vanishing from menu bar, its menu inaccessible. I've seen it happen when launching normally, freshly built debug builds or release build installed from TestFlight, also launched from Xcode attached to lldb. In the latter case I can poke around in the state of the app but haven't been able to find any answers yet. Things of note: The menu bar icon isn't being removed in any normal fashion, it leaves an unnatural gap in the menu bar when my icon should be. My app isn't crashing, hanging, or getting terminated: as evidenced by seeing it still running within Xcode. A part of my app that runs off a recurring timer responds normally to breakpoints. The NSStatusIcon isn't getting released, its isVisible flag remains true, its button isn't going anywhere and neither is its button image. Nothing interesting is logged to the Xcode console, I haven't found anything interesting in Console.app. Does anyone know the state an app could get into that has this effect on its NSStatusIcon?
Topic: UI Frameworks SubTopic: AppKit
0
0
113
3w
TextKit 2 undocumented and unexpected behavior in textViewportLayoutControllerDidLayout
The NSTextViewportLayoutControllerDelegate.textViewportLayoutControllerDidLayout(_:) documentation states that Layout information on textViewportLayoutController is up-to-date at the point of this call. however it is easy to put the NSTextViewportLayoutController in a state where after calling textViewportLayoutControllerDidLayout, the value of viewportRange is nil (unexpected) and value of the property viewportBounds is .zero The TextKit2 sample application found at https://developer.apple.com/documentation/uikit/using-textkit-2-to-interact-with-text makes that assumption as well, and in few places force unwrap the value of viewportRange, that leads to runtime crashes. This behavior is also discussed in Developer Forum thread about TextKit2 viewport relocation: https://developer.apple.com/forums/thread/761364?answerId=800516022#800516022 How to reproduce: Run Mac target of LayoutWithTextKit2 sample project found at https://developer.apple.com/documentation/uikit/using-textkit-2-to-interact-with-text locate menu.rtf file and duplicate its content several times - the goal is to increase the length of the layout text quickly resize application window - that results in viewport layouts - that result in out-of-bound viewport - that results ina crash OR quickly scroll down/up to the end of the document using scroller bar on the right side of the window Reproducible 100% The situation occurs when the document is not fully laid out, the estimated size (height) of the content exceeds the final (correct) height, and the layoutViewport() function is executed quickly. Resulting in partial viewport layout, and once the viewport moves outside of the document's total height, the viewportLayoutController starts to report viewportRange = nil. FB19698121 Why does it happen? Is it expected? How to recover from that state? And most importantly, how to make the NSTextLayoutManager display the portion of the document that is currently scrolled to. and how to do it without for ce layout the full document on each viewportLayout()
1
0
109
3w
Sharelink dismisses Parent View
Hello Folks, what's causing the "smart" dismiss after shareLink? this only happens when saving the photos. view -> opens a popover -> sharelink -> save to photo -> Allow photo Access -> ✅ view -> opens a popover -> sharelink -> save to photo -> [Observe popover dismisses ❌] popover should stay open Remember to add INFOPLIST_KEY_NSPhotoLibraryAddUsageDescription = save to album in project settings import SwiftUI @main struct sharepopoverDismissApp: App { var body: some Scene { WindowGroup { ContentView() } } } struct ContentView: View { @State private var showingSharePopover = false @State private var urlToShare: URL = Bundle.main.url(forResource: "BigBuckBunny", withExtension: "mp4") ?? URL(string: "https://www.example.com")! var body: some View { VStack { Button { showingSharePopover = true } label: { Label("Show Share Options", systemImage: "square.and.arrow.up") .font(.title2) .padding(.vertical, 10) .padding(.horizontal, 20) } .buttonStyle(.borderedProminent) .tint(.indigo) .controlSize(.large) .shadow(radius: 5) .popover(isPresented: $showingSharePopover, attachmentAnchor: .point(.center)) { ShareLinkPopoverView(url: urlToShare) } } .padding() } } struct ShareLinkPopoverView: View { let url: URL var body: some View { VStack(spacing: 20) { ShareLink(item: url) { Label("Share Now", systemImage: "square.and.arrow.up") .font(.headline) .padding(.vertical, 8) .padding(.horizontal, 15) } .interactiveDismissDisabled() .buttonStyle(.borderedProminent) .tint(.green) .controlSize(.regular) } .padding(20) .presentationCompactAdaptation(.popover) } }
3
0
120
3w
NSTableView.reloadData(forRowIndexes:columnIndexes:) causes wrong subview layout when usesAutomaticRowHeights = true
I have a table view where each row has two labels, one left-aligned and one right-aligned. I would like to reload a single row, but doing so causes the right-aligned label to hug the left-aligned label. Before the reload: After the reload: Reloading the whole table view instead, or disabling automatic row height, solves the issue. Can a single row be reloaded without resorting to these two workarounds? I created FB13534100 1.5 years ago but got no response. class ViewController: NSViewController, NSTableViewDataSource, NSTableViewDelegate { override func loadView() { let tableView = NSTableView() tableView.translatesAutoresizingMaskIntoConstraints = false tableView.dataSource = self tableView.delegate = self tableView.usesAutomaticRowHeights = true let column = NSTableColumn() column.width = 400 tableView.addTableColumn(column) let scrollView = NSScrollView(frame: CGRect(x: 0, y: 0, width: 500, height: 500)) scrollView.translatesAutoresizingMaskIntoConstraints = false scrollView.documentView = tableView view = scrollView Timer.scheduledTimer(withTimeInterval: 2, repeats: false) { _ in print("reload") tableView.reloadData(forRowIndexes: IndexSet(integer: 2), columnIndexes: IndexSet(integer: 0)) // tableView.reloadData() } } func numberOfRows(in tableView: NSTableView) -> Int { return 5 } func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? { let cell = NSTableCellView() let textField1 = NSTextField(labelWithString: "hello") textField1.translatesAutoresizingMaskIntoConstraints = false let textField2 = NSTextField(wrappingLabelWithString: "world") textField2.translatesAutoresizingMaskIntoConstraints = false textField2.alignment = .right let stack = NSStackView(views: [ textField1, textField2 ]) stack.translatesAutoresizingMaskIntoConstraints = false stack.distribution = .fill cell.addSubview(stack) NSLayoutConstraint.activate([stack.topAnchor.constraint(equalTo: cell.topAnchor, constant: 0), stack.leadingAnchor.constraint(equalTo: cell.leadingAnchor, constant: 0), stack.bottomAnchor.constraint(equalTo: cell.bottomAnchor, constant: 0), stack.trailingAnchor.constraint(equalTo: cell.trailingAnchor, constant: 0)]) return cell } }
Topic: UI Frameworks SubTopic: AppKit Tags:
2
0
95
3w
Bypass App Clip Card in Subsequent Advanced Experience Invocations
When an Advanced Experience is created for an App Clip, using the Camera app to scan a QR Code whose URL matches the pattern configured in the Advanced Experience will present the App Clip card. Currently, this App Clip card is presented even if the App Clip or main app is already installed In the device. Is it possible to show the card only when neither the App Clip nor main app is installed? For example: User who does not have the App Clip/main app installed on their device scans a QR code that matches an Advanced Experience User taps the yellow button and sees the App Clip card User taps ”Open” on the card and launches the App Clip, the App Clip is now installed in the device. User returns to the Camera app and scans the same QR code again Camera recognizes the QR code, yellow button appears, user taps it At this point, is it possible for the user to be taken directly to the installed App Clip instead of presenting the App Clip card again?
2
0
131
3w
New window scenes on iPad always take the size of the activating window
I'm using multiple scenes in my iPad app. When I open a new scene from my main window, that new window is always the same size as the previous window. When I make the main window very small and then create a new scene, that new window is also tiny. When I make the main window very big, you guessed it. UIWindowScene.sizeRestrictions does not seem to help here. How can I give new windows a default size (it's okay if they're resizable after presenting)? This is such a weird behavior. Video of the problem in action: https://mastodon.social/@nicoreese/115033539035249909
Topic: UI Frameworks SubTopic: UIKit Tags:
1
0
117
3w
App lifecycle on iPadOS 26
It appears from my testing that the following is true: If you close all windows of an app, the app terminates entirely. Minimizing the last window sends it into multitasking. This is different from previous behavior and might have implications on your app's logic. If you close the last window and quickly tap the app icon again, that same window will come back. Waiting a second before tapping the app icon will bring up the main window (likely because by that point the app was terminated and relaunched). Is this expected behavior? I did not see any announcement of this. I find this a bit counterintuitive and would presume that closing the last window would just send the app to multitasking, just like previously. Quitting the app should be reserved by swiping up on it in the multitasking UI or with a new context menu command.
Topic: UI Frameworks SubTopic: UIKit Tags:
0
0
59
3w