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

SwiftUI Documentation

Post

Replies

Boosts

Views

Activity

Is there a way to disable button tap feedback in watchOS double-tap gesture?
First post here! Is there a way to reduce the number of haptic feedback for double tap on primary button? Context: Double tap is awesome. Two haptic actuations are given to the gesture to let the user know that the gesture is "received" then a third haptic feedback is given shortly after to signal the primary button is tapped. Is there a way to disable the third haptic feedback. In other words make primary action "silent"? I have tested a number of apps that supports double tap, it seems to me that the triple tap is a system level default, and it cannot be changed. Any help would be greatly appreciated.
0
0
9
1h
Limiting the Number of Bool (True) Values
I have the following lines of code where I show a bunch of checkboxes, each of which can toggle between on and off with a tap. import SwiftUI struct ContentView: View { @State private var viewModel = ContentViewModel() var body: some View { VStack(alignment: .leading) { List { ForEach(viewModel.models, id: \.id) { model in CheckButtonView(id: model.id, text: model.name, isOn: model.isOn) { id, bool in updateDate(id: id, bool: bool) } } } } } func updateDate(id: String, bool: Bool) { for i in 0..<viewModel.models.count { let oldModel = viewModel.models[i] if oldModel.id == id { let newModel = Content(id: oldModel.id, name: oldModel.name, isOn: bool) viewModel.models.remove(at: i) viewModel.models.insert(newModel, at: i) break } } var count = 0 for i in 0..<viewModel.models.count { let model = viewModel.models[i] if model.isOn { count += 1 } } } } struct CheckButtonView: View { let id: String let text: String @State var isOn: Bool var callBack: (String, Bool) -> Void var body: some View { HStack { Button { isOn.toggle() callBack(id, isOn) } label: { Image(systemName: isOn ? "checkmark.square.fill" : "square") .resizable() .aspectRatio(contentMode: .fit) .frame(width: 18) .tint(!isOn ? .black : .blue) } Text(text) .font(.subheadline) Spacer() } .frame(maxWidth: .infinity) } } struct Content { let id: String let name: String let isOn: Bool } class ContentViewModel: ObservableObject { @Published var models = [Content]() @Published var canChange = true init() { models = [ Content(id: UUID().uuidString, name: "Jim", isOn: false), Content(id: UUID().uuidString, name: "Jenny", isOn: false), Content(id: UUID().uuidString, name: "Nancy", isOn: false), Content(id: UUID().uuidString, name: "Natalie", isOn: false) ] } } According to the picture above, I have two checkboxes that are turned on. Now, what I want to do is let the user turn on as many as two checkboxes only. Can someone think of a good way of doing that? Thanks.
0
0
26
2h
NavigationSplitView does not work inside NavigationStack
When using a NavigationSplitView within a NavigationStack, the NavigationSplitView does not work as expected on iOS 18 (it worked previously). Items do not show their associated detail views when selected. See the following minimum reproducible example: import SwiftUI struct ContentView: View { @State var selectedItem: String? = nil @State var navigationState: NavigationState? = nil var body: some View { NavigationStack { List(selection: self.$selectedItem) { NavigationLink("Item 1", value: "item") } .navigationDestination(item: self.$selectedItem) { value in ChildView() } } } } enum NavigationState: Hashable { case general case secondary } struct ChildView: View { @State var navigationState: NavigationState? = nil var body: some View { NavigationSplitView { List(selection: self.$navigationState) { NavigationLink(value: NavigationState.general) { Text("Basic info") } NavigationLink(value: NavigationState.secondary) { Text("Secondary info") } } } detail: { if self.navigationState == nil { Text("Nothing") } else { Text("Details") } } } }
0
0
52
12h
ScrollViewReader
I'd like to use ScrollViewReader, but on a list of static text that has formatting such as font colors and bold text. Essentially, my list has a bunch of: Text("some text ") + Text(" and more text").fontWeight(.bold).foregroundStyle(boldColor) Switching to AttributedString would be a pain, and I'm not so sure ScrollViewReader is working correctly. It seems like there are a lot of bugs reports about it. Plus, do we really need a separate string format, just to have proper formatting? Really? Is there another version I'm missing? One that can scroll to anchor points that I could set?
0
0
63
17h
Parametrized Shortcuts do not show up in Shortcuts app and search with localisation.
Hi! When my device is set to English, both search and the Shortcuts up automatically show multiple shortcuts parametrised for each value of the AppEnum - which is what I expected. When my device is set to German, I get only the basic AppShortcut without the (optional) parameter. I am using an AppEnum (see below) for the parametrised phrases and localise the phrases into German with an AppShortcuts String Catalog added to my project. Everything else seems to work, I can use my AppShortcut in the Shortcuts app and invoke it via Siri in both English and German. The Shortcuts app displays the values correctly using the localized strings. Any ideas? import AppIntents class ApolloShortcuts: AppShortcutsProvider { static var appShortcuts: [AppShortcut] { AppShortcut( intent: GetIntent(), phrases: [ "Get data from \(.applicationName)", "Get data from \(.applicationName) for \(\.$day)", "Get data from \(.applicationName) for the \(\.$day)" ], shortTitle: "Get Data", systemImageName: "wand.and.sparkles") } } enum ForecastDays: String, AppEnum { static var typeDisplayRepresentation: TypeDisplayRepresentation = "Day" static var caseDisplayRepresentations: [Self : DisplayRepresentation] = [ .today: DisplayRepresentation(title: LocalizedStringResource("today", table: "Days")), .tomorrow: DisplayRepresentation(title: LocalizedStringResource("tomorrow", table: "Days")), .dayAfterTomorrow: DisplayRepresentation(title: LocalizedStringResource("dayAfterTomorrow", table: "Days")) ] case today case tomorrow case dayAfterTomorrow var displayName: String { String(localized: .init(rawValue), table: "Days") } }
0
0
70
19h
Force position change of the document edit menu in Document based app on SwiftUI
How can I make this appear inside the NavigationSplitView toolbar? It doubles up with the close button and takes up space... App Main view import SwiftUI @main struct WritingApp: App { var body: some Scene { DocumentGroup(newDocument: WritingAppDocument()) { file in StoryView(document: file.$document) } } } Story view import SwiftUI struct StoryView: View { @Binding var document: WritingAppDocument @State private var isShowingSheet = false @FocusState private var isFocused: Bool var body: some View { NavigationSplitView { Text("Sidebar") } detail: { HStack { Text("Detail View") } .toolbar { ToolbarItem { Button("Book", systemImage: "book") { } } ToolbarItem { Button("Circle", systemImage: "circle") { } } } } } }
1
0
66
20h
swift DeviceActivityReport run in background
DeviceActivityReport presents statistics for a device: https://developer.apple.com/documentation/deviceactivity/deviceactivityreport The problem: DeviceActivityReport can present statistics with a delay for a parent device (when DeviceActivityReport is presenting, the DeviceActivityReportExtension is called to process the statistics). One possible solution is to call DeviceActivityReport periodically throughout the day in a child device. However, the app will not be available all day. Is there any way to run DeviceActivityReport in the background? I have tried the following approach, but it didn’t work (DeviceActivityReportExtension didnt call): let hostingController: UIHostingController? = .init(rootView: DeviceActivityReport(context, filter: filter)) hostingController?.view.frame = .init(origin: .zero, size: .init(width: 100, height: 100)) hostingController?.beginAppearanceTransition(true, animated: false) hostingController?.loadView() hostingController?.viewDidLoad() try? await Task.sleep(for: .seconds(0.5)) hostingController?.viewWillAppear(true) hostingController?.viewWillLayoutSubviews() try? await Task.sleep(for: .seconds(0.5)) hostingController?.viewDidAppear(true) try? await Task.sleep(for: .seconds(0.5)) hostingController?.didMove(toParent: rootVC) try? await Task.sleep(for: .seconds(0.5)) hostingController?.viewWillLayoutSubviews() hostingController?.viewDidLayoutSubviews() hostingController?.view.layoutIfNeeded() hostingController?.view.layoutSubviews() hostingController?.endAppearanceTransition() Is there any way to run DeviceActivityReport in the background? (when app is not visible/closed). The main problem is call DeviceActivityReport
0
0
80
1d
SwiftUI App crashes while switching orientation
Hi, I am a new SwiftUI app developer and developing my first application. In the process of designing not very GUI rich app, I noticed my app crashed whenever I switched orientation (testing on multiple iPhone devices). After going through all kind of logs and errors, performance enhancements nothing worked. Then I started rolling back all GUI related features 1 by 1 and tested (I am sure there are better approaches, but excuse me I am novice in app development :) ). Even though it's time consuming, I could pin point the cause of the fatal error and app crash, it's due to multiple .shadow modifiers I used on NavigationLink inside a ForEach look (to be precise I used it like following, .shadow(radius: 15) .shadow(radius: 20) .shadow(radius: 20) .shadow(radius: 20) .shadow(radius: 20) Note, there are only 7 items in List and it uses the Hero View (like app store's Today section) for child views. Once I got rid of shadow modifies or used only 1 app works fine and doesn't crash. Lesson learnt... P.S. It's so ironic that so performance tuned devices couldn't handle this basic GUI stuff.
2
0
59
1d
SF symbol effects don't work unless font modifier is applied
why do I need to set the font of an image of an SF symbol to get the effect to work? This should be a bug, it's bad behavior. Xcode 16.1 iOS 18.1, so frustrating. for example: this works Image(systemName: "arrow.trianglehead.2.clockwise.rotate.90.circle.fill") .symbolEffect(.rotate, options: .repeat(.continuous), value: isActive) .font(.largeTitle) .onAppear() { isActive = true } but this does not animate, which makes no sense Image(systemName: "arrow.trianglehead.2.clockwise.rotate.90.circle.fill") .symbolEffect(.rotate, options: .repeat(.continuous), value: isActive) .onAppear() { isActive = true } its the same if you use a simple setup and different font size, and whether font is before or after the symbol effect Image(systemName: "arrow.trianglehead.2.clockwise.rotate.90.circle.fill") .font(.headline) // only works if this line is here .symbolEffect(.rotate, options: .repeat(.continuous))
0
1
62
1d
StoreKit Causing Unrelated SwiftUI View to Freeze
Hello everyone! I've encountered an issue related to SwiftUI and StoreKit. Please take a look at the SwiftUI code snippet below: import SwiftUI struct ContentView: View { var body: some View { NavigationStack { List { NavigationLink { Page1() } label: { Text("Go to Page 1") } } } } } struct Page1: View { @Environment(\.dismiss) private var dismiss @State private var string: String = "" var body: some View { List { NavigationLink { List { Page2(string: $string) .simpleValue(4) } } label: { Text("Tap this button will freeze the app") } } .navigationTitle("Page 1") } } struct Page2: View { @Binding var string: String? init(string: Binding<String>) { self._string = Binding(string) } var body: some View { Text("Page 2") } } extension EnvironmentValues { @Entry var simpleValue: Int = 3 } extension View { func simpleValue(_ value: Int) -> some View { self.environment(\.simpleValue, value) } } This view runs normally until the following symbol is referenced anywhere in the project: import StoreKit extension View { func notEvenUsed() -> some View { self.manageSubscriptionsSheet(isPresented: .constant(false)) } } It seems that once the project links the View.manageSubscriptionsSheet(isPresented:) method, regardless of whether it's actually used, it causes the above SwiftUI view to freeze. Steps to Reproduce: Clone the repository: https://github.com/gongzhang/StrangeFreeze Open it in Xcode 16 and run on iOS 17-18.1 Navigate to the second page and tap the button, causing the app to freeze. Remove manageSubscriptionsSheet(...), then everything will work fine
1
0
64
1d
Textfield producing : Can't find or decode reasons, Failed to get or decode unavailable reasons
How to reproduce: create blank Xcode project run on physical iPhone(mine 14 pro) not simulator, updated iOS18.1.1 most up to date, on Xcode 16.1 make a text field enter any value in it in console: Can't find or decode reasons Failed to get or decode unavailable reasons This is happening in my other projects as well and I don't know a fix for it is this just an Xcode bug random log noise? It makes clicking the text field lag sometimes on initial tap.
2
1
113
1d
UIViewRepresentable & MVVM
I am trying to get my head around how to implement a MapKit view using UIViewRepresentable (I want the map to rotate to align with heading, which Map() can't handle yet to my knowledge). I am also playing with making my LocationManager an Actor and setting up a listener. But when combined with UIViewRepresentable this seems to create a rather convoluted data flow since the @State var of the vm needs to then be passed and bound in the UIViewRepresentable. And the listener having this for await location in await lm.$lastLocation.values seems at least like a code smell. That double await just feels wrong. But I am also new to Swift so perhaps what I have here actually is a good approach? struct MapScreen: View { @State private var vm = ViewModel() var body: some View { VStack { MapView(vm: $vm) } .task { vm.startWalk() } } } extension MapScreen { @Observable final class ViewModel { private var lm = LocationManager() private var listenerTask: Task&lt;Void, Never&gt;? var course: Double = 0.0 var location: CLLocation? func startWalk() { Task { await lm.startLocationUpdates() } listenerTask = Task { for await location in await lm.$lastLocation.values { await MainActor.run { if let location { withAnimation { self.location = location self.course = location.course } } } } } Logger.map.info("started Walk") } } struct MapView: UIViewRepresentable { @Binding var vm: ViewModel func makeCoordinator() -&gt; Coordinator { Coordinator(parent: self) } func makeUIView(context: Context) -&gt; MKMapView { let view = MKMapView() view.delegate = context.coordinator view.preferredConfiguration = MKHybridMapConfiguration() return view } func updateUIView(_ view: MKMapView, context: Context) { context.coordinator.parent = self if let coordinate = vm.location?.coordinate { if view.centerCoordinate != coordinate { view.centerCoordinate = coordinate } } } } class Coordinator: NSObject, MKMapViewDelegate { var parent: MapView init(parent: MapView) { self.parent = parent } } } actor LocationManager{ private let clManager = CLLocationManager() private(set) var isAuthorized: Bool = false private var backgroundActivity: CLBackgroundActivitySession? private var updateTask: Task&lt;Void, Never&gt;? @Published var lastLocation: CLLocation? func startLocationUpdates() { updateTask = Task { do { backgroundActivity = CLBackgroundActivitySession() let updates = CLLocationUpdate.liveUpdates() for try await update in updates { if let location = update.location { lastLocation = location } } } catch { Logger.location.error("\(error.localizedDescription)") } } } func stopLocationUpdates() { updateTask?.cancel() updateTask = nil } func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) { switch clManager.authorizationStatus { case .authorizedAlways, .authorizedWhenInUse: isAuthorized = true // clManager.requestLocation() // ?? case .notDetermined: isAuthorized = false clManager.requestWhenInUseAuthorization() case .denied: isAuthorized = false Logger.location.error("Access Denied") case .restricted: Logger.location.error("Access Restricted") @unknown default: let statusString = clManager.authorizationStatus.rawValue Logger.location.warning("Unknown Access status not handled: \(statusString)") } } func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) { Logger.location.error("\(error.localizedDescription)") } }
1
0
83
2d
MacOS SwiftUI access modelContext from menu (.commands)?
Adding an Import... menu item using .commands{CommandGroup... on DocumentGroup( ... ) { ContentView() } .commands { CommandGroup(replacing: .importExport) { Button("Import…") { isImporting = true } .keyboardShortcut("I", modifiers: .option) .fileImporter( isPresented: $isImporting, allowedContentTypes: [.commaSeparatedText], allowsMultipleSelection: false ) { result in switch result { case .success(let urls): print("File import success") ImportCSV.importCSV(url: urls, in: context) // This is the issue case .failure(let error): print("File import error: \(error)") } } } I could get this to work if I were not using DocumentGroup but instead programmatically creating the modelContext. using the shared modelContext in ImportCSV is not possible since that is not a View passing the context as shown above would work if I knew how to get the modelContext but does it even exist yet in Main? Is this the right place to put the commands code? Perhaps the best thing is to have a view appear on import, then used the shared modelContext. In Xcode menu File/Add Package Dependencies... opens a popup. How is that done?
1
0
107
2d
Discovered a bug where Alert button colors are changed by the tint modifier.
I used .tint(.yellow) to change the default back button color. However, I noticed that the color of the alert button text, except for .destructive, also changed. Is this a bug or Apple’s intended behavior? this occurs in iOS 18.1 and 18.1.1 Below is my code: // App struct TintTestApp: App { var body: some Scene { WindowGroup { MainView() .tint(.yellow) } } } // MainView var mainContent: some View { Text("Next") .foregroundStyle(.white) .onTapGesture { isShowingAlert = true } .alert("Go Next View", isPresented: $isShowingAlert) { Button("ok", role: .destructive) { isNextButtonTapped = true } Button("cancel", role: .cancel) { } } } thank you!
0
1
83
3d
Since iOS 18.1, the color of Alert buttons has been affected by the tint modifier.
I used .tint(.yellow) to change the default back button color. However, I noticed that the color of the alert button text, except for .destructive, also changed. Is this a bug or Apple’s intended behavior? Thank you! Below is my code: // App struct tintTestApp: App { var body: some Scene { WindowGroup { MainView() .tint(.yellow) } } // MainView var mainContent: some View { Text("Next") .foregroundStyle(.white) .onTapGesture { isShowingAlert = true } .alert("Go Next View", isPresented: $isShowingAlert) { Button("ok", role: .destructive) { isNextButtonTapped = true } Button("cancel", role: .cancel){} } }
2
2
96
3d
Customizing Tables in SwiftUI
Hi, How to customize tables in SwiftUI its color background for example, the background modifier doesn't work ? how to change separator lines ? rows background colors ? give header row different colors to its text and background color ? Kind Regards
1
0
72
3d
Macos 15.2 beta 4 App Crash
I have a SwiftUI based program that has compiled and run consistently on previous macos versions. After upgrading to 15.2 beta 4 to address a known issue with TabView in 15.1.1, my app is now entering a severe hang and crashing with: "The window has been marked as needing another Update Contraints in Window pass, but it has already had more Update Constraints in Window passes than there are views in the window. .<SwiftUI.AppKitWindow: 0x11d82a800> 0x87 (2071) {{44,0},{1468,883}} en" Is there a known bug that could be causing this crash or known change in the underlying layout model?
0
0
106
3d
Horizontal window/map on visionOS
Hi, would anyone be so kind and try to guide me, which technologies, Kits, APIs, approaches etc. are useful for creating a horizontal window with map (preferrably MapKit) on visionOS using SwiftUI? I was hoping to achieve scenario: User can walk around and interact with horizontal map window and also interact with (3D) pins on the map. Similar thing was done by SAP in their "SAP Analytics Cloud" app (second image from top). Since I am complete beginner in this area, I was looking for a clean, simple solution. I need to know, if AR/RealityKit is necessary or is this achievable only using native SwiftUI? I tried using just Map() with .rotation3DEffect() which actually makes the map horizontal, but gestures on the map are out of sync and I really dont know, if this approach is valid or complete rubbish. Any feedback appreciated.
1
0
88
3d
sourceImageURL in imagePlaygroundSheet isn't optional
I can't shake the "I don't think I did this correctly" feeling about a change I'm making for Image Playground support. When you create an image via an Image Playground sheet it returns a URL pointing to where the image is temporarily stored. Just like the Image Playground app I want the user to be able to decide to edit that image more. The Image Playground sheet lets you pass in a source URL for an image to start with, which is perfect because I could pass in the URL of that temp image. But the URL is NOT optional. So what do I populate it with when the user is starting from scratch? A friendly AI told me to use URL(string: "")! but that crashes when it gets forced unwrapped. URL(string: "about:blank")! seems to work in that it is ignored (and doesn't crash) when I have the user create the initial image (that shouldn't have a source image). This feels super clunky to me. Am I overlooking something?
0
0
77
3d
Most idiotic problem with assign value to value?
Why assigning function.formula = formula does not change function.formula to formula in one go? It's always late one change behind. struct CustomFunction has defined .formula as @MainActor. I feel stupid. There is a part of code: struct CustomFormulaView: View { @Binding var function: CustomFunction @State var testFormula: String = "" @EnvironmentObject var manager: Manager .... .onChange(of: testFormula) { debugPrint("change of test formula: \(testFormula)") switch function.checkFormula(testFormula, on: manager.finalSize) { case .success(let formula): debugPrint("before Change: \(function.formula)") function.formula = formula // Nothing happens debugPrint("Test formula changed: \(testFormula)") debugPrint("set to success: \(formula)") debugPrint("what inside function? \(function.formula)") Task { //Generate Image testImage = await function.image( size: testImageSize), simulate: manager.finalSize) debugPrint("test image updated for: \(function.formula)") } .... and it produces this output when changed from 0.5 to 1.0 Debug: change of test formula: 1.0 Debug: before Change: 0.5 Debug: Test formula changed: 1.0 Debug: set to success: 1.0 Debug: what inside function? 0.5 Debug: test image updated for: 0.5 0.5 is an old value, function.formula should be 1.0 WT??
3
0
131
4d