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

Posts under SwiftUI tag

200 Posts
Sort by:

Post

Replies

Boosts

Views

Activity

WKWebView crashes after repeated reloads on iOS 18
Hi! I have a rather complicated SwiftUI browser app with a WKWebView. There is an option to reload the website after a configurable amount of time. Starting with iOS 18, the app crashes after repeated reloads. How many reloads that are required depends on the device, sometimes 100, sometimes 1000. Reloading is done via a timer that triggers the following code on the main thread: let request = URLRequest(url: url, cachePolicy: policy) self.parent.webView.load(request) The URL is configurable and cachePolicy can be either .reloadIgnoringLocalAndRemoteCacheData or .useProtocolCachePolicy How the crash affects the device also differs from device to device and from time to time. I have suffered from the following crashtypes: App is killed App is killed and Safari also stops working App is killed and the whole OS is really slow The WKWebView stops loading and hangs at 20%. The device is rebooted My app has an option to disable cache. Cache is disabled by setting cachePolicy to .reloadIgnoringLocalAndRemoteCacheData and by removing all cache in a rather complicated way. Basicly i'm doing something like this: dataStore.removeData(ofTypes: types, modifiedSince: Date.distantPast, completionHandler: nil) if let klazz = NSClassFromString("Web" + "History"), let clazz = klazz as AnyObject as? NSObjectProtocol { if clazz.responds(to: Selector(("optional" + "Shared" + "History"))) { if let webHistory = clazz.perform(Selector(("optional" + "Shared" + "History"))) { let o = webHistory.takeUnretainedValue() _ = o.perform(Selector(("remove" + "All" + "Items"))) } } } if let cachesPath = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true).first { let contents = (try? FileManager.default.contentsOfDirectory(atPath: cachesPath)) ?? [] for file in contents { if foldersToDelete.contains(file) { let path = cachesPath.appending("/").appending(file) do { try FileManager.default.removeItem(atPath: path) } catch { print("Can't delete cache file: \(path), error: \(error.localizedDescription)") } } } } The cache state affects the intensity of the crash. Disabling the cache shortens the time the app is working, while enabling the cache reduces the intensity of the bug. Based on my investigation, I suspect that loading a website in a WKWebVew leaks memory in iOS 18. If the whole website needs to be requested (= caching off), it results in a more significant memory leak and a faster crash time. Is this a known issue? Am I doing something wrong? Is there a potential workaround?
2
0
250
2w
SwiftUI Gestures: Sequenced Long Press and Drag
In creating a sequenced gesture combining a LongPressGesture and a DragGesture, I found that the combined gesture exhibits two problems: The @GestureState does not properly update as the gesture progresses through its phases. Specifically, the updating(_:body:) closure (documented here) is only ever executed during the drag interaction. Long presses and drag-releases do not call the updating(_:body:) closure. Upon completing the long press gesture and activating the drag gesture, the drag gesture remains empty until the finger or cursor has moved. The expected behavior is for the drag gesture to begin even when its translation is of size .zero. This second problem – the nonexistence of a drag gesture once the long press has completed – prevents access to the location of the long-press-then-drag. Access to this location is critical for displaying to the user that the drag interaction has commenced. The below code is based on Apple's example presented here. I've highlighted the failure points in the code with // *. My questions are as follows: What is required to properly update the gesture state? Is it possible to have a viable drag gesture immediately upon fulfilling the long press gesture, even with a translation of .zero? Alternatively to the above question, is there a way to gain access to the location of the long press gesture? import SwiftUI import Charts enum DragState { case inactive case pressing case dragging(translation: CGSize) var isDragging: Bool { switch self { case .inactive, .pressing: return false case .dragging: return true } } } struct ChartGestureOverlay<Value: Comparable & Hashable>: View { @Binding var highlightedValue: Value? let chartProxy: ChartProxy let valueFromChartProxy: (CGFloat, ChartProxy) -> Value? let onDragChange: (DragState) -> Void @GestureState private var dragState = DragState.inactive var body: some View { Rectangle() .fill(Color.clear) .contentShape(Rectangle()) .onTapGesture { location in if let newValue = valueFromChartProxy(location.x, chartProxy) { highlightedValue = newValue } } .gesture(longPressAndDrag) } private var longPressAndDrag: some Gesture { let longPress = LongPressGesture(minimumDuration: 0.2) let drag = DragGesture(minimumDistance: .zero) .onChanged { value in if let newValue = valueFromChartProxy(value.location.x, chartProxy) { highlightedValue = newValue } } return longPress.sequenced(before: drag) .updating($dragState) { value, gestureState, _ in switch value { case .first(true): // * This is never called gestureState = .pressing case .second(true, let drag): // * Drag is often nil // * When drag is nil, we lack access to the location gestureState = .dragging(translation: drag?.translation ?? .zero) default: // * This is never called gestureState = .inactive } onDragChange(gestureState) } } } struct DataPoint: Identifiable { let id = UUID() let category: String let value: Double } struct ContentView: View { let dataPoints = [ DataPoint(category: "A", value: 5), DataPoint(category: "B", value: 3), DataPoint(category: "C", value: 8), DataPoint(category: "D", value: 2), DataPoint(category: "E", value: 7) ] @State private var highlightedCategory: String? = nil @State private var dragState = DragState.inactive var body: some View { VStack { Text("Bar Chart with Gesture Interaction") .font(.headline) .padding() Chart { ForEach(dataPoints) { dataPoint in BarMark( x: .value("Category", dataPoint.category), y: .value("Value", dataPoint.value) ) .foregroundStyle(highlightedCategory == dataPoint.category ? Color.red : Color.gray) .annotation(position: .top) { if highlightedCategory == dataPoint.category { Text("\(dataPoint.value, specifier: "%.1f")") .font(.caption) .foregroundColor(.primary) } } } } .frame(height: 300) .chartOverlay { chartProxy in ChartGestureOverlay<String>( highlightedValue: $highlightedCategory, chartProxy: chartProxy, valueFromChartProxy: { xPosition, chartProxy in if let category: String = chartProxy.value(atX: xPosition) { return category } return nil }, onDragChange: { newDragState in dragState = newDragState } ) } .onChange(of: highlightedCategory, { oldCategory, newCategory in }) } .padding() } } #Preview { ContentView() } Thank you!
3
0
243
2w
FocusState and pickers error
Hello, since the last version of iOS and WatchOS I have a problem with this code. This is the minimal version of the code, it have two pickers inside a view of a WatchOS App. The problem its with the focus, I can't change the focus from the first picker to the second one. As I said before, it was working perfectly in WatchOS 10.0 but in 11 the problems started. struct ParentView: View { @FocusState private var focusedField: String? var body: some View { VStack { ChildView1(focusedField: $focusedField) ChildView2(focusedField: $focusedField) } } } struct ChildView1: View { @FocusState.Binding var focusedField: String? @State private var selectedValue: Int = 0 var body: some View { Picker("First Picker", selection: $selectedValue) { ForEach(0..<5) { index in Text("Option \(index)").tag("child\(index)") } }.pickerStyle(WheelPickerStyle()).focused($focusedField, equals: "first") } } struct ChildView2: View { @FocusState.Binding var focusedField: String? @State private var selectedValue: Int = 0 var body: some View { Picker("Second Picker", selection: $selectedValue) { ForEach(0..<5) { index in Text("Option \(index)").tag("childTwo\(index)") } }.pickerStyle(WheelPickerStyle()).focused($focusedField, equals: "second") } } When you do vertical scrolling on the second picker, the focus should be on it, but it dosnt anything. I try even do manually, setting the focusState to the second one, but it sets itself to nil. I hope that you can help me, thanks!
3
0
242
1w
document-based sample code doesn't work... work around?
I just tried the "Building a document-based app with SwiftUI" sample code for iOS 18. https://developer.apple.com/documentation/swiftui/building-a-document-based-app-with-swiftui I can create a document and then close it. But once I open it back up, I can't navigate back to the documents browser. It also struggles to open documents (I would tap multiple times and nothing happens). This happens on both simulator and device. Will file a bug, but anyone know of a work-around? I can't use a document browser that is this broken.
1
1
174
2w
send data or share variables between Immersive view and "attached" 2D view
I have an immersive space with a RealityKit view which is running an ARKitSession to access main camera frames. This frame is processed with custom computer vision algorithms (and deep learning models). There is a 3D Entity in the RealityKit view which I'm trying to place in the world, but I want to debug my (2D) algorithms in an "attached" view (display images in windows). How to I send/share data or variables between the views (and and spaces)?
1
0
194
2w
Content size of NSWindow returns zero frame after setting view on macOS 15.0 and xCode 16.1
I would like to show a nswindow at a position on screen base on height of the nswindow and its content view. I received zero width and height on macOS 15.0 and xCode 16.1 however they were returned correct width and height on previous macOS version. import Cocoa import SwiftUI class AppDelegate: NSObject, NSApplicationDelegate { private var window: NSWindow! func applicationDidFinishLaunching(_ aNotification: Notification) { window = NSWindow( contentRect: .zero, styleMask: [.miniaturizable, .closable, .resizable], backing: .buffered, defer: false) window.title = "No Storyboard Window" window.contentView = NSHostingView(rootView: ContentView()) // a swiftui view window.center() let windowFrame = window.frame print("window Frame \(windowFrame)") // print width and height zero here window.makeKeyAndOrderFront(nil) } } struct ContentView: View { var body: some View { VStack { Image(systemName: "globe") .imageScale(.large) .foregroundStyle(.tint) Text("Hello, world!") } .padding() } } I tried window.layoutIfNeeded() after setting contentview but it didn't work How can I get the frame after setting contentview for nswindow on macOS 15.0?
1
0
222
2w
SwiftUI 'List' performance issue on macOS
Hi, When using SwiftUI ‘List’ with a large number of elements (4000+), I noticed a significant performance issue if extracting the views inside the ‘ForEach’ block into their own subview class. It affects scrolling performance, and using the scroll handle in the scrollbar causes stutters and beachballs. This seems to happen on macOS only ... the same project works fine on iOS. Here's an example of what I mean: List (selection: $multiSelectedContacts) { ForEach(items) { item in // 1. this subview is the problem ... replace it with the contents of the subview, and it works fine PlainContentItemView(item: item) // 2. Uncomment this part for it to work fine (and comment out PlainContentItemView above) /*HStack { if let timestamp = item.timestamp, let itemNumber = item.itemNumber { Text("\(itemNumber) - \(timestamp, formatter: itemFormatter)") } }*/ } } struct PlainContentItemView: View { let item: Item var body: some View { HStack { if let timestamp = item.timestamp, let itemNumber = item.itemNumber { Text("\(itemNumber) - \(timestamp, formatter: itemFormatter)") } } } } Item is a NSManagedObject subclass, and conforms to Identifiable by using the objectID string value. With this, scrolling up and down using the scrolling handle, causes stuttering scrolling and can beachball on my machine (MacBook Pro M1). If I comment out the ‘PlainContentItemView’ and just use the HStack directly (which is what was extracted to ‘PlainContentItemView’), the performance noticeably improves, and I can scroll up and down smoothly. Is this just a bug with SwiftUI, and/or can I do something to improve this?
0
0
177
3w
Pre-initialization of views?
It seems somewhere around the update to xcode 16 and swift 6, apple may have decided to change when view are initialized. My views suddenly pre-initialize before opening the view. Is this a new feature? I have a regular VStack or a LazyVStack, with ForEach and navigationLinks inside. Those views that the navigation link takes you to are initializing as I am scrolling in the VStack. This is absurd, there is so much overhead going on in these views to be initialized. I can think of a fix which is to implement init functions in the onAppear, and keep a property to track if view already appeared. But before that I just want to make sure this is a new feature and not some mishap on my part, and if there is a way to disable it. Thank you.
2
0
123
2w
Issue with .itemProvider on macOS 15.1
I have a List with draggable items. According to this thread (https://developer.apple.com/forums/thread/664469) I had to use .itemProvider instead of .onDrag, because otherwise the selection of the list will not work anymore. The items in my list refer to a file URL. So the dragging allowed to copy the files to the destination of the drag & drop. Therefore I used this code .itemProvider { let url = ....... // get the url with an internal function return NSItemProvider(object: url as NSURL) } Since the update to macOS 15.1 this way isn't working anymore. It just happens nothing. I also tried to use .itemProvider { let url = .... return NSItemProvider(contentsOf: url) ?? NSItemProvider(object: url as NSURL) } but this doesn't work too. The same way with .onDrag works btw. .onDrag { let url = ....... // get the url with an internal function return NSItemProvider(object: url as NSURL) } but as I wrote, this will break the possibility to select or to use the primaryAction of the .contextMenu. Is this a bug? Or is my approach wrong and is there an alternative?
5
0
162
2h
iOS18.1 Issue SwiftUI’s App
The interactiveDismissDisabled() function in SwiftUI's Sheet no longer works as expected in iOS 18.1 (22B83). It was working as expected until iOS 18.0.1. Are there any other users experiencing the same issue? struct ContentView: View { @State private var openSheet = false var body: some View { NavigationStack { Button("Open") { openSheet = true } .sheet(isPresented: $openSheet) { SheetView() } } } } struct SheetView: View { @Environment(\.dismiss) private var dismiss var body: some View { NavigationStack { Text("This is the Sheet") .toolbar { ToolbarItem(placement: .cancellationAction) { Button("Cancel") { dismiss() } } } .interactiveDismissDisabled() } } } Supplementary information: In iOS 18.1, even Apple's native Journal app allows users to swipe-to-dismiss the sheet when creating a new entry. Previously, a confirmation dialog would be displayed, but this is no longer the case.​​​​​​​​​​​​​​​​
2
1
297
3w
'Save to Files' doesn't work with ShareLink with FileRepresentation
I want to use ShareLink+FileRepresentation to save a small text file to my iPhone with the steps below. Tap [Share...] to display the share sheet. This sheet contains [Save to Files]. Tap [Save to Files]. A black sheet is displayed, but it disappears instantly. In step 3, I was expecting a browser to be displayed to select the location where the file will be saved. But in fact, a black sheet appears, which quickly disappears. The implemented code is as follows. import SwiftUI @main struct SLSandboxApp: App { var body: some Scene { WindowGroup { let title = Text("File Output") let numListString = "123,456,789" let numListFileName = "numlist.csv" let tagListFile = TextFile(content: numListString, filename: numListFileName) ShareView(title: title, fileToShare: tagListFile, messageToPreview: numListFileName) } } } struct ShareView: View { let title: Text let fileToShare: TextFile let messageToPreview: String var body: some View { ShareLink(item: self.fileToShare, preview: SharePreview(self.messageToPreview)) } } struct TextFile: Transferable { let content: String let filename: String static var transferRepresentation: some TransferRepresentation { FileRepresentation(exportedContentType: .data) { textFile in let data = textFile.content.data(using: .utf8) ?? Data() let tempDirectory = FileManager.default.temporaryDirectory let fileURL = tempDirectory.appendingPathComponent(textFile.filename) try data.write(to: fileURL) return SentTransferredFile(fileURL) } } } The development environment is as follows. Xcode 15.4 (Deployment Target = iOS Deployment Target 17.5) macOS 14.6.1 The execution environment is as follows. iPhone SE Gen3 17.7 The following is a console log from the time the application was launched to the time when the share sheet was displayed by tapping [Share...]. Error acquiring assertion: &lt;Error Domain=RBSServiceErrorDomain Code=1 "(originator doesn't have entitlement com.apple.runningboard.primitiveattribute AND originator doesn't have entitlement com.apple.runningboard.assertions.frontboard AND target is not running or doesn't have entitlement com.apple.runningboard.trustedtarget AND Target not hosted by originator)" UserInfo={NSLocalizedFailureReason=(originator doesn't have entitlement com.apple.runningboard.primitiveattribute AND originator doesn't have entitlement com.apple.runningboard.assertions.frontboard AND target is not running or doesn't have entitlement com.apple.runningboard.trustedtarget AND Target not hosted by originator)}&gt; (501) personaAttributesForPersonaType for type:0 failed with error Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service named com.apple.mobile.usermanagerd.xpc was invalidated: failed at lookup with error 159 - Sandbox restriction." UserInfo={NSDebugDescription=The connection to service named com.apple.mobile.usermanagerd.xpc was invalidated: failed at lookup with error 159 - Sandbox restriction.} Received port for identifier response: &lt;(null)&gt; with error:Error Domain=RBSServiceErrorDomain Code=1 "Client not entitled" UserInfo={RBSEntitlement=com.apple.runningboard.process-state, NSLocalizedFailureReason=Client not entitled, RBSPermanent=false} elapsedCPUTimeForFrontBoard couldn't generate a task port Received port for identifier response: &lt;(null)&gt; with error:Error Domain=RBSServiceErrorDomain Code=1 "Client not entitled" UserInfo={RBSEntitlement=com.apple.runningboard.process-state, NSLocalizedFailureReason=Client not entitled, RBSPermanent=false} elapsedCPUTimeForFrontBoard couldn't generate a task port Received port for identifier response: &lt;(null)&gt; with error:Error Domain=RBSServiceErrorDomain Code=1 "Client not entitled" UserInfo={RBSEntitlement=com.apple.runningboard.process-state, NSLocalizedFailureReason=Client not entitled, RBSPermanent=false} elapsedCPUTimeForFrontBoard couldn't generate a task port The following is the console log that was written when I tapped [Save to file] on the share sheet. cancelled request - error: The operation couldn’t be completed. Invalid argument What modifications should I make to the code to get the expected result?
0
0
174
3w
SwiftUI TabView lifecycle is weird
I tested the life cycle of TabView and its sub-Views through the demo and found something strange. Please help analyze it. Thank you. The demo project is here https://feedbackassistant.apple.com/feedback/15629780 Operation steps: Step 1: launch app Step 2: click Login button the below log is correct SettingsViewModel init HomeViewModel init HomeView appear Step 3: click Settings tab SettingsView appear (correct) Step 4: click Refresh TabView button the below log is incorrect Refresh TabView StatusViewModel init AccountViewModel init StatusViewModel init (weird) AccountViewModel init (weird) HomeView appear (weird) StatusViewModel deinit AccountViewModel deinit AccountView appear SettingsViewModel deinit HomeViewModel deinit Expect log: Refresh TabView SettingsViewModel deinit HomeViewModel deinit StatusViewModel init AccountViewModel init AccountView appear
0
0
159
3w
UIHostingConfiguration + MainActor.assumeIsolated?
I'm trying to use a SwiftUI view as UICalendarView decoration and I get Call to main actor-isolated instance method 'makeContentView()' in a synchronous nonisolated context; this is an error in the Swift 6 language mode in the following code: class Coordinator: NSObject, UICalendarViewDelegate { func calendarView(_ calendarView: UICalendarView, decorationFor dateComponents: DateComponents) -> UICalendarView.Decoration? { .customView { UIHostingConfiguration { ... } .makeContentView() } } } I've fixed using MainActor.assumeIsolated but is this the correct approach or is there a better one? class Coordinator: NSObject, UICalendarViewDelegate { func calendarView(_ calendarView: UICalendarView, decorationFor dateComponents: DateComponents) -> UICalendarView.Decoration? { .customView { MainActor.assumeIsolated { UIHostingConfiguration { ... } .makeContentView() } } } }
1
0
160
3w
Widget Intent does not work on macOS Sequoia
Environment Xcode: 16.1 Swift 6 and SwiftUI for macOS development macOS Sequoia I have an app for macOS, and that uses an interactive widget feature. On macOS Sequoia, the widget does not display anything and widget intent doesn't work either. I tested it on macOS Sonoma and it totally works. I assume it's a macOS bug. The app has been working fine before Sequoia. Even on Xcode, when I tried to run the widget preview, Failed to load widget. The operation couldn't be completed. (WidgetKit_Simulator.WidgetDocument.Error error 4.). I could avoid the error by changing version and build numbers, but I still got The operation couldn't be completed. (CHSErrorDomain error 1103.) How am I able to fix the issue? I wanna at least know if its a bug from the app or macOS Sequoia.
0
0
131
3w
SwiftUI - Horizontal Scroll not Working with NSTextView in NSViewRepresentable
Hello, I have an NSViewRepresentable displaying an NSTextView in SwiftUI. GeometryReader() { geometry in ScrollView([.vertical, .horizontal]) { Representable() // -18 for vertical scroller .frame(minWidth: geometry.size.width - 18) } } When I use the vertical scrollbar the mouse click is passed to the Representable and is not registered by the Scroll bar. In the image you can see I tried to use the scroll bar and it highlighted some text instead. There is a suggestion on stackoverflow to use an overlay. This fixes the scrolling issue, but will then make the Representable uninteractable. How can I use the horizontal scroll bar here as expected?
1
0
187
3w
PersonNameComponents TextField Not Responding As Expected on macOS
Using this adapted code snippet from the Apple Developer Documentation, struct ContentView: View { @State var nameComponents = PersonNameComponents() var body: some View { Form { TextField( "Proper name", value: $nameComponents, format: .name(style: .medium) ) .onSubmit { } .disableAutocorrection(true) .border(.secondary) Text(nameComponents.debugDescription) } } } It runs and works as expected on my iOS device. When I use this same code in my macOS app, it has unexpected results. The validation mechanism (likely caused by format: .name(style: .medium) in order to bind the TextField to a PersonNameComponents instance, will not let me add spaces or delete all the text in the TextField. I have to write the first name in this format: "FirstLast" and then add a space in between the t and L. Are there any ways I can fix this on macOS while still binding my TextField to a PersonNameComponents instance?
0
0
141
3w
I can’t understand this SwiftUI compile error.
Text("Sample Text with wrong font type") .font(.bold) I know this code is incorrect, and it returns an error stating that .font doesn’t have a .bold type. However, when I place this incorrect code within a stack… …no error message appears. Instead, I get: The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions when trying to run the code. It’s unclear why the compiler doesn’t specify that the issue originates from .font(.bold). This was confusing, and I spent 20 minutes figuring out it was a typo.
3
0
188
3w