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

.disabled() doesn't VISUALLY disable buttons inside ToolbarItem on iOS 26 devices
[Also submitted as FB19313064] The .disabled() modifier doesn't visually disable buttons inside a ToolbarItem container on iOS 26.0 (23A5297i) devices. The button looks enabled, but tapping it doesn't trigger the action. When deployment target is lowered to iOS 18 and deployed to an iOS 18 device, it works correctly. It still fails on an iOS 26 device, even with an iOS 18-targeted build. This occurs in both the Simulator and on a physical device. Screen Recording Code struct ContentView: View { @State private var isButtonDisabled = false private var osTitle: String { let version = ProcessInfo.processInfo.operatingSystemVersion return "iOS \(version.majorVersion)" } var body: some View { NavigationStack { VStack { Button("Body Button") { print("Body button tapped") } .buttonStyle(.borderedProminent) .disabled(isButtonDisabled) Toggle("Disable buttons", isOn: $isButtonDisabled) Spacer() } .padding() .navigationTitle("Device: \(osTitle)") .navigationBarTitleDisplayMode(.large) .toolbar { ToolbarItem { Button("Toolbar") { print("Toolbar button tapped") } .buttonStyle(.borderedProminent) .disabled(isButtonDisabled) } } } } }
7
3
370
Oct ’25
Navigation title in master splitview panel wrong colour with dark mode and hard scrollEdgeEffect
The navigation title color is wrong (dark on dark background) when applying hard scrolledgeeffectstyle. Illustrated by code example. In simulator or physical device. Changing scrollEdgeEffectStyle to soft resolves the issue. As does changing the listStyle. @main struct AppView: App { var body: some Scene { WindowGroup { NavigationSplitView { NavigationStack { Section { NavigationLink(destination: OptionsView()) { Label("More Options", systemImage: "gearshape") } .isDetailLink(false) } header: { Text("WITH OPTIONS").bold() } .navigationTitle("TESTING") } } detail: { Text("DETAIL") } .preferredColorScheme(.dark) } } } struct OptionsView: View { var body: some View { List { Text("List Item") } .listStyle(.plain) .navigationTitle("MORE OPTIONS TITLE") .scrollEdgeEffectStyle(.hard, for: .all) } } Submittted FB20811402 Bug appears in Landscape mode for iPhone only. Any orientation for iPad.
Topic: UI Frameworks SubTopic: SwiftUI
7
0
158
2w
Illegible navigation title when presenting Map view
When building with the iOS 26 SDK (currently beta 4), the navigation title is often illegible when rendering a Map view. For example, note how the title "Choose Location" is obscured by the map's text ("South America") in the screenshot below: This screenshot is the result of the following view code: import MapKit import SwiftUI struct Demo: View { var body: some View { NavigationStack { Map() .navigationTitle(Text("Choose Location")) .navigationBarTitleDisplayMode(.inline) } } } I tried using the scrollEdgeEffectStyle(_:for:) modifier to apply a scroll edge effect to the top of the screen, in hopes of making the title legible, but that doesn't seem to have any effect. Specifically, the following code seems to produce the exact same result shown in the screenshot above. import MapKit import SwiftUI struct Demo: View { var body: some View { NavigationStack { Map() .scrollEdgeEffectStyle(.hard, for: .top) // ⬅️ no apparent effect .navigationTitle(Text("Choose Location")) .navigationBarTitleDisplayMode(.inline) } } } Is there a recommended way to resolve this issue so that the navigation title is always readable?
7
3
260
Oct ’25
Bug: SwiftUI inspector doesn't update presentation detent selection on iPhone
On iPhone .inspector is presented as a sheet so you can use .presentationDetents to determine its detents. However, SwiftUI doesn't update the presentationDetents selection binding in this case. See attached minimum example of the problem - onChange will not run and print when you swipe and change the detent of the inspector sheet. import SwiftUI @main struct TestingApp: App { var body: some Scene { WindowGroup { ContentView() } } } struct ContentView: View { @State var showInspector = false @State var detent: PresentationDetent = .medium var body: some View { Button("Toggle Inspector") { showInspector.toggle() } .inspector(isPresented: $showInspector) { Text("Inspector Content") .presentationDetents([.medium, .large], selection: $detent) } .onChange(of: detent) { _, detent in print(detent) } } } #Preview { ContentView() }
7
0
259
Oct ’25
Bug in iOS 18 with NSTimeZone and DatePicker
iOS 18 broke some functionality in my Objective-C app with regard to using the DatePicker. The key lines are as follows: datePicker.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:timezoneOffset]; datePicker.date = [NSDate date]; When timezoneOffset is -29380, the value for San Francisco, the Date Picker is a whole MONTH off. It shows November instead of December. But when it is -29359, the value for Seattle, which is in the same time zone (PST), it shows the correct month. In fact, even towns surrounding San Francisco usually return the correct value. Some other cities in other time zones also cause the Date Picker to be a month off.
7
0
740
Jan ’25
App Clip Custom URL not Invoking Clip
Subject: Need Assistance with App Clip Invocation via URL Hello Developers, I’m currently facing an issue with invoking my App Clip through a URL, specifically when the link is shared via iMessage or Email. Instead of launching the App Clip, the URL redirects to the website. Here’s my current configuration: Approved App with an App Clip Universal Links functioning correctly within the App (verified through AASA file hosted on the website) Associated Domain Entitlements included for both the App and the App Clip Universal Link is expected to invoke the App Clip if the App isn’t installed Advanced Experience configured in App Store Connect The default experience URL from App Store Connect successfully triggers the App Clip, but my custom URL does not. I suspect I might be missing a crucial configuration step. Has anyone encountered a similar issue or have suggestions on what else I should verify? Thank you in advance for your help!
7
1
233
Jul ’25
Migrating SwiftUI lifecycle to UIKit's
Hi, everyone I have an app already in production that uses SwiftUI's lifecycle (paired with an AppDelegate). Due to some specific behaviour of the app, we decided to migrate the app to use UIKit's lifecycle, adding the corresponding SceneDelegate to the app, as well as modifying the Info.plist file accordingly to accommodate to these new changes. Although everything seems to work when installing the app from zero, when installing it on top of another version, the screen goes black and the user cannot interact with the app at all unless they reinstall it completely. As I've read online, iOS is reusing the window configuration from the previous execution of the app. I know this because the AppDelegate's application(application:connectingSceneSession:options) is not being called when coming from a previous version of the app. I would love to know what can I do to make this work because, as you may understand, we cannot ask our user base to reinstall the application. Thank you very much.
7
2
1.7k
Apr ’25
App built with Xcode 16 crashes, worked fine with Xcode 15
I'm not a developer, so my knowledge is limited. I only know enough to update the content of my app from time to time using Xcode. The app is database driven and includes hundreds of photos. It has worked fine for years and has never crashed. However, after I updated Xcode to 16.1 my app crashes when I run it on an iOS 18 Simulator. (It works fine on an iOS 17 Simulator.) The problem seems to have something to do with UItableView. Before I spend a lot of $$ for a developer to look into this, I'm wondering if the crashes might be because of a bug that will be fixed in future. Is there any way to tell? I have the crash report, but it's very long so I won't post it unless asked to. If it's helpful, this is the section of code that crashes: // MARK: UITableViewDataSource extension DetailCollectionViewCell: UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { guard let tableViewData = tableViewData else { fatalError("no tableViewData") } **Thread 1: fatal error: No tableViewData** return tableViewData.count
Topic: UI Frameworks SubTopic: UIKit
7
0
1.3k
Dec ’24
I don't want black background in presented sheet
I want a different color, one from my asset catalog, as the background of my first ever swift UI view (and, well, swift, the rest of the app is still obj.c) I've tried putting the color everywhere, but it does't take. I tried with just .red, too to make sure it wasn't me. Does anyone know where I can put a color call that will actually run? Black looks very out of place in my happy app. I spent a lot of time making a custom dark palette. TIA KT @State private var viewModel = ViewModel() @State private var showAddSheet = false var body: some View { ZStack { Color.myCuteBg .ignoresSafeArea(.all) NavigationStack { content .navigationBarTitleDisplayMode(.inline) .toolbar { ToolbarItem(placement: .principal) { Image("cute.image") .font(.system(size: 30)) .foregroundColor(.beigeTitle) } } } .background(Color.myCuteBg) .presentationBackground(.myCuteBg) .sheet(isPresented: $showAddSheet) { AddView() } .environment(viewModel) .onAppear { viewModel.fetchStuff() } } .tint(.cuteColor) } @ViewBuilder var content: some View { if viewModel.list.isEmpty && viewModel.anotherlist.isEmpty { ContentUnavailableView( "No Content", image: "stop", description: Text("Add something here by tapping the + button.") ) } else { contentList } } var contentList: some View { blah blah blah } } First I tried the background, then the presentation background, and finally the Zstack. I hope this is fixed because it's actually fun to build scrollable content and text with swiftUI and I'd been avoiding it for years.
7
0
308
Oct ’25
Set edge effect style in AppKit
In macOS 26 beta 2 it is possible to set an edge effect style via UIKit using the .scrollEdgeEffectStyle property. (note: I haven't tested this, I'm just looking at the documentation). See: https://developer.apple.com/documentation/swiftui/view/scrolledgeeffectstyle(_:for:) Is there an equivalent API for AppKit-based apps? I can't seem to find any additions in NSView or NSScrollView or elsewhere that seem relevant. Scroll edge effects are mentioned in the "Build an AppKit app with the new design" talk here, which heavily implies it must be possible from AppKit: https://developer.apple.com/videos/play/wwdc2025/310/?time=567
7
0
280
Jul ’25
NSScrollView scrolling hitch
When scrolling a basic NSScrollView there seems to be a sudden jump after each flick. Scrolling does not appear smooth and is disorientating. A scroll jump seems to happen directly after letting go of a scroll flick using a trackpad/mouse. Right at that moment the scroll turns into a momentum scroll, slowly decreasing the speed. But the first frame after the gesture the content jumps forward, more than what is expected. Observations: Counterintuitively, scrolling appears to be smoother when disabling NSScrollView.isCompatibleWithResponsiveScrolling. If disabled using a custom NSScrollView subclass there is no large jump anymore. Scrolling also appears to be smoother using a SwiftUI ScrollView. I assume that has the same behaviour as a disabled isCompatibleWithResponsiveScrolling Ironically a WKWebView scrolls much smoother. No sudden jump is observable. It also seems to scroll with faster acceleration, but the individual frames do appear smoother. Why is this better than a native NSScrollView? Elastic scrolling at the bounds of the scroll view also appears much smoother for WKWebViews. When pulling to refresh there is a jump for NSScrollView/SwiftUI, but not for WKWebView. When using an NSScrollView with isCompatibleWithResponsiveScrolling disabled, scrolling appears just as smooth as WKWebView on macOS 13 Ventura and below. On macOS 14 Sonoma scrolling behaviour is suddenly different. Please see a sample project with 4 different scroll views side by side: https://github.com/floorish/ScrollTest Screen recordings show the sudden jumps when scrolling and when elastic scrolling. Tested on Intel & Arm Macs, macOS 11 Big Sur through 15 Sequoia, built with Xcode 16. Should isCompatibleWithResponsiveScrolling be disabled on Sonoma+? Are there any drawbacks? There is also no overdraw anymore since Monterey, as described in https://developer.apple.com/library/archive/releasenotes/AppKit/RN-AppKitOlderNotes/#10_9Scrolling Even with responsive scrolling disabled, why is WKWebView scrolling much smoother than NSScrollView?
Topic: UI Frameworks SubTopic: AppKit Tags:
7
2
648
15h
SwiftData & CloudKit: Arrays of Codable Structs Causing NSKeyedUnarchiveFromData Error
I have SwiftData models containing arrays of Codable structs that worked fine before adding CloudKit capability. I believe they are the reason I started seeing errors after enabling CloudKit. Example model: @Model final class ProtocolMedication { var times: [SchedulingTime] = [] // SchedulingTime is Codable // other properties... } After enabling CloudKit, I get this error logged to the console: 'NSKeyedUnarchiveFromData' should not be used to for un-archiving and will be removed in a future release CloudKit Console shows this times data as "plain text" instead of "bplist" format. Other struct/enum properties display correctly (I think) as "bplist" in CloudKit Console. The local SwiftData storage handled these arrays fine - this issue only appeared with CloudKit integration. What's the recommended approach for storing arrays of Codable structs in SwiftData models that sync with CloudKit?
7
1
340
2d
NSCollectionLayoutBoundarySupplementaryItem background blur covering the entire layout section
My app has the following UI layout: NSSplitViewController as the windows contentViewController NSPageController in the content (right) split item NSTabViewController as the root items of the NSPageController NSViewController with a collection view in the first tab of that NSTabViewController The collection view is using a NSCollectionViewCompositionalLayout in which the sections are set up to have a header using NSCollectionLayoutBoundarySupplementaryItem with pinToVisibleBounds=true and alignment=top With macOS 26, the pinned supplementary item automatically gets a blurred/semi-transparent background that seamlessly integrates with the toolbar. When the window's title bar has a NSTitlebarAccessoryViewController added, the said semi-transparent background gets a bottom hard edge and a hairline to provide more visual separation from the main content. During runtime, my NSPageController transitions from the NSTabViewController to another view controller. When transitioning back, the semi-transparent blur bleeds into the entire section. This happens no matter if there's a NSTitlebarAccessoryViewController added or not. It doesn't happen 100% of the cases, it seems to depend on section size, header visibility and/or scroll position. But it happens more often than not. Most of the time, a second or so after the back transition - shortly after pageControllerDidEndLiveTransition: of the NSPageControllerDelegate is called - the view updates and the supplementary views are back to normal. Sometimes, the issue also appears not when transitioning using NSPageController, but simply by scrolling through the collection view. Anyone has an idea what is happening here? Below are two screenshots of both the "ok" and "not ok" state I'm on macOS 26.0.1 and I'm using XCode 26.0.1
Topic: UI Frameworks SubTopic: AppKit Tags:
7
0
196
2d
How to correctly fetch data using SwiftData
Hi there! I'm making an app that stores data for the user's profile in SwiftData. I was originally going to use UserDefaults but I thought SwiftData could save Images natively but this is not true so I really could switch back to UserDefaults and save images as Data but I'd like to try to get this to work first. So essentially I have textfields and I save the values of them through a class allProfileData. Here's the code for that: import SwiftData import SwiftUI @Model class allProfileData { var profileImageData: Data? var email: String var bio: String var username: String var profileImage: Image { if let data = profileImageData, let uiImage = UIImage(data: data) { return Image(uiImage: uiImage) } else { return Image("DefaultProfile") } } init(email:String, profileImageData: Data?, bio: String, username:String) { self.profileImageData = profileImageData self.email = email self.bio = bio self.username = username } } To save this I create a new class (I think, I'm new) and save it through ModelContext import SwiftUI import SwiftData struct CreateAccountView: View { @Query var profiledata: [allProfileData] @Environment(\.modelContext) private var modelContext let newData = allProfileData(email: "", profileImageData: nil, bio: "", username: "") var body: some View { Button("Button") { newData.email = email modelContext.insert(newData) try? modelContext.save() print(newData.email) } } } To fetch the data, I originally thought that @Query would fetch that data but I saw that it fetches it asynchronously so I attempted to manually fetch it, but they both fetched nothing import SwiftData import SwiftUI @Query var profiledata: [allProfileData] @Environment(\.modelContext) private var modelContext let fetchRequest = FetchDescriptor<allProfileData>() let fetchedData = try? modelContext.fetch(fetchRequest) print("Fetched count: \(fetchedData?.count ?? 0)") if let imageData = profiledata.first?.profileImageData, let uiImage = UIImage(data: imageData) { profileImage = Image(uiImage: uiImage) } else { profileImage = Image("DefaultProfile") } No errors. Thanks in advance
7
0
223
2d
@Transient update doesn't propagate to view
When I update a variable inside my model that is marked @Transient, my view does not update with this change. Is this normal? If I update a non-transient variable inside the model at the same time that I update the transient one, then both changes are propagated to my view. Here is an example of the model: @Model public class WaterData { public var target: Double = 3000 @Transient public var samples: [HKQuantitySample] = [] } Updating samples only does not propagate to my view.
7
8
2.7k
Jun ’25
button is pressed when starting scrolling in iOS 18
On iOS 18, while on a modal screen, if the scrolling starts on a button, that button gets pressed, outside of a modal this doesn't reproduce, also not reproducible on older iOS versions, neither on modals or outside of them. The code to reproduce the issue: import SwiftUI struct ContentView: View { @State var presentModal = false var body: some View { Button(action: { presentModal = true }, label: { Text("open modal") }) .sheet(isPresented: $presentModal, content: { ScrollView { ForEach(0..<100, id: \.self) { index in Button(action: { print("Button \(index) tapped!") }) { Text("Button \(index)") .frame(maxWidth: .infinity) .frame(height: 100) .background(randomColor(for: index)) .padding(.horizontal) } } } }) } func randomColor(for index: Int) -> Color { let hue = Double(index % 100) / 100.0 return Color(hue: hue, saturation: 0.8, brightness: 0.8) } } #Preview { ContentView() }
7
6
685
Jun ’25
SwiftUI Gestures: Sequenced Long Press and Drag
In creating a sequenced gesture combining a LongPressGesture and a DragGesture, I found that the combined gesture exhibits two problems: The @GestureState does not properly update as the gesture progresses through its phases. Specifically, the updating(_:body:) closure (documented here) is only ever executed during the drag interaction. Long presses and drag-releases do not call the updating(_:body:) closure. Upon completing the long press gesture and activating the drag gesture, the drag gesture remains empty until the finger or cursor has moved. The expected behavior is for the drag gesture to begin even when its translation is of size .zero. This second problem – the nonexistence of a drag gesture once the long press has completed – prevents access to the location of the long-press-then-drag. Access to this location is critical for displaying to the user that the drag interaction has commenced. The below code is based on Apple's example presented here. I've highlighted the failure points in the code with // *. My questions are as follows: What is required to properly update the gesture state? Is it possible to have a viable drag gesture immediately upon fulfilling the long press gesture, even with a translation of .zero? Alternatively to the above question, is there a way to gain access to the location of the long press gesture? import SwiftUI import Charts enum DragState { case inactive case pressing case dragging(translation: CGSize) var isDragging: Bool { switch self { case .inactive, .pressing: return false case .dragging: return true } } } struct ChartGestureOverlay<Value: Comparable & Hashable>: View { @Binding var highlightedValue: Value? let chartProxy: ChartProxy let valueFromChartProxy: (CGFloat, ChartProxy) -> Value? let onDragChange: (DragState) -> Void @GestureState private var dragState = DragState.inactive var body: some View { Rectangle() .fill(Color.clear) .contentShape(Rectangle()) .onTapGesture { location in if let newValue = valueFromChartProxy(location.x, chartProxy) { highlightedValue = newValue } } .gesture(longPressAndDrag) } private var longPressAndDrag: some Gesture { let longPress = LongPressGesture(minimumDuration: 0.2) let drag = DragGesture(minimumDistance: .zero) .onChanged { value in if let newValue = valueFromChartProxy(value.location.x, chartProxy) { highlightedValue = newValue } } return longPress.sequenced(before: drag) .updating($dragState) { value, gestureState, _ in switch value { case .first(true): // * This is never called gestureState = .pressing case .second(true, let drag): // * Drag is often nil // * When drag is nil, we lack access to the location gestureState = .dragging(translation: drag?.translation ?? .zero) default: // * This is never called gestureState = .inactive } onDragChange(gestureState) } } } struct DataPoint: Identifiable { let id = UUID() let category: String let value: Double } struct ContentView: View { let dataPoints = [ DataPoint(category: "A", value: 5), DataPoint(category: "B", value: 3), DataPoint(category: "C", value: 8), DataPoint(category: "D", value: 2), DataPoint(category: "E", value: 7) ] @State private var highlightedCategory: String? = nil @State private var dragState = DragState.inactive var body: some View { VStack { Text("Bar Chart with Gesture Interaction") .font(.headline) .padding() Chart { ForEach(dataPoints) { dataPoint in BarMark( x: .value("Category", dataPoint.category), y: .value("Value", dataPoint.value) ) .foregroundStyle(highlightedCategory == dataPoint.category ? Color.red : Color.gray) .annotation(position: .top) { if highlightedCategory == dataPoint.category { Text("\(dataPoint.value, specifier: "%.1f")") .font(.caption) .foregroundColor(.primary) } } } } .frame(height: 300) .chartOverlay { chartProxy in ChartGestureOverlay<String>( highlightedValue: $highlightedCategory, chartProxy: chartProxy, valueFromChartProxy: { xPosition, chartProxy in if let category: String = chartProxy.value(atX: xPosition) { return category } return nil }, onDragChange: { newDragState in dragState = newDragState } ) } .onChange(of: highlightedCategory, { oldCategory, newCategory in }) } .padding() } } #Preview { ContentView() } Thank you!
7
1
1.5k
Mar ’25