Provide views, controls, and layout structures for declaring your app's user interface using SwiftUI.

SwiftUI Documentation

Post

Replies

Boosts

Views

Activity

Xcode 16 - List Lazy loading broken
In Xcode 16 and Xcode 16.1 beta 2 the lazy loading of list does not work properly. Tested on physical device with iOS 17. Below is minimal code to reproduce this issue: You can see in the debug console how many child views are initialized based on the print statement. import SwiftUI @main struct TestDemoApp: App { let data = Array(1...1000) var body: some Scene { WindowGroup { List(data, id: \.self) { item in SomeView(item: item) } } } } struct SomeView: View { static var count = 0 let item: Int init(item: Int){ self.item = item Self.count += 1 print(Self.count) } var body: some View{ Text(String(item)) .frame(height: 100) } } When the view is shown the List creates all child views at once as shown in the console output: It does not loads only first 13 out of 1000 as it does in older xcode 15.2: As the List is quite often used component in Swiftui Apps, the apps will be slow, because all the data are loaded and the main thread will be stuck until all child views are loaded.
2
1
116
4d
NavigationSplitView's toolbar item disappears on resize
When a NavigationSplitView's sidebar has a default selected value, the detail's toolbar item disappears when resizing the view from compact to regular size. @State private var selectedId: String? = "anything" NavigationSplitView { List(selection: $selectedId) { Text("Sidebar") } } detail: { Text("Detail") .toolbar { Button("Button") {} } } There is no way to get the toolbar item back, other than reloading the view. I have no idea why this happens. In my example I have a dummy Text("Sidebar") without a value, but the problem occurs regardless of its content. Tested on Simulator iPadOS 18.0, and I've seen this happen in our production app.
3
0
152
1w
Suddenly getting "Trailing closure passed to parameter of type 'Visibility' that does not accept a closure" for toolbars
Not sure exactly what’s going on here. I’ve been building out this little app for the past couple of weeks using Xcode 16 betas, and in a couple of places I have code like this: EditItemView(item: inItem) .toolbar { ToolbarItem { Button(action: { self.printLabel(item: inItem) }) { Label("Print Label", systemImage: "printer.filled.and.paper") } } } Now all of a sudden I'm getting an error on .toolbar: “Trailing closure passed to parameter of type 'Visibility' that does not accept a closure.” Looking at the comment for toolbar, it says this method "specifies the visibility," which is a weird thing for it to do with a name like that. But it also has a deprecation tag that I don't quite understand: @available(macOS, introduced: 13.0, deprecated: 100000.0, renamed: "toolbarVisibility(_:for:)"). The name change makes sense, given the description. But what is the huge deprecation version number? Just a hack? And why is this code no longer compiling? As I'm commenting out instances of this, all my toolbars are failing in this way. ETA: yeah, I finally found the right declaration of .toolbar: func toolbar<Content>(@ViewBuilder content: () -> Content) -> some View where Content : View. It's no longer choosing that one. I hate Swift sometimes. ETA2: I finally whittled it down to it not liking Label for some reason. Replacing that with Image works. But of course, the compiler won't tell me why. ETA3: It's worse than I thought: I tried to make a small test case for a bug, and Label works just fine. Why does my code not?
0
0
138
4d
Why doesn't my app show up in the accessibility list?
Hello guys, In a macOS app developed with SwiftUI and swift, the NSAccessibility key has been added to the Info.plist file to explain why the app requires Accessibility permissions, and also the AXIsProcessTrustedWithOptions function has been called, but the app is not seen in the system's Accessibility list. I thought, it will show up in the system's Accessibility list like following Some of my code import SwiftUI @available(macOS 13.0, *) @main struct LOKIApp: App { @State private var activeWindow: NSWindow? = nil @State private var accessibilityGranted = false var body: some Scene { MenuBarExtra("App Menu Bar Extra", image: "trayicon") { Button("Settings") {} .keyboardShortcut("s") Divider() Button("Quit") { NSApplication.shared.terminate(nil) } .keyboardShortcut("q") }.menuBarExtraStyle(.menu) } init() { let options: NSDictionary = [kAXTrustedCheckOptionPrompt.takeRetainedValue() as NSString: true] let accessibilityEnabled = AXIsProcessTrustedWithOptions(options) if accessibilityEnabled == true { print("Accessibility is enabled") } else { print("Accessibility is not enabled. Please enable it in System Preferences") } } } I didn't do any other configuration, and test this app by using the command Command+R, need I set provisioning profile? Please help, thank you.
1
2
606
Mar ’24
Unable to use transitions for SwiftData in List
I can't for the life of me get transitions and animations to work well with SwiftData and List on MacOS 15 and iOS 18. I've included an example below, where I define several animations and a transition type, but they are all ignored. How do I animate items being added to / removed from a List()? I am attached to List() due to its support for selection, context menu, keyboard shortcuts, etc. If I would switch to ScrollView with VStack I would have to rebuild all of that. Also, this is super basic and should just work, right? Thanks for reading. import SwiftUI import SwiftData struct ContentView: View { @Environment(\.modelContext) private var modelContext /// Issues on iOS: /// Items animate into and out of view, but I seem to have no control over the animation. /// In the code here I've specified a 'bouncy' and a slow 'easeIn' animation: both are not triggered. /// The code also specifies using a 'slide' transition, but it is ignored. /// -> How do I control the transition and animation timing on iOS? /// /// Issues on MacOS: /// Items do not animate at all on MacOS! They instantly appear and are instantly removed. /// -> How do I control the transition and animation timing on MacOS? // animation added here -> has no effect? @Query(animation: .bouncy) private var items: [Item] var body: some View { VStack { Button("Add to list") { // called without 'withAnimation' -> no animation let newItem = Item(timestamp: Date()) modelContext.insert(newItem) } List() { ForEach(items, id: \.self) { item in Text(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard)) .transition(.slide) // items do not slide in/out of view .onTapGesture { // called with 'withAnimation' -> no animation withAnimation(.easeIn(duration: 2)) { modelContext.delete(item) } } } .animation(.spring(duration: 3), value: items) } } .padding() } } #Preview { ContentView() .modelContainer(for: Item.self, inMemory: true) }
1
0
70
4d
NavigationLinks embedded in a List getting clipped in tvOS
I want to recreate an user experience like in the settings app in tvOS. Therefore I have a HStack with some content on the left side and a List of NavigationLinks on the right side. However a focused link in the list gets clipped on the left side. I tried paddings and spacers and what not, but nothing helped. Is this is a bug or am I missing something? Here is some example code to show the problem: struct ContentView: View { var body: some View { NavigationStack { HStack(spacing: 20) { VStack(alignment: .center) { Image(systemName: "globe") .imageScale(.large) .foregroundStyle(.tint) Text("Hello, world!") } List { ForEach(SomeViewEnum.allCases) { someView in NavigationLink(someView.rawValue, value: someView) } } .navigationDestination(for: SomeViewEnum.self) { someView in Text(someView.rawValue) } } } } } And a screenshot to show the problem:
1
1
516
Oct ’23
SwiftUI TextField inside Toolbar on MacOS not trigger onChange of focusedState
struct ContentView: View { @State private var editTitle = "title" @FocusState private var isFocused: Bool var body: some View { NavigationSplitView { Text("sidebar") } detail: { Text("detail") .navigationTitle("") .toolbar { ToolbarItem(placement: .principal) { TextField("", text: $editTitle) .focused($isFocused) .onChange(of: isFocused) { oldValue, newValue in print("onChange") } } } } } } on iOS, onChange is triggerred when TextField is inside toolbar or not on MacOS, onChange is not triggerred when TextField is inside toolbar, but when not in toolbar, it works fine
0
0
87
5d
Invalid Numeric Value (NaN) Error in SwiftUI's TextField on Long-Press
I'm experiencing a peculiar issue with SwiftUI's TextField. Whenever I long-press on the TextField, the console outputs an error about passing an invalid numeric value (NaN, or not-a-number) to the CoreGraphics API. This issue persists even in a new Xcode project with minimal code. Code Snippet: import SwiftUI struct ContentView: View { @State private var text: String = "" var body: some View { TextField("Placeholder", text: $text) } } Error: this application, or a library it uses, has passed an invalid numeric value (NaN, or not-a-number) to CoreGraphics API and this value is being ignored. Please fix this problem. Steps to Reproduce: Create a new SwiftUI project in Xcode. Add a TextField to the ContentView. Run the app on a device or simulator. Long-press inside the TextField. What I've Tried: Updating to the latest version of Xcode and iOS. Using UIViewRepresentable to wrap a UIKit UITextField. Creating a new Xcode project to isolate the issue. None of these steps have resolved the issue. Questions: Has anyone else encountered this problem? Are there any known workarounds for this issue? Is this a known bug, and if so, has it been addressed in any updates?
15
25
6.4k
Oct ’23
Bug and crash when changing tabs in SwiftUI on the mac.
I like how the TabView control looks on the mac and ipad and decided to see if my current code can show the tabs in my multi-platform app just to realize that whenever I click on one of those tabs my macOS app currently crashes every time I press any other tab with the error: Thread 1: "NSToolbar 0x600003de33c0 already contains an item with the identifier com.apple.SwiftUI.navigationSplitView.toggleSidebar. Duplicate items of this type are not allowed." While trying to troubleshoot I noticed several other people have had a similar issue with differing reasons (toolbars and searchers mentioned) all in macOS since upgrading to 15.0: https://forums.developer.apple.com/forums/thread/763829 Minimal Viable Project: to show the issue I commented out most of my code calls hoping to create a project that worked so I could bring my code back in and see if it broke. I still had this issue so I next created a minimal viable example. Here it is: import SwiftUI import SwiftData @Model class Issue { var name: String init(name: String) { self.name = name } } @main struct TestMultiplatformApp: App { var sharedModelContainer: ModelContainer = { let schema = Schema([ Issue.self, ]) let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false) do { return try ModelContainer(for: schema, configurations: [modelConfiguration]) } catch { fatalError("Could not create ModelContainer: \(error)") } }() var body: some Scene { WindowGroup { ContentView() } .modelContainer(sharedModelContainer) } } struct ContentView: View { @State var isCompact: Bool = true var body: some View { VStack { if isCompact { EntryTab() } else { EntrySidebar() } Toggle(isOn: $isCompact, label: { Text(isCompact ? "TabView" : "Sidebar") }) .padding(.horizontal, 20) .padding(.bottom, 20) } } } public struct tabControl: Identifiable, Hashable, Sendable { public static func == (lhs: tabControl, rhs: tabControl) -> Bool { lhs.id < rhs.id } public var id: Int // Tab Number public var displayName: String public init(id: Int, displayName: String) { self.id = id self.displayName = displayName } } struct EntryTab: View { let entryTabs = [ tabControl(id: 0, displayName: "row 0"), tabControl(id: 1, displayName: "row 1"), tabControl(id: 2, displayName: "row 2"), tabControl(id: 3, displayName: "row 3") ] @State private var selectedTab: Int = 0 var body: some View { TabView(selection: $selectedTab) { ForEach(entryTabs) { tabCtrl in NavigationSplitView { Text("Selected tab is \(selectedTab)") } detail: { Text("Choose item from sidebar... in future this would be content") } .tabItem { Text(tabCtrl.displayName) } .tag(tabCtrl.id) } } } } struct EntrySidebar: View { @State private var selectedTabID: Int? let entryTabs = [ tabControl(id: 0, displayName: "row 0"), tabControl(id: 1, displayName: "row 1"), tabControl(id: 2, displayName: "row 2"), tabControl(id: 3, displayName: "row 3") ] var body: some View { NavigationSplitView(sidebar: { List(entryTabs, id:\.id, selection: $selectedTabID) { thisItem in Text(thisItem.displayName) } }, content: { Text("Hi selected tab: \(String(describing: selectedTabID))") }, detail: { Text("Choose item from sidebar... in future this would be content") }) .onAppear() { // Set the selected tab selectedTabID = 1 } } }
0
0
127
5d
Xcode 16 MacOS Sequoia SwiftData not saving data after running application
After upgrading to MacOS Sequoia and Xcode 16 my app was behaving oddly. While running the application from Xcode, the app appears to save data, but running the app again from Xcode, the data is not there. If I open the app on the iPhone, run it and create data, the data persists even after I kill the app from the app switcher. I went many rounds through my code and found nothing that helped. I finally ran the sample app that appears when you begin a new project and that is behaving the same way. There are errors thrown. error: the replacement path doesn't exist: "/var/folders/qv/m7sk8kcd3713j3l4bg8wt1lw0000gn/T/swift-generated-sources/@_swiftmacro_13SwiftDataTest11ContentViewV5items33_BCE1062261466603F5F86A688789BF68LL5QueryfMa.swift" error: the replacement path doesn't exist: "/var/folders/qv/m7sk8kcd3713j3l4bg8wt1lw0000gn/T/swift-generated-sources/@_swiftmacro_13SwiftDataTest11ContentViewV5items33_BCE1062261466603F5F86A688789BF68LL5QueryfMa.swift" error: the replacement path doesn't exist: "/var/folders/qv/m7sk8kcd3713j3l4bg8wt1lw0000gn/T/swift-generated-sources/@_swiftmacro_13SwiftDataTest11ContentViewV5items33_BCE1062261466603F5F86A688789BF68LL5QueryfMa.swift"
4
2
376
2w
SwiftUI : NavigationStack in new iOS 18 TabView pushes twice when path in parameter
Hello, With iOS 18, when NavigationStack is in new TabView, with path parameter containing current navigation state is set, the navigation destination view is pushed twice. See below with example that pushes twice on iOS 18 but is correct on iOS 17 @MainActor class NavigationModel: ObservableObject { static let shared = NavigationModel() @Published var selectedTab: String @Published var homePath: [Route] @Published var testPath: [Route] } struct ContentView: View { @StateObject private var navigationModel: NavigationModel = NavigationModel.shared var body: some View { TabView(selection: $navigationModel.selectedTab){ HomeView() .tabItem { Label("Home", systemImage: "house") } .tag("home") TestView() .tabItem { Label("Test", systemImage: "circle") } .tag("test") } } } struct HomeView: View { @StateObject private var navigationModel: NavigationModel = NavigationModel.shared var body: some View { NavigationStack(path: $navigationModel.homePath){ VStack{ Text("home") NavigationLink(value: Route.test1("test1")){ Text("Go to test1") } } .navigationDestination(for: Route.self){ route in NavigationModelBuilder.findFinalDestination(route:route) } } } } I don't what causes the issue because it works well on iOS 16 and iOS 17. I think the path is somehow reset but I don't why (maybe by the TabView ?) Note that the bug only occurs with TabView. Don't really know if it is a TabView bug or if it is on my side. I filed a feedback with sample project FB14312064
31
10
2.9k
Jul ’24
Possible NavigationSplitView bug
With macOS 15, I'm noticing a new behavior when initializing a NavigationSplitView with columnVisibility. For example: @State var sidebar = NavigationSplitViewVisibility.all var body: some View { ZStack { NavigationSplitView(columnVisibility: $sidebar) { This code previous to macOS 15 would behave as expected: the sidebar could be toggled and the views would stay intact. However, when you update sidebar after updating to macOS 15, the entire view is reinitialized, meaning that every single child view that depends on this parent view is also reinitialized. Is this expected behavior? Simply clicking the toggle sidebar UI button does not reinitialize views, but when you initialize a NavigationSplitView with the column visibility, changes to the sidebar will completely reload the UI. Has anyone else experienced this?
0
0
95
5d
Tinted widgets have an inset background in the widget gallery only
When the home screen is in tinted mode in iOS 18, the widget gallery seems to display widgets with the background inset from the edge of the widget (i.e. negative padding). You can see this behavior in the Apple News widget too, where the full-bleed content outside of the inset is very light. This only happens in the sample gallery, not when the widgets are placed on the home screen. For my widgets, this outer edge contains important content and the clipping behavior makes the widgets look poorly designed when viewed in the gallery. Is there any way to turn this behavior off and just show the widget normally in the gallery with no weird inset — the way it will actually display when added to the home screen? If it matters, my widgets are currently configured with: .contentMarginsDisabled() .containerBackground(for: .widget) { // ... (background color) */ }
1
0
114
1w
Map Annotations not always receiving tap events on iOS 18.0
My app uses the SwiftUI Map control to display annotations. When annotations contain buttons AND the map has an .onTapGesture modifier, annotation button taps aren’t always recognized. Given the following ContentView, run it on an iOS device or simulator. Tap the buttons. Since iOS 18.0, some of the buttons won't respond to tap. I've also tried using the onTapGesture instead of a button, and that shows the same issue. This was not a problem under iOS 17.x: it has only shown up for my users since updating to iOS 18. Additionally, this issue does not occur when running on either macOS 15.0 or visionOS 2.0 when running in "designed for iPad" mode. Note that there was previously a tap issue on VisionOS 1.x (designed for iPad), where no tap gestures were received by annotations. I'm curious if this issue could be related. I have filed a report in Feedback Assistant (FB15273909). struct ContentView: View { private let center = CLLocationCoordinate2D(latitude: 37.77925, longitude: -122.41924) @State private var label: String = "tap a button" @State private var locations: [Location] = [] var body: some View { Map { ForEach(locations) { location in Annotation(location.name, coordinate: location.coordinate) { Button(location.name) { print("\(location.name) tapped") label = "\(location.name) tapped" } .buttonStyle(.borderedProminent) } .annotationTitles(.hidden) } } .onTapGesture { point in print("Map tapped") label = "map tapped" } .safeAreaInset(edge: .top) { Text(label) .padding() .background(.thinMaterial) .clipShape(.rect(cornerRadius: 10)) } .navigationTitle("Test Page") .navigationBarTitleDisplayMode(.inline) .task { for index in 1...16 { locations.append(Location(name: "location \(index)", coordinate: CLLocationCoordinate2D(latitude: center.latitude + Double.random(in: -0.02...0.02), longitude: center.longitude + Double.random(in: -0.02...0.02)))) } } } private struct Location: Identifiable { let id: UUID = UUID() let name: String let coordinate: CLLocationCoordinate2D } } #Preview { ContentView() }
0
0
92
5d
SwiftUI context menu scroll broken when view changes
Hi I am on ios 18 and xcode 16 I have a view that changes with a timer and I want to be able to long press that view and show a context menu. However the scroll on the context menu seems to be broken? import SwiftUI struct ContentView: View { @State var number = 0 @State var timer = Timer.publish(every: 0.25, on: .main, in: .common).autoconnect() var body: some View { VStack { Text(number.formatted()) .font(.largeTitle) Text("Long press me") Text("Notice context menu cannot scroll down") } .padding() .background { RoundedRectangle(cornerRadius: 10.0) .fill(Color(uiColor: .secondarySystemBackground)) } .contextMenu { ForEach(0 ..< 100) { index in Button { print("option \(index)") } label: { Label("Option \(index)", systemImage: "globe") } } } .onReceive(timer) { t in number += 1 } } } Is this a bug in swiftUI? In my real application I want the context menu to be able to switch the kind of data the user is viewing.
0
0
75
5d
Section's .sheet(…) disappears first time shown when header: is set
I have a peculiar situation, where the first time I present a sheet from a Section that has the header: set, the sheet disappears by itself the first time it is presented. @State private var show = false // … List { Section { Text("foo") } header: { Text("bar") } .sheet(isPresented: $show) { Text("baz") } // just to enable Button("toggle") { show = true } } In Xcode I get this warning when I present the sheet (taken from our live app): Attempt to present <_TtGC7SwiftUI29PresentationHostingControllerVS_7AnyView_: 0x10a819e00> on <_TtGC7SwiftUI19UIHostingControllerGVS_15ModifiedContentVS_7AnyViewVS_12RootModifier__: 0x10a020600> (from <_TtGC7SwiftUI32NavigationStackHostingControllerVS_7AnyView_: 0x10a0cba00>) while a presentation is in progress. Tested on iOS 17.4.1, iPadOS 17.4.0 (Simulator), Xcode 15.3 Previews.  Circumstances The circumstances are as following: a Section has to be in a List, and have content:, and header: or footer: set to something, and have the .sheet(…) set on the section itself. The problem does not occur with these sections: Section { Text("…") } Section { } footer: { Text("…") } Section { Text("…") } header: { } … but the following views have the sheet disappear the first time it is presented: Section { Text("…") } header: { Text("…") } Section { Text("…") } footer: { Text("…") } Section { Text("…") } header: { Text("…") } footer: { Text("…") } Is this a known issue, and are there any known workarounds to present from a Section? My best guess is to move the .sheet(…) to the parent container, but I'll have to restructure part of my code quite a bit to do so 😕
2
1
367
Apr ’24