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

SwiftUI Documentation

Post

Replies

Boosts

Views

Activity

SwiftUI Menu with NavigationLinks inside overall NavigationStack
I've read all previous posts on this topic but none seem to address what I'm seeing for iOS 16 and using NavigationStack. I'm also using an overall @EnvironmentObject for navigation state. I have a split view app. In the detail section, I have a NavigationStack surrounding the detail view. Within the detail view (MyView), there is a base view with a "+" button in the toolbar to create a new entity. That opens NewEntityView where I show a grid of buttons for the user to select a type to create a new entity before moving to NewEntityView to fill in the details for the entity. The top row of the grid of buttons takes the user straight to the NewEntityView with a NavigationLink. These work fine. The next row of buttons present a menu of sub-types and then should take the user to the NewEntityView view. These buttons do not work. Code (simplified to not have clutter): SplitViewDetailView: struct SplitViewDetailView: View { @EnvironmentObject var navigationManager: NavigationStateManager @Binding var selectedCategory: Route? var body: some View { NavigationStack(path: $navigationManager.routes) { // other irrelevant stuff MyView() } .environmentObject(navigationManager) .navigationDestination(for: Route.self) { $0 } } } MyView: struct MyView: View { @EnvironmentObject var navigationManager: NavigationStateManager var body: some View { List { // other stuff } .toolbar { ToolbarItem(placement: .navigationBarTrailing) { Button(action: {}, label: { NavigationLink(value: Route.newTypeSelect) { Image(systemName: "plus") .frame(width: 44, height: 44) } } ) } } .navigationDestination(for: Route.self) { $0 } } SelectTypeView: struct SelectTypeView: View { var body: some View { ZStack { VStack { // Top row with no subtypes HStack { ForEach (topRows, id: \.self) { type in NavigationLink(value: Route.newEntityDetails(type.rawValue)) { <-- these work Text(type) } } } HStack { ForEach (middleRow, id: \.self) { type in Menu { ForEach (subtype[type], id: \.self) { sub in NavigationLink(value: Route.newEntityDetails(sub.rawValue)) { <-- these go nowhere Text(sub) } } } label: { Text(type) } } } } } } } NavigationStateManager: class NavigationStateManager: ObservableObject { @Published var routes = [Route]() // other stuff } And Route: enum Route: Identifiable { var id: UUID { UUID() } case newTypeSelect case newEntityDetails(String) } extension Route: View { var body: some View { switch self { case .newTypeSelect: SelectTypeView() case .newEntityDetails(let type): NewEntityView(selectedType: type) } } } The menus show up fine but tapping on an item does nothing. I've attempted to wrap the menu in its own NavigationStack but that is rejected stating it is already in one defined by a parent view. I've tried making the links Buttons with destinations and those are also rejected. What is the newest/best way to present a menu with NavigationLinks? One doesn't simply wrap the menu in a NavigationView if one is using a NavigationStack?
1
0
868
Aug ’23
Broken focus on TabView with more than 7 tabs on tvos18
I am using the TabView control in SwiftUI on a tvOS 18 target with the style of sidebarAdaptable. When I have 7 or less tabs things operate correctly. When I add an 8th tab and you navigate to the contents of the tab the menu collapses as expected but you cannot navigate back to restore the menu. This code reproduces the issue: import SwiftUI struct ContentView: View { var body: some View { TabView { Tab("Tab1", systemImage: "person.circle") { Button("Button1") {} } Tab("Tab2", systemImage: "person.circle") { Button("Button2") {} } Tab("Tab3", systemImage: "person.circle") { Button("Button3") {} } Tab("Tab4", systemImage: "person.circle") { Button("Button4") {} } Tab("Tab5", systemImage: "person.circle") { Button("Button5") {} } Tab("Tab6", systemImage: "person.circle") { Button("Button6") {} } Tab("Tab7", systemImage: "person.circle") { Button("Button7") {} } Tab("Tab8", systemImage: "person.circle") { Button("Button8") {} } } .tabViewStyle(.sidebarAdaptable) } } If you eliminate Tab 8 the problem goes away. You can navigate back to the menu by moving to the left. Notably the Destination Video sample also reproduces this issue: https://developer.apple.com/documentation/visionos/destination-video To reproduce: Load the above code or Destination Video sample. Navigate right (click right on remote or swipe right). Menu dismisses and just shows the item you have selected in the upper left corner. Try to navigate left by clicking left on the remote or swiping left. It looks like the collapsed menu gets focus briefly, screen elements flash but the focus remains outside the menu. Has anyone else encountered this issue?
3
3
205
Nov ’24
Can’t focus the sidebar on tvOS when TabView contains TabSection elements
In a TabView with the .sidebarAdaptable style, including TabSection elements prevents the default back swipe on the remote from revealing the sidebar. Removing all TabSection elements and using only Tab elements makes it work as expected: import SwiftUI struct ContentView: View { var body: some View { TabView { Tab("Tab", systemImage: "square.fill") { Button(action: {}) { Text("Button") } } Tab("Tab", systemImage: "square.fill") { Button(action: {}) { Text("Button") } } Tab("Tab", systemImage: "square.fill") { Button(action: {}) { Text("Button") } } Tab("Tab", systemImage: "square.fill") { Button(action: {}) { Text("Button") } } Tab("Tab", systemImage: "square.fill") { Button(action: {}) { Text("Button") } } Tab("Tab", systemImage: "square.fill") { Button(action: {}) { Text("Button") } } Tab("Tab", systemImage: "square.fill") { Button(action: {}) { Text("Button") } } Tab("Tab", systemImage: "square.fill") { Button(action: {}) { Text("Button") } } Tab("Tab", systemImage: "square.fill") { Button(action: {}) { Text("Button") } } TabSection("Section") { Tab("Tab", systemImage: "square.fill") { Button(action: {}) { Text("Button") } } Tab("Tab", systemImage: "square.fill") { Button(action: {}) { Text("Button") } } } }.tabViewStyle(.sidebarAdaptable) } } Am I using it wrong, or is this a bug?
2
2
523
Jul ’24
SWIFTUI - update an Array/property Element gives error (had to replace the Whole structure)
SWIFTUI - update an Array/property Element gives error (had to replace the Whole structure), not sure my syntax is correct and Gives Syntax error.. Cannot assign value of type 'Double' to type 'Binding' , snippet of code below BTW, I was able to use AllObjects.Replace (but it is process intensive & hanges ) .. replaceSubrange(index...index, with: [TestObjects(.. latitude:Double(-999.0) //... etc )] Perhaps My syntax has issue .. please help //code snippets //declaration @State private var AllObjects:[TestObjects] = [] func TestObjUpdateLoc(index:Int32) { AllObjects.TestObjects[index].latitude = Double(-999.0) **//error ..Cannot assign value of type 'Double' to type 'Binding' ** } // TestObjects struct TestObjects: Codable, Hashable { let seq_id:Int32 let latitude:Double let longitude:Double // Many more... }
2
0
166
1w
BUG: screen flicker on quick tap / swipe to go back
I have found a system bug with UINavigationController, UIGestureRecognizerDelegate mainly the swipe back control. I have reproduced this in many apps, while some that use custom swipe back i can not reproduce, however any app using default uikit/swift transitions i can reproduce the flicker/previous screen flashing The Bug: a slight tap or series of quick taps anywhere on the screen (with the slightest (1-2pt -x)confuse the system into thinking its a swipe back gesture, however instead of pushing back to previous screen the UI flickers and flashes the previous screen. for a split second, very easy to reproduce. on screens with lots of options of boxes to tap it happens quite often. I have removed all custom "swipe back from anywhere" logic, all custom gesture logic, and can still reproduce by tapping the edge of the screen with only UINavigationController, UIGestureRecognizerDelegate in my navigation controller. Please let me know the best way to get in contact with someone at apple to either build an extension to prevent this flicker or if a developer has a fix but this is rarely talked about. (velocity limits etc do not work, and just make the gesture feel awful) all the developers i have reached out too have looked into this and have said "its an ios bug, only fix is build a custom swipe back from anywhere, or wait for apple to fix it).... as a small indie app, building my own seems daunting Recap: quick or taps with small x movement flash previous screen instead of pushing back or simply recognizing it as a tap and not flashing previous screen. this happens with no custom code default uikit/swift. Link me your app i can probably reproduce it, I have reproduced it in X(was hard), Retro(easy), and many more. The goal is to have a smooth native swipe/drag back from anywhere gesture while preventing flicking on fast taps or short taps with minor x movement. i have tried everything from setting limits to -x, velocity limits etc. nothing fixes this. happy hacking! PS i hope someone at apple calls me and i can explain this and we can fix it for every app in an update.
1
0
176
1w
AppIntents - Choosing a default Measurement<UnitMass> for body weight based on locale
Here’s a clearer and more concise version of your question: I’m creating an AppIntent to allow users to log their body weight. My intent includes a @Parameter defined as: @Parameter( title: "Weight", description: "Current Weight", defaultUnit: .pounds, supportsNegativeNumbers: false ) var weight: Measurement<UnitMass> This works but doesn’t respect the user’s Locale and its measurementSystem. When I add defaultUnitAdjustForLocale: true to the @Parameter macro, the default always switches to kilograms, regardless of the locale. How can I correctly set the default unit to match the user’s locale for the purpose of entering a users body weight?
0
0
147
1w
SwiftUI From/List Issue: All Buttons Trigger Simultaneously in List View
Hello everyone, I am a beginner in programming and recently encountered an interesting issue in SwiftUI. (I must admit that it might not be a bug and could simply be due to my lack of understanding.) I have extracted the relevant code that causes this behavior. Here's the code: struct BugView: View { var body: some View { List { VStack { Button("Bug") { print("1") } Button("Bug") { print("2") } Button("Bug") { print("3") } } } } } In this view, clicking any of the buttons results in all of them being triggered simultaneously. As a result, the console outputs: 1 2 3 I would appreciate it if someone could help me understand why this happens and how to fix it. Thanks in advance!
3
0
178
1w
Inconsistent DragGesture translation?
I feel like I must be missing something dumb, but I can't figure it out. I'm trying to create a modifier to make items resizable by dragging on the corner (I haven't actually implemented the corner part yet though so dragging anywhere on the object resizes it). However the rate that I'm dragging at is different from the rate that the object is resizing. It's also different for horizontal and vertical translation (the horizontal change is smaller than the rate that I'm dragging while the vertical change is larger). Any help would be greatly appreciated! Here's my code for the modifier: struct Resizable: ViewModifier { @State var size: CGSize = CGSize(width: 500, height: 500) @State var activeSize: CGSize = .zero func body(content: Content) -> some View { content .frame(width: abs(size.width + activeSize.width), height: abs(size.height + activeSize.height)) // offset is so the top right corner doesn't move .offset(x: -abs(size.width + activeSize.width) / 2, y: abs(size.height + activeSize.height) / 2) .gesture( DragGesture() .onChanged { gesture in activeSize.width = -gesture.translation.width activeSize.height = gesture.translation.height } .onEnded { _ in size.width += activeSize.width size.height += activeSize.height activeSize = .zero } ) } } extension View { func resizable(maxSize: CGSize = .zero) -> some View { modifier(Resizable()) } } And it is used like so: struct ContentView: View { var body: some View { Rectangle() .fill(Color.blue) .resizable() } }
1
0
150
1w
SwiftUI creating MapCameraPosition from CLLocationManager initialiser/self error when trying to tie them? (see code)
Trying to use new Swift @Observable to monitor GPS position within SwiftUI content view. But how do I tie the latest locations to the SwiftUI Map's mapCameraPosition? Well ideally the answer could cover: How to fix this error - So get map tracking along with the User Position, but also How to include facility to turn on/off the map moving to track the user position (which I'll need to do next). So could be tracking, then disable, move map around and have a look at things, then click button to start syncing the mapcameraposition to the GPS location again Refer to error I'm embedded in the code below. import SwiftUI import MapKit @Observable final class NewLocationManager : NSObject, CLLocationManagerDelegate { var location: CLLocation? = nil private let locationManager = CLLocationManager() func startCurrentLocationUpdates() async throws { if locationManager.authorizationStatus == .notDetermined { locationManager.requestWhenInUseAuthorization() } for try await locationUpdate in CLLocationUpdate.liveUpdates() { guard let location = locationUpdate.location else { return } self.location = location } } } struct ContentView: View { var newlocationManager = NewLocationManager() @State private var cameraPosition: MapCameraPosition = .region(MKCoordinateRegion( center: newlocationManager.location?.coordinate ?? <#default value#>, span: MKCoordinateSpan(latitudeDelta: 0.25, longitudeDelta: 0.25) )) // GET ERROR: Cannot use instance member 'newlocationManager' within property initializer; property initializers run before 'self' is available var body: some View { ZStack { Map(position: $cameraPosition) Text("New location manager: \(newlocationManager.location?.description ?? "NIL" )") // works } .task { try? await newlocationManager.startCurrentLocationUpdates() } } } #Preview { ContentView() }
2
0
1.1k
Jan ’24
Swift/ Swift UI errors.
Hi everyone, I am a new developer. I am writing some code in swift playgrounds and came across some odd errors. I have looked for solutions and have found nothing. If any more experienced developers could point me in the right direction, that would be great.
4
0
189
1w
Confusion about units for new WeatherKit visibility items
I am really confused by some of the new data returned in WeatherKit for iOS 18. The visibility (of an object) was already being returned in HourWeather as a Measurement. iOS 18 added max/min visibility (of terrain) in DayWeather. BUT instead of a Measurement it's just a Double. HourWeather: /// The distance at which an object can be clearly seen. /// /// The amount of light and weather conditions like fog, mist, and smog affect visibility. public var visibility: Measurement<UnitLength> DayWeather's comment: /// The maximum distance at which terrain is visible for the day. /// /// The amount of light, and weather conditions like fog, mist, and smog affect visibility. @available(iOS 18.0, macOS 15.0, tvOS 18.0, watchOS 11.0, visionOS 2.0, *) public var maximumVisibility: Double This makes it sound like the new items are also a distance and not a percentage. Why wasn't Measurement used so the unit would be clear? Documentation doesn't explain this either. I'm hoping that this isn't being returned in the unit used by the current locale because my app lets you specify what unit to use for temperature, length, etc regardless of locale. Since all the temperature, length, etc data returned had used Measurement that was possible. The iOS weather app refers to the lowest/highest visibility in my preferred unit, which is miles.
0
0
119
1w
SwiftUI crashed on iOS16 when use List with .animation
When I use the following code List { ForEach(data.items, id: \.knowledgeInfo.mediaID) { item in SelectableKnowledgeListItem(knowledgeData: item, baseID: data.knowledgeBaseID, isSelectionMode: $isSelectionMode, selectedItems: $selectedItems) .KnowledgeListItemStyle() } // 添加底部加载更多 if !data.isEnd && !isRefreshing { ProgressView() .frame(maxWidth: .infinity, alignment: .center) .onAppear { self.isRefreshing = true manager.getKnowledgeList(knowledgeBaseID: data.knowledgeBaseID, completion: { self.isRefreshing = false }) } } } .animation(.interactiveSpring) .scrollContentBackground(.hidden) .environment(\.defaultMinListHeaderHeight, 7) The number of Views rendered in the List remains unchanged after he adds an item to data.items (data is an ObservedObject, items is Published) at runtime.When I removed .animation(.interactiveSpring), it would be processed normally.And if I perform a delete operation after adding, it will cause a crash. *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of sections. The number of sections contained in the collection view after the update (11) must be equal to the number of sections contained in the collection view before the update (10), plus or minus the number of sections inserted or deleted (1 inserted, 1 deleted).
0
0
88
1w
SwiftUI glitch with coloreffect shader & orientation change
Hi, I have the following swiftUI code: Image(uiImage: image) .resizable() .aspectRatio(contentMode: .fit) .colorEffect(ShaderLibrary.AlphaConvert()) and the following shader: [[ stitchable ]] half4 AlphaConvert(float2 position, half4 currentColor) { return half4(currentColor.r>0.5,currentColor.r<=0.5,0,(currentColor.r>0.5)); } I am loading a full-res image from my photo library (24MP)... The image initially displays fine, with portions of the image red, and the rest black (due to alpha blending)... However, after rotating the device, I get an image that is a combination of red&green... Note, that the green pixels from the shader have alpha 0, hence, should never be seen. Is there something special that needs to be done on orientation changes so that the shader works fine?
0
0
129
1w
scrollTargetLayout + @FetchRequest causes items to constantly re-initialize
On a ScrollView+LazyVStack, the addition of .scrollTargetLayout causes many list items to be initialized, instead of the ordinary economical behavior of LazyVStack, where only the necessary items and views are initialized. Even worse, as the stack is scrolled down, all list items are reinitialized for every small scroll. Without, .scrollTargetLayout, everything works fine. I've tried every variation of locating modifiers, and different ways of identifying the list items, with no success. Any ideas? Thanks. @FetchRequest( sortDescriptors: [NSSortDescriptor(keyPath: \Post.created, ascending: true)], animation: .default) private var posts: FetchedResults<Post> var body: some View { ZStack{ ScrollView{ LazyVStack(spacing:0) { ForEach(posts, id: \.self) { post in PostView(post: post) } .onDelete(perform: deletePosts) }.scrollTargetLayout() // <---- causes multiple Posts re-instantiations for any small scroll, very slow } .scrollPosition(id: $scrolledID) .scrollTargetBehavior(.paging)
2
0
145
3w
the ID [":"] occurs multiple times within the collection, this will give undefined results!
Hi! After upgrading to Xcode 16.1 my watchOS app is getting below error using a DatePicker configured with: displayedComponents: .hourAndMinute. I cannot find a solution for this error/warning. It only appears when im using : .hourAndMinute or : .hourAndMinuteandSeconds, but not .date. Note! My code is unchanged only change I Xcode upgrade. Any suggestions? ForEach<Array, Array, _ConditionalContent<_ConditionalContent<_ConditionalContent<_ConditionalContent<YearPicker, MonthPicker>, _ConditionalContent<DayPicker, ComponentPicker>>, _ConditionalContent<_ConditionalContent<ComponentPicker, ComponentPicker>, _ConditionalContent<AMPMPicker, ModifiedContent<Text, _PaddingLayout>>>>, EmptyView>>: the ID [":"] occurs multiple times within the collection, this will give undefined results! import SwiftUI import WidgetKit struct TimeEditView: View { let title: String @Binding var storedValue: String var body: some View { Form { DatePicker( title, selection: Binding<Date>( get: { Date.from(storedValue) ?? Date() }, set: { newDate in storedValue = newDate.toString() } ), displayedComponents: .hourAndMinute ) .onChange(of: storedValue) { WidgetCenter.shared.reloadAllTimelines() print("Morning Start changed!") } } .navigationTitle(title) } }
0
0
142
1w
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.
12
10
1k
Sep ’24
.navigationTitle causes hang when creating a new item on a separate page, then navigating back to a TabView with PageTabViewStyle that is displaying that data on iOS 18.2
After a lot of testing and diagnosing, I found that when going to a item creation page, creating an item, navigating back to a TabView with a tabViewStyle of PageTabViewStyle and a navigationTitle that is displaying that data, and all inside of a NavigationStack, the app hangs. I have tested this on iOS 18.2, on both a simulator and a physical iPhone 16 Pro Max, and it always hangs, not crashing. However, when run on My Mac (Designed for iPad) and the iPad simulator, it doesn't crash. This could just be a really niche problem, but it might be the result of some other issue that could cause other problems. I have created a minimal reproducible example, stemming from the iOS App template, with SwiftUI and SwiftData. ContentView.swift import SwiftUI import SwiftData struct ContentView: View { @Environment(\.modelContext) private var modelContext @Query private var items: [Item] var body: some View { NavigationStack { TabView { ForEach(items) { item in Text(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard)) } } .tabViewStyle(PageTabViewStyle(indexDisplayMode: .automatic)) .toolbar { ToolbarItem(placement: .navigationBarTrailing) { NavigationLink { Button(action: { modelContext.insert(Item(timestamp: Date())) }) { Text("Create Item") } } label: { Text("Creation Page") } } } // When added, crashes the app .navigationTitle("Crash") } } } TestingApp.swift (unchanged) import SwiftUI import SwiftData @main struct TestingApp: App { var sharedModelContainer: ModelContainer = { let schema = Schema([ Item.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) } } Item.swift (unchanged) import Foundation import SwiftData @Model final class Item { var timestamp: Date init(timestamp: Date) { self.timestamp = timestamp } }
1
0
130
1w
Cannot preview in this file, failed to launch
I am not able to use SwiftUI Preview Here is the report I get while trying to see the issue: Here is the report of the issue: And here is the call and code preview: import SwiftUI struct ContentView: View { var body: some View { VStack { Image(systemName: "globe") .imageScale(.large) .foregroundStyle(.tint) Text("Hello, world!") } .padding() } } #Preview { ContentView() } Please update.
1
0
160
2w
Unexpected Frame Resizing Behavior During Animation of safeAreaInset content.
Hey everyone! I’m encountering an issue while attempting to animate height changes of the content inside safeAreaInset(edge:alignment:spacing:content:). When animating a reduction in the frame height, the container view (in my case, Map) also animates unexpectedly. However, when animating an increase in the frame height, the animation works smoothly, and the Map view remains still. How can I address this odd resizing behavior of the container? Code: struct MapView: View { var body: some View { Map() .safeAreaInset(edge: .bottom) { MapDetailView() } } } struct MapDetailView: View { @State private var oldHeightOffset: CGFloat = 0 @State private var newHeightOffset: CGFloat = 0 @State private var containerHeight: CGFloat = 0 private var drag: some Gesture { DragGesture(coordinateSpace: .global) .onChanged { value in withAnimation(.interactiveSpring) { newHeightOffset = oldHeightOffset + value.translation.height } } .onEnded { value in switch newHeightOffset { case containerHeight * 0.625...containerHeight: withAnimation(.spring) { newHeightOffset = containerHeight * 0.75 } case containerHeight * 0.25..<containerHeight * 0.625: withAnimation(.spring) { newHeightOffset = containerHeight * 0.5 } case 0..<containerHeight * 0.25: withAnimation(.spring) { newHeightOffset = 0 } default: break } oldHeightOffset = newHeightOffset } } var body: some View { NavigationStack { Rectangle() .fill(.clear) .containerBackground(.ultraThinMaterial, for: .navigation) } .gesture(drag) .containerRelativeFrame(.vertical) { length, _ in length - newHeightOffset } .onGeometryChange(for: CGFloat.self) { geometryProxy in let frame = geometryProxy.frame(in: .local) return frame.height + newHeightOffset } action: { containerHeight in self.containerHeight = containerHeight } } } Reducing safe area inset's content height (drag down): Increasing safe area inset's content height (drag up):
0
0
130
1w
CallKit
I am working on Agora Voice Call and using CallKit to manage incoming and outgoing calls. Issue: When I accept a call, CallKit goes behind my app. I want CallKit to remain in front of my app. Please guide me.
0
0
115
1w