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

SwiftUI Documentation

Post

Replies

Boosts

Views

Activity

Issues with List selection in Sequoia (SwiftUI)
In one of my applications I use several List views with Sections. After upgrading to Sequoia I faced the issue, that after selecting an item, the List suddenly scrolls to a different position. Sometimes the selection even gets out of the view, but in every case a double click just went to the wrong item. At one list I found out, that the issue could be solved after changing the data source. I used a computed property, what seems to be a stupid idea. After changing this it now works. Unfortunately there is another List, where this didn't bring the solution. And unfortunately, I cannot reproduce the issue in a code example. One guess of mine is, that it could be related to the fact, that the rows have different heights (because in some are two lines of text and in some are three). And it seems to happen only in very long lists. It worked perfectly in Sonoma. Does anyone face the same issue?
5
0
212
Sep ’24
visionOS - Positioning and sizing windows
Hi, In the visionOS documentation Positioning and sizing windows - Specify initial window position In visionOS, the system places new windows directly in front of people, where they happen to be gazing at the moment the window opens. Positioning and sizing windows - Specify window resizability In visionOS, the system enforces a standard minimum and maximum size for all windows, regardless of the content they contain. The first thing I don't understand is why it talk about macOS in visionOS documentation. The second thing, what is this page for if it's just to tell us that on visionOS we have no control over the position and size of 2D windows. Whereas it is precisely the opposite that would be interesting. I don't understand this limitation. It limits so much the use of 2D windows under visionOS. I really hope that this limitation will disappear in future betas.
11
2
4.0k
Jul ’23
How to build a top/bottom split view with a dynamically-sized divider?
Is there a way to structure three views vertically with a top, middle divider, and bottom view, where the… Middle divider view “hugs” its contents vertically (grows and shrinks based on height of child views) Top and bottom views fill the space available above and below the divider Divider can be dragged all the way up (or down), to completely hide the top view (or bottom view) I’ve been working on this for a while and still can’t get it quite right. The code below is close, but the parent view’s bottom edge shifts when the divider resizes. As a result, the bottom view shifts upward when the divider shrinks, whereas I want it to continue to fill the space to the bottom of the screen. import SwiftUI struct ContentView: View { @State private var topRatio: CGFloat = 0.5 @State private var dividerHeight: CGFloat = 44 var body: some View { GeometryReader { geometry in let topInset = geometry.safeAreaInsets.top let bottomInset = geometry.safeAreaInsets.bottom let totalHeight = geometry.size.height let availableHeight = max(totalHeight - bottomInset - dividerHeight, 0) VStack(spacing: 0) { TopView() .frame(height: max(availableHeight * topRatio - topInset, 0)) .frame(maxWidth: .infinity) .background(Color.red.opacity(0.3)) DividerView() .background(GeometryReader { proxy in Color.clear.preference(key: DividerHeightKey.self, value: proxy.size.height) }) .onPreferenceChange(DividerHeightKey.self) { height in dividerHeight = height } .gesture( DragGesture() .onChanged { value in let maxDragDistance = availableHeight + dividerHeight let translation = value.translation.height / max(maxDragDistance, 1) let newTopRatio = topRatio + translation topRatio = min(max(newTopRatio, 0), 1) } ) .zIndex(1) BottomView() .frame(height: max(availableHeight * (1 - topRatio), 0)) .frame(maxWidth: .infinity) .background(Color.green.opacity(0.3)) } } } } struct DividerHeightKey: PreferenceKey { static var defaultValue: CGFloat = 44 static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) { value = nextValue() } } struct DividerView: View { @State private var showExtraText = true var body: some View { VStack(spacing: 0) { Text(showExtraText ? "Tap to hide 'More'" : "Tap to show 'More'") .frame(height: 44) if showExtraText { Text("More") .frame(height: 44) } } .frame(maxWidth: .infinity) .background(Color.gray) .onTapGesture { showExtraText.toggle() } } } struct TopView: View { var body: some View { VStack { Spacer() Text("Top") } .padding(0) } } struct BottomView: View { var body: some View { VStack { Text("Bottom") Spacer() } .padding(0) } } #Preview { ContentView() }
2
0
230
Oct ’24
Is this log noise? "CoreSVG: Error: NULL ref passed to getObjectCoreSVG: Error: NULL ref passed to getObject"
Before I waste time creating an Apple Developer Support ticket, I’m hoping an Apple DTS engineer can confirm if this is just log noise. Here’s the code: import SwiftUI struct ContentView: View { @State private var editMode: EditMode = .inactive @State private var items = ["Item 1", "Item 2", "Item 3"] var body: some View { NavigationStack { List { ForEach(items, id: \.self) { item in Text(item) } .onDelete { indexSet in items.remove(atOffsets: indexSet) } } .environment(\.editMode, $editMode) .toolbar { ToolbarItem(placement: .topBarTrailing) { EditButton() .environment(\.editMode, $editMode) } } } } } #Preview { ContentView() } When you run this code and tap Edit, you’ll initially get: CoreSVG has logged an error. Set environment variabe [sic] "CORESVG_VERBOSE" to learn more. After setting CORESVG_VERBOSE = YES, you’ll see: CoreSVG: Error: NULL ref passed to getObjectCoreSVG: Error: NULL ref passed to getObject This error only appears the first time Edit is tapped after a build and run. It won't happen again, even after force-quitting and reopening the app. The issue also only happens on iOS 18.0 and 18.1—I can’t reproduce it on iOS 17.5. Fortunately, it doesn’t seem to cause any negative side effects. Is this just log noise?
1
2
362
2w
UIHostingConfiguration + MainActor.assumeIsolated?
I'm trying to use a SwiftUI view as UICalendarView decoration and I get Call to main actor-isolated instance method 'makeContentView()' in a synchronous nonisolated context; this is an error in the Swift 6 language mode in the following code: class Coordinator: NSObject, UICalendarViewDelegate { func calendarView(_ calendarView: UICalendarView, decorationFor dateComponents: DateComponents) -> UICalendarView.Decoration? { .customView { UIHostingConfiguration { ... } .makeContentView() } } } I've fixed using MainActor.assumeIsolated but is this the correct approach or is there a better one? class Coordinator: NSObject, UICalendarViewDelegate { func calendarView(_ calendarView: UICalendarView, decorationFor dateComponents: DateComponents) -> UICalendarView.Decoration? { .customView { MainActor.assumeIsolated { UIHostingConfiguration { ... } .makeContentView() } } } }
1
0
152
2w
Fatal error: UnsafeRawBufferPointer with negative count
I'm using Xcode 14.1 to start a Core Data project. I created a new Project, checking CoreData. The resulting program works in Preview and in the Simulator. I've changed the data from a Item/timestamp to Locations/title. I plan to add more Attributes but that's for later. I think I've got all the Item instances changed to Locations and timestamp to title. It seems to work OK when in Preview for ContentView.swift but crashes in the Simulator with the error Swift/UnsafeRawBufferPointer.swift:946: Fatal error: UnsafeRawBufferPointer with negative count Any suggestions on what I have done wrong? Thanks. PS, the New Project includes the line Text("Select a location") but Select a location doesn't appear in the Preview.
1
1
965
Nov ’22
Access Environment values through PresentationDetents.Context
I want to create a custom presentation detent to set a custom height for a sheet presentation. For that, I added a struct conforming to CustomPresentationDetent which has an only method static function height(in: Self.Context) -> CGFloat?. Implementation works fine, the view presented inside the sheet modifier has the height returned by the custom detent. The problem comes when I try to access the Context's environment values inside the protocol conformance method. PresentationDetent.Context has a subscript that enables accessing any environment value subscript<T>(dynamicMember _: KeyPath<EnvironmentValues, T>) -> T but using it from the custom detents height method only returns the default value for each one. I'm trying to set the environment values through environment<V>(WritableKeyPath<EnvironmentValues, V>, V) modifier but it does not seem to work. When accessed via @Environment property wrapper from the view it does get the updated value though. Is there any other way to set an environment value or any special way to set it so that it is visible from a presentation detent?
3
0
213
Aug ’24
Issue with SwiftUI NavigationStack, Searchable Modifier, and Returning to Root View
I'm facing an issue with SwiftUI's NavigationStack when using the searchable modifier. Everything works as expected when navigating between views, but if I use the search bar to filter a list and then tap on a filtered result, I can navigate to the next view. However, in the subsequent view, my "Set and Return to Root" button, which is supposed to call popToRoot(), does not work. Here's the setup: Structure: RootView: Contains a list with items 1-7. ActivityView: Contains a list of activities that can be filtered with the searchable modifier. SettingView: Contains a button labeled "Set and Return to Root" that calls popToRoot() to navigate back to the root view. RootView struct RootView: View { @EnvironmentObject var navManager: NavigationStateManager var body: some View { NavigationStack(path: $navManager.selectionPath) { List(1...7, id: \.self) { item in Button("Element \(item)") { // Navigate to ActivityView with an example string navManager.selectionPath.append(NavigationTarget.activity) } } .navigationTitle("Root View") .navigationDestination(for: NavigationTarget.self) { destination in switch destination { case .activity: ActivityView() case .settings: SettingsView() } } } } } ActivityView struct ActivityView: View { @EnvironmentObject var navManager: NavigationStateManager let activities = ["Running", "Swimming", "Cycling", "Hiking", "Yoga", "Weightlifting", "Boxing"] @State private var searchText = "" var filteredActivities: [String] { if searchText.isEmpty { return activities } else { return activities.filter { $0.localizedCaseInsensitiveContains(searchText) } } } var body: some View { List { ForEach(filteredActivities, id: \.self) { activity in NavigationLink( destination: SettingsView(), // Navigiere zur SettingsView label: { HStack { Text(activity) .padding() Spacer() } } ) } } .navigationTitle("Choose Activity") .searchable(text: $searchText, placement: .navigationBarDrawer(displayMode: .always), prompt: "Search Activities") } } SettingView struct SettingsView: View { @EnvironmentObject var navManager: NavigationStateManager var body: some View { VStack { Text("Settings") .font(.largeTitle) .padding() Button("Set and Return to Root") { // Pop to the root view when the button is pressed navManager.popToRoot() } .padding() .background(Color.blue) .foregroundColor(.white) .cornerRadius(10) } .navigationTitle("Settings") } } NavigationStateManager // Define enum globally at the top enum NavigationTarget { case activity case settings } class NavigationStateManager: ObservableObject { @Published var selectionPath = NavigationPath() func popToRoot() { selectionPath = NavigationPath() } func popView() { selectionPath.removeLast() } } Problem When I search in the ActivityView and tap on a filtered result, I successfully navigate to the SettingView. However, in this view, pressing the "Set and Return to Root" button does not trigger the navigation back to RootView, even though popToRoot() is being called. This issue only occurs when using the search bar and filtering results. If I navigate without using the search bar, the button works as expected. Question Why is the popToRoot() function failing after a search operation, and how can I ensure that I can return to the root view after filtering the list? Any insights or suggestions would be greatly appreciated!
4
1
365
Sep ’24
Lose my variables when my watch turn off
Hello guys, I have such a big coding problem since a half year now about data saving. I have a fitness app where we can add our exercices depend of the muscle, so you can choose it and then select your weight and number of repetitions and valid your exercise. But when I do my exercises and my watch screen is also turn off, my muscle and muscleExercise variables are going back to their default value. Here some code for you : @EnvironmentObject var dataManager: DataManager @Environment(\.modelContext) private var context @AppStorage("savedGroupName") private var savedGroupName: String = "" @AppStorage("savedExerciceName") private var savedExerciceName: String = "" @State var groupName: String = "À choisir" @State var ExerciceChoose: String = "À choisir" I use my variables here : HStack { Text("Muscle:") Spacer() NavigationLink(destination: MusclesView()) { Text(savedGroupName.isEmpty ? "À choisir" : savedGroupName) } .buttonStyle(PlainButtonStyle()) } .onAppear { savedGroupName = groupName } HStack { Text("Exercise:") Spacer() NavigationLink(destination: MuscleExercicesView(groupName: groupName, ExerciceChoose: ExerciceChoose)) { Text(savedExerciceName.isEmpty ? "À choisir" : savedExerciceName) } .onAppear { savedExerciceName = ExerciceChoose } .buttonStyle(PlainButtonStyle()) } The value of my muscle variable is taking in an other view : struct MusclesView: View { let muscleGroup = ExerciceData.muscleGroups var body: some View { NavigationStack { List(muscleGroup, id: \.name) { group in NavigationLink(destination: MuscleExercicesView(groupName: group.name, ExerciceChoose: "À choisir")) { Text(group.name) } } } } } #Preview { MusclesView() } and the value of the exerciseMuscle variable is also taking in an other view : ```import SwiftUI struct MuscleExercicesView: View { let exerciceGroup = ExerciceData.muscleGroups @State var groupName: String @State var ExerciceChoose: String var body: some View { if let group = ExerciceData.muscleGroups.first(where: { $0.name == groupName }) { List(group.exercices, id: \.id) { exercice in NavigationLink(exercice.name, destination: CurrentInformationsView(groupName: groupName, ExerciceChoose: exercice.name)) } /*.onTapGesture { print("Selected exercise: \(ExerciceChoose) for muscle group: \(groupName)") }*/ .navigationTitle(Text("Exercices pour \(groupName)")) } else { Text("Aucun exercice trouvé pour \(groupName)") .navigationTitle(Text("Erreur")) } } } #Preview { MuscleExercicesView(groupName: "Pectoraux", ExerciceChoose: "À choisir") } I tried many things (like userDefault, put my values in an array to save it etc..) to keep my variables with the same value during the session but nothing works. I wish I could have some help from you guys. Have a good day ! Cyrille
0
0
137
2w
SwiftUI - Horizontal Scroll not Working with NSTextView in NSViewRepresentable
Hello, I have an NSViewRepresentable displaying an NSTextView in SwiftUI. GeometryReader() { geometry in ScrollView([.vertical, .horizontal]) { Representable() // -18 for vertical scroller .frame(minWidth: geometry.size.width - 18) } } When I use the vertical scrollbar the mouse click is passed to the Representable and is not registered by the Scroll bar. In the image you can see I tried to use the scroll bar and it highlighted some text instead. There is a suggestion on stackoverflow to use an overlay. This fixes the scrolling issue, but will then make the Representable uninteractable. How can I use the horizontal scroll bar here as expected?
1
0
176
2w
Problem with ScrollView
Hi guys, I have a really odd problem. Whenever I try to add a vertical ScrollView, VStack or a LazyVStack to this code everything disappears. Anyone have an idea why this is happening and how to fix it? No errors show up in my code. GeometryReader{ geometry in VStack(alignment: .center, spacing: 100){ ScrollView(.horizontal, showsIndicators: false){ HStack(spacing: 250){ CardView1( showOnlyImage: false, imagename1: "TheMiceGalaxiesHubble", heading1: "The Mice Galaxies", description1: "Located in the constellation Coma Berenices." ) .scaleEffect(getScale(proxy: geometry)) .animation(.easeOut(duration: 0.3), value: getScale(proxy: geometry)) CardView1( showOnlyImage: false, imagename1: "TheMiceGalaxiesHubble", heading1: "The Mice Galaxies", description1: "Located in the constellation Coma Berenices." ) .scaleEffect(getScale(proxy: geometry)) .animation(.easeOut(duration: 0.3), value: getScale(proxy: geometry)) } } .frame(height: -200) ScrollView(.horizontal, showsIndicators: false){ HStack(spacing: 250){ CardView1( showOnlyImage: false, imagename1: "TheMiceGalaxiesHubble", heading1: "The Mice Galaxies", description1: "Located in the constellation Coma Berenices." ) .scaleEffect(getScale(proxy: geometry)) .animation(.easeOut(duration: 0.3), value: getScale(proxy: geometry)) } } } } } .contentMargins(50, for: .scrollContent) .scrollTargetBehavior(.viewAligned) .scrollTargetLayout() .padding(.horizontal, 10) .padding(.top, -35) .padding(.bottom, 50) } } } } }
0
0
121
2w
SwiftUI ScrollView performance in macOS 15
There seems to be a performance issue when scrolling using the track pad with SwiftUI scroll views in macOS 15. This issue is NOT present in macOS 14. When using the track pad the scrolling is not smooth, but "stutters". However scrolling using the scroll bars is very smooth. The "stuttering" is worse if the SwiftUI ScrollView is in the detail view of a NavigationSplitView. The problem is not noticeable in scroll views with a small number views, but when the more views inside the scroll view, the more prominent the problem becomes. I have a simple example app that illustrates the problem here (the example app is a simplification of my app Yammixer): https://github.com/danwaltin/SwiftUIScrollViewPerformance When running this example app on macOS 14 (Sonoma) on an Intel i7 Mac book pro from 2019 the scrolling is "buttery smooth". But on macOS 15 (Sequoia) on my Apple Silicon M1 Mac book pro the issue is very obvious. When using Instruments I see that on macOS 15 "flame graph" shows that 85% of the execution time is in a "_hitTestForEvent" method. If the test app does not use NavigationSplitView about 70% of execution time is in the _hitTestForEvent method.
9
8
484
Sep ’24
PersonNameComponents TextField Not Responding As Expected on macOS
Using this adapted code snippet from the Apple Developer Documentation, struct ContentView: View { @State var nameComponents = PersonNameComponents() var body: some View { Form { TextField( "Proper name", value: $nameComponents, format: .name(style: .medium) ) .onSubmit { } .disableAutocorrection(true) .border(.secondary) Text(nameComponents.debugDescription) } } } It runs and works as expected on my iOS device. When I use this same code in my macOS app, it has unexpected results. The validation mechanism (likely caused by format: .name(style: .medium) in order to bind the TextField to a PersonNameComponents instance, will not let me add spaces or delete all the text in the TextField. I have to write the first name in this format: "FirstLast" and then add a space in between the t and L. Are there any ways I can fix this on macOS while still binding my TextField to a PersonNameComponents instance?
0
0
138
2w
CPU use increases over time with simple animation
I created a simple animation of a circle that changes sizes. The circle pulses like a heartbeat in the center of the screen. My expectation was for the CPU use to be very low, but that is not the case. In addition, even if the CPU use isn't as low as I would expect, I did not expect the CPU use to increase over time because nothing else is happening in the app. Here is the code: import SwiftUI @main struct TestApp: App { var body: some Scene { WindowGroup { SplashScreenView() } } } import SwiftUI struct SplashScreenView: View { var body: some View { ZStack { SplashNucleusView(minSize: 50, maxSize: 100) } } } import SwiftUI struct SplashNucleusView: View { let minSize: Double let maxSize: Double @State private var nucleusColor: Color = .primary @State private var nucleusRadius: Double = 10 @State private var nucleusOpacity: Double = 1.0 private var nucleusAnimation: Animation { .easeInOut(duration: 0.25) .repeatForever(autoreverses: true) } let timer = Timer.publish(every: 0.5, on: .main, in: .common).autoconnect() var body: some View { Circle() .fill(nucleusColor) .frame(width: nucleusRadius) .opacity(nucleusOpacity) .onReceive(timer) { _ in withAnimation(nucleusAnimation) { nucleusRadius = Double.random(in: minSize...maxSize) } } } } This is how the animation looks: The animation is snappy until the CPU use reaches 95%, at which point there is visible stuttering. Here is how the CPU looks when the animation duration value is 0.5 seconds and the timer publishing interval is 3 seconds: Changing the animation duration value to 0.25 seconds and the timer publishing interval to 0.5 seconds changes the CPU use as follows: The complete view has many other moving parts, which make the issue much worse. The issue is evident with only the circle view. I spent hours working with the debugger, reading about animations, and testing new approaches, but the result is always the same. Why is this happening?
2
0
189
2w
Drag and Drop operations fail when executed from within the same List
I am working on creating a file viewer to browse a network directory as a way to introduce myself to iOS app development, and was trying to implement a feature that would allow users to drag and drop both files and folders onto another folder inside of the app to move items around. However, it seems that if the View that is set to draggable, and then the view that is set as the Drop Destination is in the same List, then the Drop Destination will not detect when the draggable view has been dropped onto it. Here is the structure of my code: List { Section(header: Text("Folders")) { ForEach($folders, id: \.id) { $folder in FolderCardView() .onDrop(of: [UTType.item], isTargeted: $fileDropTargeted, perform: { (folders, cgPoint) -> Bool in print("Dropped") return true }) } } Section(header: Text("Files")) { ForEach($files, id: \.id) { $file in FileCardView() .onDrag({ let folderProvider = NSItemProvider(object: file) return folderProvider }) } } } I have verified that the issue comes down to the list, because if I move both of the ForEach loops out on their own, or even into their own respective lists, the code works perfectly. I have not only tested this with the older .onDrop and .onDrag modifiers as shown above, but also the newer .draggable and .dropDestination modifiers, and the result is the same. Does anyone know if this is intended behavior? I really like the default styling that the List element applies to other elements within, so I am hoping that it might just be a bug or an oversight. Thanks!
3
0
693
Jul ’23
Text right-to-left direction with mathematical text
Hi, I am writing a calculator app in Swift 5 and decided to support eastern asian numerals to make it a bit interesting. The numeric display itself works well in Arabic langauge setting, but I have a protocol view that reports the entered data and results. I do it in a Grid with two Text items, one for the input and one for the result. The result contains a numeric string in U0660... arabic numerals, and that looks fine. The input is a construct looking like Text(number1) + Text(" ") + Text(operation), so it goes into a single Grid cell. The standard version looks like this: but the arabic version shows the numbers and operation symbols in the wrong sequence: I guess that has something to do with the mathematical symbols such as + and = simply register as ltr Text and confuse the text layout. If I localize π, the result looks different: So my question would be: How do I force a fragment such as Text(" +") to go in rtl direction? Is this a SwiftUI topic or doesit go deeper? I am looking at the Text element now, but may be that is the wrong approach.
6
0
152
3w
Is it intended for onchange to work with let properties?
Hi all, by chance, we introduced code similar to the following in the body of one of our views: struct MyView: View { let myInt: Int var body: some View { EmptyView() // Empty body .onChange(of: myInt) { newValue in … } } } Notice that a simple let of type Int is used here, rather than State or something similar. While it works and onChange is actually triggered when views are rebuilt, I’d like to clarify a few things: Is this behavior actually expected and reliable, or is it a gray area and can be changed in the future? If it is expected, can this be made clearer in the documentation? If it is a gray area, can the documentation be improved to address it? Thanks!
1
1
144
3w