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?
SwiftUI
RSS for tagProvide 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
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!
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!
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.
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)?
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?
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?
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.
Hello,
WatchOS crown not producing any effects in Preview window of Xcode. I tried lower version (10.5) and currently using 11.0 . I tried different faces, sizes, models but none is working, even though it rotates beautifully in preview.
Thanks,
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?
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.
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: <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)}>
(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: <(null)> 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: <(null)> 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: <(null)> 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?
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
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()
}
}
}
}
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.
The app added control widgets and crashed online。
SwiftU!
static ControlWidgetConfigurationAdaptor._makeWidgetConfiguration(widget inputs:)
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?
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?
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.
Hello. Was wondering if anybody has come across code or tutorial on creating a dynamic wind compass. Already tied into weather api, struggling with UI