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

SwiftUI Documentation

Post

Replies

Boosts

Views

Activity

.scrollPosition does not scroll smoothly when inside .navigationDestination
I filed FB15170881 about this. When using .scrollPosition on a view that is inside a .navigationDestination, scrolling the ScrollView causes the content to jump around rather than animate smoothly. The same view placed outside of the .navigationDestination scrolls smoothly as expected. To view this in action, use the example below. It's apparent on MacOS and iOS, as a Preview or run on-device. Launch it It will load to the problematic view by default. Scroll the view in the square to see the janky movement. You can also press the "back" button to go to a version of the same view that isn't nested inside a .navigationDestination. This one works smoothly as expected. import SwiftUI struct ContentView: View { let items = [0, 1, 2, 3, 4] @State private var position = ScrollPosition(idType: Int.self) @State private var showPage: Bool = true let height = 300.0 let width = 300.0 var body: some View { NavigationStack { VStack { Text("This scrolls nicely.") Text("It's at the navigation root.") demoView Spacer() Button(action: { showPage = true }) { Text("Go to broken version") } .buttonStyle(.bordered) .navigationDestination(isPresented: $showPage) { VStack { Text("This stutters when scrolling.") Text("It's in a navigationDestination.") demoView Spacer() } } Spacer() } } } @ViewBuilder var demoView: some View { let _ = Self._printChanges() ScrollView(.vertical) { LazyVStack(spacing: 0) { ForEach(items, id: \.self) { _ in Text("Scroll me") .frame(width: width, height: height) .border(.pink) } } .scrollTargetLayout() } .frame(width: width, height: height) .border(.blue) .scrollPosition($position) } } #Preview { ContentView() .modelContainer(for: Item.self, inMemory: true) }
1
0
86
1w
SwiftUI video editing timeline implementation
I am trying to build a video editing timeline using SwiftUI which consists of a series of trimmers (sample code for trimmer below). I plan to embed multiple of these trimmers in an HStack to make an editing timeline (HStack in turn will be embedded in a ScrollView). What I want to achieve is that if I trim end of any of these trimmers by dragging it's left/right edge, the other trimmers on timeline should move left/right to fill the gap. I understand as the view shrinks/expands during trimming, there might be a need for spacers on the edges of HStack whose widths need to be adjusted while trimming is ongoing. Right now the code I have for the trimmer uses a fixed frameWidth of the view, so the view occupies full space even if the trimming ends move. It's not clear how to modify my code below to achieve what I want. This was pretty much possible to do in UIKit by the way. import SwiftUI struct SimpleTrimmer: View { @State var frameWidth:CGFloat = 300 let minWidth: CGFloat = 30 @State private var leftOffset: CGFloat = 0 @State private var rightOffset: CGFloat = 0 @GestureState private var leftDragOffset: CGFloat = 0 @GestureState private var rightDragOffset: CGFloat = 0 private var leftAdjustment: CGFloat { // NSLog("Left offset \(leftOffset + leftDragOffset)") var adjustment = max(0, leftOffset + leftDragOffset) if frameWidth - rightOffset - adjustment - 60 < minWidth { adjustment = frameWidth - rightOffset - minWidth - 60.0 } return adjustment } private var rightAdjustment: CGFloat { var adjustment = max(0, rightOffset - rightDragOffset) if frameWidth - adjustment - leftOffset - 60 < minWidth { adjustment = frameWidth - leftOffset - 60 - minWidth } return adjustment } var body: some View { HStack(spacing: 10) { Image(systemName: "chevron.compact.left") .frame(width: 30, height: 70) .background(Color.blue) .offset(x: leftAdjustment) .gesture( DragGesture(minimumDistance: 0) .updating($leftDragOffset) { value, state, trans in state = value.translation.width } .onEnded { value in var maxLeftOffset = max(0, leftOffset + value.translation.width) if frameWidth - rightAdjustment - maxLeftOffset - 60 < minWidth { maxLeftOffset = frameWidth - rightAdjustment - minWidth - 60 } leftOffset = maxLeftOffset } ) Spacer() Image(systemName: "chevron.compact.right") .frame(width: 30, height: 70) .background(Color.blue) .offset(x: -rightAdjustment) .gesture( DragGesture(minimumDistance: 0) .updating($rightDragOffset) { value, state, trans in state = value.translation.width } .onEnded { value in var minRightOffset = max(0, rightOffset - value.translation.width) if minRightOffset < leftAdjustment - 60 - minWidth { minRightOffset = leftAdjustment - 60 - minWidth } rightOffset = minRightOffset } ) } .foregroundColor(.black) .font(.title3.weight(.semibold)) .padding(.horizontal, 7) .padding(.vertical, 3) .background { RoundedRectangle(cornerRadius: 7) .fill(.yellow) .padding(.leading, leftAdjustment) .padding(.trailing, rightAdjustment) } .frame(width: frameWidth) } } #Preview { SimpleTrimmer() }
0
0
137
1w
Reducing space between list rows
Hi, However I tried to reduce space between list rows in below code I fail, is there any way to reduce this space ? @State var flag: Bool = false var myList: [String] = ["Hello", "World", "SwiftUI"] var body: some View { VStack(alignment: .leading) { List (myList, id: \.self) { list in Text(list) .border(Color.black) .font(.system(size: 12)) // Smaller font size .frame(maxWidth: .infinity, minHeight: 20, alignment: .leading) // Reduced height .padding(.vertical, 4) // Minimal padding for vertical spacing .listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0)) // Remove insets .listRowSeparator(.hidden) // Hide separator } .listStyle(.plain) } .overlay( RoundedRectangle(cornerRadius: 10) .stroke(sysSecondary.opacity(0.4), lineWidth: 1) ) .frame(width: 220, height:260) .background(.white) .clipShape (RoundedRectangle (cornerRadius: 10)) } }
2
0
116
2w
Getting inconsistent padding on widgets between devices and simulators
I'm trying to design a homescreen widget but I am unable to properly control the padding and sizing of various components. In the four attached screenshots you can see the huge variation in padding around the outside, the change in text colour and the spacing between the text. I've boiled it down as simple as possible and attached the view as a sample file. What I'd like to achieve is a consistent look between iPads and iPhones and ideally in the simulator too. Is there a simple way to set the padding so that all places use the same, and then scale the text so that I know that if the text fits in the simulator the same text will fit on all devices? Device iPad 8 - 17.7 iPhone 13 Pro Max - 17.7 Xcode Canvas - iPad 13" Simulator - iPad Pro sampleview.txt 13"
0
0
98
2w
Springboard crash when trying to add Control Widget
Xcode 16, iOS 18 official release. On both my phone and simulator, when I build the release build of my app, when I go to control center and select "Add a Control", springboard crashes (see attached crash log). Somehow this does not happen in debug config, with debug config (which does have a different bundle ID but everything else is the same) I'm able to add the control widget just fine. The widget code is taken directly from the Apple docs: struct WidgetTestWidgetControl: ControlWidget { static let kind: String = "com.myapp.WidgetTestWidget" var body: some ControlWidgetConfiguration { AppIntentControlConfiguration( kind: Self.kind, provider: Provider() ) { value in ControlWidgetToggle( "Start Timer", isOn: value.isRunning, action: StartTimerIntent(value.name) ) { isRunning in Label(isRunning ? "On" : "Off", systemImage: "timer") } } .displayName("Timer") .description("A an example control that runs a timer.") } } extension WidgetTestWidgetControl { struct Value { var isRunning: Bool var name: String } struct Provider: AppIntentControlValueProvider { func previewValue(configuration: TimerConfiguration) -> Value { WidgetTestWidgetControl.Value(isRunning: false, name: configuration.timerName) } func currentValue(configuration: TimerConfiguration) async throws -> Value { let isRunning = true // Check if the timer is running return WidgetTestWidgetControl.Value(isRunning: isRunning, name: configuration.timerName) } } } struct TimerConfiguration: ControlConfigurationIntent { static let title: LocalizedStringResource = "Timer Name Configuration" @Parameter(title: "Timer Name", default: "Timer") var timerName: String } struct StartTimerIntent: SetValueIntent { static let title: LocalizedStringResource = "Start a timer" @Parameter(title: "Timer Name") var name: String @Parameter(title: "Timer is running") var value: Bool init() {} init(_ name: String) { self.name = name } func perform() async throws -> some IntentResult { // Start the timer… return .result() } } However in a fresh project I am able to add this widget code and it works completely fine in both debug and release. How can I fix this? This is clearly affecting many apps and is the 'fault' of the app, see these threads: https://www.reddit.com/r/ios/comments/1fiqrd7/ios_18_control_center_keeps_crashing_when_trying/ https://discussions.apple.com/thread/255759997?sortBy=rank crash-log.txt
3
1
236
2w
SwiftUI List hidden line separator not working
Hi, I have the below code as you can see the list doesn't hide its line separator, so is it a bug ? is there any work around ? @State var flag: Bool = false var myList: [String] = ["Hello", "World", "SwiftUI"] var body: some View { VStack(alignment: .leading) { List (myList, id: \.self) { list in Text(list) } .listRowSeparator(.hidden) .listStyle(.plain) } .overlay( RoundedRectangle(cornerRadius: 10) .stroke(sysSecondary.opacity(0.4), lineWidth: 1) ) .frame(width: 220, height:260) .background(.white) .clipShape (RoundedRectangle (cornerRadius: 10)) } }
1
0
121
2w
Using ContactAccessButton freezes the entire app
When using both the ContactsAccessButton demo project, as well as when implementing it in my own, the whole app freezes after entering a few characters and searching through contacts. I don't know if this is necessarily reproducable because it's probably related to the contacts in my contact book. Typing in "Lex" does not freeze the app, but typing in "Adam No" freezes it. I get the following console error before my app freezes and I'm forced to force quit it: #ContactsButton Failed to get service proxy: Error Domain=NSCocoaErrorDomain Code=4097 "connection to service with pid 3387 named com.apple.ContactsUI.ContactsButtonXPCService" UserInfo={NSDebugDescription=connection to service with pid 3387 named com.apple.ContactsUI.ContactsButtonXPCService} #ContactsButton Failed to get remote content: nil (got this a number of times ContactsAccessButton really doesn't seem production ready...
1
1
139
2w
iOS 18 SwiftUI navigation bar problem
Okay I know, fill a bug... but here is a super simple app that will demostrate that the navigation bar chnages from Dark scheme to light scheme when you tap back after it goes to the second view. import SwiftUI struct ContentView: View { var body: some View { NavigationStack { NavigationLink { Text("Tap back and notice the navigation title changes to black text instead of white") .toolbarBackground(.visible, for: .navigationBar) .toolbarBackground(Color.orange, for: .navigationBar) .toolbarColorScheme(.dark, for: .navigationBar) } label: { VStack { Text("First page is the sweetest") } .padding() } .navigationTitle("First Page") .toolbarBackground(.visible, for: .navigationBar) .toolbarBackground(Color.orange, for: .navigationBar) .toolbarColorScheme(.dark, for: .navigationBar) } } } #Preview { ContentView() }
5
5
796
2w
[ERROR] Could not create a bookmark: NSError: Cocoa 4097 "connection to service named com.apple.FileProvider" when using PhotosPicker
Hi I am using PhotosPicker and SwiftData with iOS17.0. I released my own app using codes of two above. No problem came up right until I upgraded my iphone to iOS 18.0 17th of September 24. A single post pokes the similar problem. SwiftData and PhotosPikcer. He or She said it was about SwiftData Model Insert something. But, I was able to use other methods that use SwiftData, so insert Model setup isn't my problem. But when tapping a photo to get a photo from PhotosPicker makes the ui goes down, and navigate back. Weird. iIt doesnt crash but when I tap a photo, the debug message [ERROR] Could not create a bookmark: NSError: Cocoa 4097 "connection to service named com.apple.FileProvider" comes up and the view navigates back. The selecting a photo itself doesnt include any SwiftData related methods, it only does loadTransferable thing and shows the photo on the screen. I cannot understand it. it only happened when I upgraded to iOS 18.0. AND Then i debugged the prob with Xcode 16.0 nothing but the unexpected message appears and not many posts are up here or google. Can you help me? Things I tried: Check any use of the PhotosPickerItem anywhere else. -> No where. Use try await loadTransferable Changed the form of initiating PhotosPikcer View Debugging every line -> Nothing appeared. PhotosPicker(selection: $currentImage, matching: .images, photoLibrary: .shared()) { Text("") } .frame(height: 360) .photosPickerStyle(.inline) .photosPickerAccessoryVisibility(.hidden, edges: .bottom) .photosPickerDisabledCapabilities(.selectionActions) .onChange(of: currentImage) { _, newImage in // SomeLogic } .ignoresSafeArea(edges: .bottom) .transition(.move(edge: .bottom).combined(with: .opacity))
3
2
250
2w
Unable to compile SwiftUI Charts on Xcode 16.1 Beta 2
Unable to compile app that imports Swift UI Charts SDK on Xcode Version 16.1 beta 2 (16B5014f) with error: Failed to build module 'Charts'; this SDK is not supported by the compiler (the SDK is built with 'Apple Swift version 6.0 effective-5.10 (swiftlang-6.0.0.7.41 clang-1600.0.24.1)', while this compiler is 'Apple Swift version 6.0 effective-5.10 (swiftlang-6.0.0.9.11 clang-1600.0.26.2)'). Please select a toolchain which matches the SDK. FB15161667
3
12
916
2w
Obtaining the RGB values for a color in darkMode
I have a colorSet which includes a "Any Appearance" color and a "Dark" color. I have a need to get the hex value of both. I know how to add a .colorScheme(.dark) view modifier to cause the view to adapt to darkMode. That is not the issue. I want to display a swatch containing the darkMode color and I want to display the hex value under the swatch. No matter what I do, it always returns the hex value of the "Any Appearance" version of the color. It seems that the solution might be to use Color.resolve(in:EnvironmentValues), but I do not see how to specify the needed EnvironmentValues
1
0
117
2w
SwiftUI: .textSelection(.enabled) not working in List on iOS 18
In iOS 18, textSelection(_:) not working in List. So, I can't copy text. Works on iOS 17 and earlier. Is this a bug and is there any solution? // Not Work: iOS 18 struct ContentView: View { var body: some View { List { Text("Hello World") .textSelection(.enabled) } } } // Work: iOS 18 and earlier struct ContentView: View { var body: some View { Text("Hello World") .textSelection(.enabled) } }
2
3
199
2w
Live queries on SwiftData DB but without @Query macro?
I switched from using @Query to @ModelActor because of the following reasons: Performance Issues: With @Query, my app became unresponsive with large datasets because data fetching occurred on the main thread. Integration with CKSyncEngine: I needed to implement @ModelActor anyway to allow CKSyncEngine to add data to local persistent storage from the background. In my current setup, the onAppear() method for my view calls the getItems() function on my model actor, which returns [ItemsDTO] and then View renders them. However, I'm now facing a challenge in achieving the same automatic data refreshing and view updates that @Query provided. Here are a few potential solutions I'm considering: Periodic Data Fetching: Fetch data at regular intervals to keep the view updated. But this seems expensive. Local Write Monitoring: Monitor all local writes to automatically trigger updates when changes occur. But this is quite a lot of code I would have to write myself. Switch to manual refresh: Users would have to manually trigger UI updates by pressing button. Reintroduce @Query: Writes would happen from ModelActor, but reads would still happen from Main thread. But then again app would become unresponsive on reads. If you have any additional ideas or best practices for maintaining reactivity with @ModelActor, I'd love to hear them!
1
0
241
2w
Considering Alternatives to SwiftUI for a Complex App
I am working on an application that has some complex navigation needs, and I'm considering abandoning SwiftUI, at least in a few core areas of the app. I found SwiftUI intuitive and useful for simple things like: Using a state to toggle the appearance or disappearance of an element Using state to alter the look of UI elements Watching the values of built-in interfaces like TextField or Slider Controlling out-of-the-box UI elements like NavigationSplitView But now I've got a UI that depends on a data model that can change at any time, and from that data I'll display lists of objects, and objects in detail, and all of this will be displayed according to a NavigationPath that depends on the data model's internal structure. This means that, for instance, I may be in the detail view of element X after having traveled to it from the detail view of element Y which was tapped in a list of XYZ, which was the result of tapping into part of the detail view of element W. This whole path could be invalidated by an update to the data model when it's received from the network. Furthermore, any element could have it's details changed, or be deleted, and I'd want the UI to reflect that right away if possible. For the navigation work, I'm still optimistic that custom edits to a NavigationPath could be the way to go. However, for propagating data updates around my app, I know @State, @Bindable, etc are intended to handle this kind of thing, but when I'm try to send these bindings through the circuitous path of views I mentioned above, and I run into any unexpected hiccup, it feels like I'm at a disadvantage when debugging because I'm relying on opaque SwiftUI Magic to handle things under the hood in a way I don't really understand. I could put more effort into learning how this works, and potentially come up against some platform limitations, bugs, or other dead-ends, or I could just use Pub/Sub and a network of custom queues/pipes, and send updates around my app the old fashioned way, but using primitives whose functions are clear to me. I've been using SwiftUI for about a year and it still trips me up, and I have watched a few WWDC talks on the topic. I'd appreciate any advice on this front from the frequenters of this forum. Thanks for reading my post.
2
0
175
2w
SwiftUI toolbar in MacOS 15 bug ?
struct ContentView: View { var body: some View { NavigationSplitView { List { Text("row 1") Text("row 2") Text("row 3") } .toolbar(content: { ToolbarItem { Button("aa", action: onToolbar) } }) } detail: { HSplitView { VStack { Image(systemName: "globe") .imageScale(.large) .foregroundStyle(.tint) Text("Hello, world!") } .toolbar(id: "toolbar", content: { ToolbarItem(id: "toolbar-1") { Button("bb", action: onToolbar) } }) .padding() Text("right") } }.navigationTitle("") } func onToolbar() {} } Run & Crash NSToolbar 0x6000005665b0 already contains an item with the identifier com.apple.SwiftUI.splitViewSeparator-0. Duplicate items of this type are not allowed.
8
0
267
2w
Using truncationMode
Hi, The example that Apple shows in link below doesn't show how truncationMode works, because the text get truncated anyway when its length it more than frame height so what's the use of truncationMode ? https://developer.apple.com/documentation/swiftui/view/truncationmode(_:) -- Kind Regards
1
0
113
2w
Widget link broken by `.desaturated` image rendering mode
Using desaturated mode on an image in a widget will break any links or buttons that use the image as their 'label'. Using the following will just open the app as if there was no link at all - therefore just using the fallback userActivity handler, or any .widgetURL() urls provided. Link(destination: URL(string: "bug://never-works")!) { Image("puppy") .widgetAccentedRenderingMode(.desaturated) } The same goes for buttons: Button(intent: MyDemoIntent()) { Image("puppy") .widgetAccentedRenderingMode(.desaturated) } I've tried hacky solutions like putting the link behind the image using a ZStack, and disabling hit testing on the image, but they don't work. Anything else to try? Logged as Feedback #15152620.
2
1
113
2w
Text with relative date - sizing bug when used in widget
When using a SwiftUI Text view with a relative date, with .minimumScaleFactor(), in a widget, the Text will always be shown at the minimum scale rather than the largest size possible. This started happening in iOS17, and is still the case in iOS18. Therefore, if for example, you wanted to have a Text, showing a relative date in a countdown, with a "minimumScaleFactor" of 0.5, it will always show at 0.5 scale, no matter how much space there is available. Text(.now, style: .relative) .font(.system(size: 80, weight: .bold, design: .rounded)) .minimumScaleFactor(0.2) ^^ will always show at 0.2 scale (in a widget) even if there's space for much more. This is only the case in widgets, not in the main app. Similarly, if you try to use "ViewThatFits" instead of "minimumScaleFactor", it will choose the smallest view, even if larger ones would fit. Screenshot demonstrates the issue - all the countdown text views should be similarly large. This is not an issue with lack of vertical spacing causing the more flexible views to shrink - it behaves the same even if there's loads of vertical space too. Maybe related, but trying to use ".fixedSize()" with a relative date Text view in a widget results in a completely blank widget. Seems like a system bug rather than anything wrong in my code - I've logged it as Feedback (#15151577) with a demo project. Has anybody else come up against these issues - any solutions?
4
0
143
2w