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

SwiftUI Documentation

Post

Replies

Boosts

Views

Activity

SwiftUI and dragging a file onto the app icon
I'm playing around with using an app to automate some of my personal work flows, and one of the things I wanted to do was to be able to drag a .webloc file onto my app icon in the dock, to launch it. I've got public.data set up as a document type for it in Xcode, which translated to <key>CFBundleDocumentTypes</key> <array> <dict> <key>CFBundleTypeRole</key> <string>Viewer</string> <key>LSHandlerRank</key> <string>Default</string> <key>LSItemContentTypes</key> <array> <string>public.data</string> </array> </dict> </array> in the Info.plist for it, which seems correct. When I drag a .webloc file onto the Dock icon, it appears to be willing to accept it, but nothing seems to happen. In the app, I've got an AppDelegate.swift file which has extension Notification.Name { static let receivedURLsNotification = Notification.Name("ReceivedURLsNotification") } class AppDelegate: NSObject, NSApplicationDelegate { func application(_ application: NSApplication, open urls: [URL]) { guard !urls.isEmpty else { return } NotificationCenter.default.post(name: .receivedURLsNotification, object: nil, userInfo: ["URLs": urls]) } } (I copied it almost verbatim from a Medium post.) In the app swift file, I have @main struct LoggerApp: App, DropDelegate { @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate I set a breakpoint on application(_:NSApplication, open:[URL]), and did my drag, and the breakpoint never triggered. I added the application(didFinishLaunching(_:Notification) method, and that does get invoked when the app launches, so the app delegate does seem to be working. That seems to indicate the problem is somewhere else?
3
0
240
Nov ’24
How to disable Dynamic Island expansion/interaction in SwiftUI Live Activity?
I have implemented a Live Activity with Dynamic Island support for my charging app. Currently, the Dynamic Island expands when tapped, but I want to disable this interaction completely. Here's my current implementation: **dynamicIsland: { context in DynamicIsland { // Expanded Regions DynamicIslandExpandedRegion(.leading) { // Leading expanded content } DynamicIslandExpandedRegion(.trailing) { // Trailing expanded content } DynamicIslandExpandedRegion(.bottom) { // Bottom expanded content } } compactLeading: { // Compact leading view content } compactTrailing: { // Compact trailing view content } minimal: { // Minimal view content } .keylineTint(Color.clear) }**
0
0
185
Nov ’24
onChange stops working after triggering navigationDestination(isPresented:destination:) within NavigationLink
In the code below, changes to the destination value aren't captured by ViewA if: ViewB is navigated to by changing the destination property of ViewModel. ViewA is embedded in a NavigationLink or another navigationDestination. For example, the return button in ViewB doesn't work when accessed from ContentWithinNavigationLink, but it works from ContentDirect. I've also noticed that the code works if I move the presentingViewB property to the ViewModel class. However, in real code, that significantly increases the complexity of ViewModel, as I have more than ten destinations to handle. Each bound with different shapes of data. I'd prefer to store an enum value in ViewModel, listen to it in ViewA, and then convert it to boolean flags and properties in ViewAβ€”just for iOS 16 compatibility. For iOS 17 and above, the enum works perfectly with navigationDestination(item:destination:). class ViewModel: ObservableObject { @Published var destination = "" func gotoB() { destination = "ViewB" } func reset() { destination = "" } } struct ContentWithinNavigationLink: View { var body: some View { NavigationStack { NavigationLink { ViewA() } label: { Text("Goto A") } } } } struct ContentDirect: View { var body: some View { NavigationStack { ViewA() } } } struct ViewA: View { @State private var presentingViewB = false @StateObject private var viewModel = ViewModel() var body: some View { Button { viewModel.gotoB() } label: { Text("goto ViewB") } .navigationDestination(isPresented: $presentingViewB) { ViewB().environmentObject(viewModel) } .onChange(of: viewModel.destination) { newValue in if newValue == "ViewB" { presentingViewB = true } else { presentingViewB = false } } } } struct ViewB: View { @EnvironmentObject var viewModel: ViewModel var body: some View { Button { viewModel.reset() } label: { Text("Return") } .navigationBarBackButtonHidden() } } The reason of using code like Button { viewModel.gotoB() } label: { Text("goto ViewB") } in ViewA is because in real code the Button is actually several subviews where the navigation-triggering code is deeply nested.
2
0
177
Nov ’24
Map in SwiftUI just wont follows users heading when first shown
I want to use a Map to show current location and heading, but the map first show, it just wont work. And when I switch off and switch on again, it works. codes below: BackgroundMapView.swift import SwiftUI import MapKit struct BackgroundMapView: View { var scope: Namespace.ID? private var cameraPosition: MapCameraPosition = .userLocation( followsHeading: true, fallback: .automatic ) private var locations: [Location] init(_ scope: Namespace.ID? = nil, locations: [Location]) { self.scope = scope self.locations = locations } var body: some View { Map( initialPosition: cameraPosition, scope: scope ) { MapPolyline(coordinates: locations.map({ $0.coordinate.toGCJ02 })) .stroke( .red, lineWidth: 3 ) } .mapControlVisibility(.hidden) } } #Preview { MainView() } HomeVIew.swift import SwiftUI struct HomeView: View { @StateObject private var locationManager = LocationManager() @State private var isMapEnabled = UserDefaults.isHomeMapEnabled { didSet { UserDefaults.isHomeMapEnabled = isMapEnabled } } @Namespace private var mapScope var body: some View { if isMapEnabled { BackgroundMapView(mapScope, locations: locationManager.locations) .mapScope(mapScope) } } }
1
0
149
Nov ’24
Unable to change TabView's background color
Hello, I seem to be unable to change TabView's background color (not the bar, but the background of the entire TabView), no matter what I try. What I am looking for: To make the TabView's background clear. My code: TabView(selection: $activeScreen) { Screen1() .tabItem { Label("Menu", systemImage: "list.dash") } } Screen1 is defined as: struct Screen1: View { var body: some View { VStack { Text("Hello") } .frame(maxWidth: .infinity, maxHeight: .infinity) } } What I have tried, based on suggestions online: Changing UITabBarAppearance in init(), and .onAppear() TabView().background(.clear) In all cases, the TabView's background remains either white or black, depending on the device's theme. I can change the background behind it by placing it in a ZStack, but that is not what I am looking for, I want the background itself to be clear. The only way that TabView will honor .background(.clear) is if I add the following: .tabViewStyle(.page) .indexViewStyle(.page(backgroundDisplayMode: .always)) But this changes the style of the TabView, which is not the desired behavior. Any help would be greatly appreciated, thank you!
2
0
202
Nov ’24
MSStickerView in SwiftUI not animating by default
I am working on a sticker app and I am building a custom sticker app in SwiftUI. I have created a custom UIViewRepresentable to allow a MSStickerView to be displayed in SwiftUI. I have local *.gif files in my project and I am loading them into the MSStickerView successfully, however when they are loaded in my iMessage sticker extension the stickers are not animating by default. When I tap on the MSStickerView the gif begins to animate, I'm not sure what else I can do to get this working properly in my app. Some sample code below: public struct CustomStickerView: UIViewRepresentable { var sticker: CustomSticker public init(sticker: CustomSticker) { self.sticker = sticker } public func makeUIView(context: Context) -> MSStickerView { let v = MSStickerView() if sticker.fileType == .gif { v.startAnimating() } return v } public func updateUIView(_ uiView: MSStickerView, context: Context) { uiView.sticker = sticker.sticker } } // CustomSticker public var sticker: MSSticker? { guard let imagePath = Bundle.main.path(forResource: name, ofType: ".\(fileType.rawValue)") else { print("Failed to get sticker - \(name).\(fileType.rawValue)") return nil } let path = URL(fileURLWithPath: imagePath) return try? MSSticker(contentsOfFileURL: path, localizedDescription: name) }
0
0
186
Nov ’24
How can I get the current screen orientation?
Hello, I am working on an iOS app that has interactive components that react to the device accelerometer. The app works in landscape left and right only, and I need some way to identify if the screen is left or right to get the acceleration direction correct. Basically, accelerating to the device's "left" means you actually need to move the elements on screen to the left or right depending on screen direction. One solution I tried is using UIDeviceOrientation. This works in most cases, but when screen lock is on, it gives an update about the device orientation when the screen itself didn't tilt. Is there some other way to get the screen orientation that accurately reflects the screen orientation and not just device orientation? Thank you.
2
0
172
Nov ’24
Scrolling Table with children in SwiftUI for macOS app
How do I scroll to a row and select it when it is part of collapsed rows in Table ScrollViewReader { scrollViewProxy in Table([node], children: \.children, selection: $selectedNodeID) { TableColumn("Key") { Text($0.key) } TableColumn("Value") { Text($0.val) } } .onChange(of: selectedNodeID) { _, newValue in withAnimation { scrollViewProxy.scrollTo(newValue) } } } The code above works well for the rows that are expanded or at the root level. However, for the rows that are not yet expanded the code above does nothing. How can I update the code so that it scrolls to a row that has not materialized yet. Info: This is a macOS app I am on macOS 15.1.1 with Xcode 16.1 and the minimum target of the app is macOS 15
0
0
175
Nov ’24
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
229
Nov ’24
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.
2
0
214
Nov ’24
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
172
Nov ’24
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
189
Nov ’24
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") } }
1
0
210
Nov ’24
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
1
171
Nov ’24
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
224
Nov ’24
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.
4
0
251
Nov ’24
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
192
Nov ’24
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
2
0
220
Nov ’24
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.
10
13
1.2k
Nov ’24