I have drag-and-drop functionality in the macOS app built with SwiftUI.
Since macOS 15 there is an issue with it, because as I found out, the completion block of loadObject method on NSItemProvider is not called until dropExited delegate method is called (see simplified code example below).
It causes very strange behavior in my app, for one of the most important features, and I am looking for a way to fix it as soon as possible.
Is anyone seeing the same issue?
I saw there was a bug with drag and drop on iOS 18, which seems to be fixed in 18.1. Anyone from Apple can say anything about this change in behaviour?
@Observable // Because it is injected via environment.
final class DragAndDropDelegate<T: Codable>: DropDelegate {
func dropEntered(info: DropInfo) {
// Is called as expected.
guard
let itemProvider = info.itemProviders(for: [UTType.data]).first
else { return }
itemProvider.loadObject(ofClass: DraggableObject<T>.self) { [weak self] (object, error) in
// This is only called after dropExited delegate method is called !!!
// Before macOS 15.0 it is called quickly after the loadObject method invokation.
asyncOnMainThread {
guard
let self,
let draggableObject = object as? DraggableObject<T>
else { return }
self.onEnter?(draggableObject.object, info.location)
}
}
}
func dropExited(info: DropInfo) {
// Is called as expected.
}
}
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
I need a magnifying glass function for one of my SwiftUI Views, but can't find a way to implement it as needed.
I found a Youtube video where the author renders the view twice, overlaying the second over the first, then scaling and masking it to create the illusion of magnification, but this is expensive and doesn't work in many cases where more complex views are presented (e.g. a LazyVGrid).
I've also explored continually capturing partial screenshots and scaling them up to create the illusion of magnification, but there's no straightforward way to achieve this with SwiftUI without getting into the messiness of UIViewRepresentables.
Any help would be greatly appreciated
In visionOS, i have been trying to implement this view as a background for information view, but i cannot find any information about it anywhere. Does anyone know what this is called or any workaround to achieve this look?
Hi all,
by chance, we introduced code similar to the following in the body of one of our views:
struct MyView: View {
let myInt: Int
var body: some View {
EmptyView() // Empty body
.onChange(of: myInt) { newValue in
…
}
}
}
Notice that a simple let of type Int is used here, rather than State or something similar. While it works and onChange is actually triggered when views are rebuilt, I’d like to clarify a few things:
Is this behavior actually expected and reliable, or is it a gray area and can be changed in the future?
If it is expected, can this be made clearer in the documentation?
If it is a gray area, can the documentation be improved to address it?
Thanks!
I integrated the image playground sheet in my app, however when I select Take Photo on the iOS version of my app it just reloads the sheet. After several attempts I get the below error message.
This issue doesn’t occur on the macOS version of my app, where it first requests camera permission before allowing me to take the photo.
I’m not sure if this is happening because I don’t request the camera permission anywhere in my app. My app doesn’t use the camera at all apart from the Take Photo feature which is part of the image playground sheet.
Feedback ID: FB15591786
A Swift MacOS works with no problem on Intel or ARM Macs (from 11, BigSur to 15, Sequoia) but recently I learned that is crashes when launched on a Mac which language is set to French.
I'm not saying this setting is causing the issue, but is the most obvious difference observed compared to many other Macs where the App runs with no problem.
The crash occurred in a MacOS intel. See excerpts from crash report below:
Process: MySwiftAPP [626]
Path: /Volumes/VOLUME/*/MySwiftAPP.app/Contents/MacOS/MySwiftAPP
Identifier: Myinfo.MYSwiftAPP
Version: X.Y.01 (1)
Code Type: X86-64 (Native)
Parent Process: launchd [1]
User ID: 501
Date/Time: 2021-01-05 01:47:12.0578 +0100
OS Version: macOS 12.2.1 (21D62)
Report Version: 12
Bridge OS Version: 3.0 (14Y910)
Anonymous UUID: 3579800E-84CC-15C4-2981-320ECF2E1400
Time Awake Since Boot: 62 seconds
System Integrity Protection: enabled
Crashed Thread: 0 Dispatch queue: com.apple.main-thread
Exception Type: EXC_BAD_INSTRUCTION (SIGILL)
Exception Codes: 0x0000000000000001, 0x0000000000000000
Exception Note: EXC_CORPSE_NOTIFY
Termination Reason: Namespace SIGNAL, Code 4 Illegal instruction: 4
Terminating Process: exc handler [626]
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0 MySwiftAPP 0x10c6df5bb 0x10c61d000 + 796091
1 MySwiftAPP 0x10c6be4dc 0x10c61d000 + 660700
2 SwiftUI 0x7ff919a8ff0e closure #1 in AppearanceActionModifier.MergedBox.update() + 72
3 SwiftUI 0x7ff9193d2047 thunk for @escaping @callee_guaranteed () -> () + 12
4 SwiftUI 0x7ff919a91012 partial apply for thunk for @escaping @callee_guaranteed () -> () + 17
5 SwiftUI 0x7ff919bbc028 closure #1 in ViewRendererHost.render(interval:updateDisplayList:) + 2414
6 SwiftUI 0x7ff919ba9fbe ViewRendererHost.render(interval:updateDisplayList:) + 359
7 SwiftUI 0x7ff919c04d56 closure #1 in NSHostingView.layout() + 126
8 SwiftUI 0x7ff919c0dce7 partial apply for thunk for @callee_guaranteed (@guaranteed NSAnimationContext) -> () + 17
9 SwiftUI 0x7ff919c023fd thunk for @escaping @callee_guaranteed (@guaranteed NSAnimationContext) -> () + 36
10 AppKit 0x7ff8113fa152 +[NSAnimationContext runAnimationGroup:] + 55
11 SwiftUI 0x7ff919c04c8a NSHostingView.layout() + 287
12 SwiftUI 0x7ff919c0508a @objc NSHostingView.layout() + 21
13 AppKit 0x7ff811435d7f NSViewLayout + 564
14 AppKit 0x7ff811435851 -[NSView layoutSubtreeWithOldSize:] + 352
15 AppKit 0x7ff811434d68 -[NSView layoutSubtreeIfNeededAndAllowTemporaryEngine:] + 1041
16 AppKit 0x7ff811677f22 +[NSWindow windowWithContentViewController:] + 57
17 SwiftUI 0x7ff9199cd634 specialized WindowStyle.makeWindow(:) + 42
18 SwiftUI 0x7ff919b6c724 AnyWindowStyleStorage.makeWindow(:) + 26
19 SwiftUI 0x7ff91974a736 AppWindowsController.makeWindowController(:restorationID:environment:) + 2314
20 SwiftUI 0x7ff91974887d AppWindowsController.makeMainWindow(info:) + 66
21 SwiftUI 0x7ff9197487c7 AppWindowsController.makeMainWindow() + 424
22 SwiftUI 0x7ff919748067 AppWindowsController.showInitialMainWindow() + 82
23 SwiftUI 0x7ff9194e0c3e AppDelegate.applicationDidFinishLaunching(:) + 85
24 SwiftUI 0x7ff9194e0dd6 @objc AppDelegate.applicationWillFinishLaunching(_:) + 114
25 CoreFoundation 0x7ff80e9a6f23 CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER + 12
26 CoreFoundation 0x7ff80ea443f9 ___CFXRegistrationPost_block_invoke + 49
27 CoreFoundation 0x7ff80ea44376 _CFXRegistrationPost + 496
28 CoreFoundation 0x7ff80e978836 _CFXNotificationPost + 733
29 Foundation 0x7ff80f7c01be -[NSNotificationCenter postNotificationName:object:userInfo:] + 82
30 AppKit 0x7ff8113e761b -[NSApplication _postDidFinishNotification] + 305
31 AppKit 0x7ff8113e736d -[NSApplication _sendFinishLaunchingNotification] + 208
32 AppKit 0x7ff8113e4f40 -[NSApplication(NSAppleEventHandling) _handleAEOpenEvent:] + 541
33 AppKit 0x7ff8113e4b97 -[NSApplication(NSAppleEventHandling) _handleCoreEvent:withReplyEvent:] + 665
34 Foundation 0x7ff80f7eb194 -[NSAppleEventManager dispatchRawAppleEvent:withRawReply:handlerRefCon:] + 308
35 Foundation 0x7ff80f7eb006 _NSAppleEventManagerGenericHandler + 80
36 AE 0x7ff815043d28 0x7ff815038000 + 48424
37 AE 0x7ff815043592 0x7ff815038000 + 46482
38 AE 0x7ff81503c9c7 aeProcessAppleEvent + 419
39 HIToolbox 0x7ff8175fdc42 AEProcessAppleEvent + 54
40 AppKit 0x7ff8113df222 DPSNextEvent + 2064
41 AppKit 0x7ff8113dd3f4 -[NSApplication(NSEvent) nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 1411
42 AppKit 0x7ff8113cf919 -[NSApplication run] + 586
43 AppKit 0x7ff8113a37b7 NSApplicationMain + 816
44 SwiftUI 0x7ff9191dad3f specialized runApp(:) + 161
45 SwiftUI 0x7ff919bf9c84 runApp(:) + 164
46 SwiftUI 0x7ff91970191f static App.main() + 63
47 MySwiftAPP 0x10c6be9ae 0x10c61d000 + 661934
48 dyld 0x1134d64fe start + 462
Thread 1:
0 libsystem_pthread.dylib 0x7ff80e8e5fec start_wqthread + 0
Thread 0 crashed with X86 Thread State (64-bit):
rax: 0x0000000200000003 rbx: 0x00007f8db5915210 rcx: 0xfffffffe00000000 rdx: 0x0000000000000003
rdi: 0x00007f8db586b178 rsi: 0x00007ff8518bbf58 rbp: 0x00007ff7b38e0080 rsp: 0x00007ff7b38e0000
r8: 0x0000000000000002 r9: 0x80000000ffffffff r10: 0xfffffffe00000000 r11: 0x0000000000000001
r12: 0x00007f8db586b170 r13: 0x00007f8db586bb40 r14: 0x00007f8db586b290 r15: 0xe800000000000000
rip: 0x000000010c6df5bb rfl: 0x0000000000010297 cr2: 0x00007ff8510288e8
Logical CPU: 0
Error Code: 0x00000000
Trap Number: 6
Hello,
SwiftData is not working correctly with Swift Concurrency. And it’s sad after all this time.
I personally found a regression. The attached code works perfectly fine on iOS 17.5 but doesn’t work correctly on iOS 18 or iOS 18.1.
A model can be updated from the background (Task, Task.detached or ModelActor) and refreshes the UI, but as soon as the same item is updated from the View (fetched via a Query), the next background updates are not reflected anymore in the UI, the UI is not refreshed, the updates are not merged into the main.
How to reproduce:
Launch the app
Tap the plus button in the navigation bar to create a new item
Tap on the “Update from Task”, “Update from Detached Task”, “Update from ModelActor” many times
Notice the time is updated
Tap on the “Update from View” (once or many times)
Notice the time is updated
Tap again on “Update from Task”, “Update from Detached Task”, “Update from ModelActor” many times
Notice that the time is not update anymore
Am I doing something wrong? Or is this a bug in iOS 18/18.1?
Many other posts talk about issues where updates from background thread are not merged into the main thread. I don’t know if they all are related but it would be nice to have
1/ bug fixed, meaning that if I update an item from a background, it’s reflected in the UI, and
2/ proper documentation on how to use SwiftData with Swift Concurrency (ModelActor). I don’t know if what I’m doing in my buttons is correct or not.
Thanks,
Axel
import SwiftData
import SwiftUI
@main
struct FB_SwiftData_BackgroundApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.modelContainer(for: Item.self)
}
}
}
struct ContentView: View {
@Environment(\.modelContext) private var modelContext
@State private var simpleModelActor: SimpleModelActor!
@Query private var items: [Item]
var body: some View {
NavigationView {
VStack {
if let firstItem: Item = items.first {
Text(firstItem.timestamp, format: Date.FormatStyle(date: .omitted, time: .standard))
.font(.largeTitle)
.fontWeight(.heavy)
Button("Update from Task") {
let modelContainer: ModelContainer = modelContext.container
let itemID: Item.ID = firstItem.persistentModelID
Task {
let context: ModelContext = ModelContext(modelContainer)
guard let itemInContext: Item = context.model(for: itemID) as? Item else { return }
itemInContext.timestamp = Date.now.addingTimeInterval(.random(in: 0...2000))
try context.save()
}
}
.buttonStyle(.bordered)
Button("Update from Detached Task") {
let container: ModelContainer = modelContext.container
let itemID: Item.ID = firstItem.persistentModelID
Task.detached {
let context: ModelContext = ModelContext(container)
guard let itemInContext: Item = context.model(for: itemID) as? Item else { return }
itemInContext.timestamp = Date.now.addingTimeInterval(.random(in: 0...2000))
try context.save()
}
}
.buttonStyle(.bordered)
Button("Update from ModelActor") {
let container: ModelContainer = modelContext.container
let persistentModelID: Item.ID = firstItem.persistentModelID
Task.detached {
let actor: SimpleModelActor = SimpleModelActor(modelContainer: container)
await actor.updateItem(identifier: persistentModelID)
}
}
.buttonStyle(.bordered)
Button("Update from ModelActor in State") {
let container: ModelContainer = modelContext.container
let persistentModelID: Item.ID = firstItem.persistentModelID
Task.detached {
let actor: SimpleModelActor = SimpleModelActor(modelContainer: container)
await MainActor.run {
simpleModelActor = actor
}
await actor.updateItem(identifier: persistentModelID)
}
}
.buttonStyle(.bordered)
Divider()
.padding(.vertical)
Button("Update from View") {
firstItem.timestamp = Date.now.addingTimeInterval(.random(in: 0...2000))
}
.buttonStyle(.bordered)
} else {
ContentUnavailableView(
"No Data",
systemImage: "slash.circle", //
description: Text("Tap the plus button in the toolbar")
)
}
}
.toolbar {
ToolbarItem(placement: .primaryAction) {
Button(action: addItem) {
Label("Add Item", systemImage: "plus")
}
}
}
}
}
private func addItem() {
modelContext.insert(Item(timestamp: Date.now))
try? modelContext.save()
}
}
@ModelActor
final actor SimpleModelActor {
var context: String = ""
func updateItem(identifier: Item.ID) {
guard let item = self[identifier, as: Item.self] else {
return
}
item.timestamp = Date.now.addingTimeInterval(.random(in: 0...2000))
try! modelContext.save()
}
}
@Model
final class Item: Identifiable {
var timestamp: Date
init(timestamp: Date) {
self.timestamp = timestamp
}
}
I have an app that I'm working on where I'd like to use the .presentationDetents modifier and I need the view to not be dismissed by the user. I'm therefore using the .interactiveDismissDisabled modifier. Unfortunately, that means that the Map on the ContentView can no longer respond to touch gestures. How can I have a similar experience to the Maps app where the underlying Map (or other views) can be interacted with and the user can still be prevented from dismissing the view controlled by the .presentationDetents modifier?
SomeView(searchResults: $searchResults, selectedItem: $selectedItem)
.presentationDetents([.height(100), .medium])
.presentationDragIndicator(.visible)
.interactiveDismissDisabled(true)
Hello! SwiftUI preview does not work. I tried different versions of Xcode, deleting the "Developer" folders, clearing the "Build" folder from the project in Xcode, reinstalling Command Line Tools and Developer Tools. I think that the error appeared after I cleaned Xcode with CleanMyMacX, before that the preview worked.
-MacBook Pro (15-inch, Mid 2012)
-macOS Catalina 10.15.7
-Xcode 12.3
Thanks for the feedback!
Running up Xcode 16.2 Beta 1, a lot of my code that used onPreferenceChange in Views to change @State properties of those views, such as some notion of a measured width is now complaining about mutating the @MainActor-isolated properties from Sendable closures.
Now I've got to hoop-jump to change @State properties from onPreferenceChange? OK, but seems a bit of extra churn.
I have a ScrollView which has inside a LazyVStack and multiple rows. On the appearing of the ScrollView, I scroll to row 250.
When having the VoiceOver running, after opening the app, the focus is on the navigation title as it should be, than, after swiping right to enter the ScrollView, one would expect the focus to be placed on the first visible row, but this is not the case, it scrolls back to some row and focus on that, than reads it.
Here is the code to reproduce it, and if you ask me, this is pretty standard stuff I don't do anything special.
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationView {
ScrollViewReader { scrollProxy in
ScrollView {
LazyVStack {
ForEach(1...500, id: \.self) { index in
NavigationLink(destination: DetailView(row: index)) {
Text("Row \(index)")
.padding()
.frame(maxWidth: .infinity)
.background(Color.gray.opacity(0.2))
.cornerRadius(8)
.padding(.horizontal)
}
}
}
}
.onAppear {
// Scroll to row 250 when the view appears
withAnimation {
scrollProxy.scrollTo(250, anchor: .center)
}
}
}
.navigationTitle("Rows")
}
}
}
struct DetailView: View {
let row: Int
var body: some View {
VStack {
Text("Detail for Row \(row)")
.font(.largeTitle)
.padding()
Spacer()
}
.navigationTitle("Row \(row) Details")
}
}
@main
struct ScrollViewExampleApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
A UI test case that checks for the existence of a SwiftUI Text element initialized with an empty string previously reliably passed in iOS 17.
In iOS 18 the assertion reliably fails.
I searched the iOS 18 developer release notes for anything possibly related to this but didn't find much. I'd like to point to a conclusive change in iOS handling before changing the test permantently. Can anyone confirm that this is indeed a change in iOS 18?
Any CoreData experts know what could be going on here when trying to display to-many entity type relationship data?
On initialisation my model does an fetch request for an entity called Expense, and some prefetching for related entities (to-many type) like this: request.relationshipKeyPathsForPrefetching = ["splits"]
I was under the impression that calling a property on one of the related entities should fire the fault (if there is one) and give me the value. Here’s where it starts to go wrong. I have a property in my extension that I use in my detailed view:
public var viewExpenseSplits: [ExpenseSplit] {
return splits?.allObjects as? [ExpenseSplit] ?? []
}
and then a list in my detail view:
List(expense.viewExpenseSplits, id: \.self) { split in
Text(split.amount ?? "")
}
Result:
What's even more baffling is that I have no problem viewing these splits in the parent view. I thought perhaps I would have more luck passing the viewExpenseSplits through to the detail view instead of trying to access them from the Expense entity itself. Whilst I can print the data out when the view loads, my list still has the same problem.
I thought this would be trivial. Can anyone point to me where I'm going wrong?
Thanks!
Hello. I am here to report a problem.
I was investigating the strange behaviour of my text animation, and I've found out that unrelated TimelineView is causing the problem.
text is animating on change and there are colors on background (in ZStack) that change using TimelineView.
As a result, when the text changes, it twitches, until it fills the whole screen width. If I pause TimelineView animation, everything works smoothly
The problem occurs only on a real device. I've tested on iOS 17 and 18
Example code
struct ContentView: View {
@State var open = false
let colors: [Color] = [.cyan, .red, .green, .gray, .blue, .orange, .pink, .purple]
@State var i: Int = 0
@State
var text: String = chunks[0]
@State var pause = false
var body: some View {
ZStack {
TimelineView(.animation(minimumInterval: 1.2, paused: pause)) { context in
let color = colors[Int(context.date.timeIntervalSinceReferenceDate) % colors.count]
ZStack {
color
.animation(.easeInOut(duration: 1.2))
Rectangle().fill(Material.regular).edgesIgnoringSafeArea(.all)
}
}
VStack {
Spacer()
Text(text)
.font(.system(size: 32))
.multilineTextAlignment(.center)
.padding()
.animation(.linear(duration: 0.1), value: text)
Spacer()
Button("Add text") {
if i < (chunks.count - 1) {
i += 1
} else {
i = 0
text = ""
}
text.append(" " + chunks[i])
}
Button("Toggle background animation") {
pause.toggle()
}
}
}
}
}
let lyrics = "I'm born to run down rocky cliffs Give me grace, bury my sins Shattered glass and black holes Can't hold me back from where I need to go"
let chunks = lyrics.components(separatedBy: " ")
As the title states, this severely limits the flexibility of multi-window applications in creating a good user experience.
Even effects like the ones shown below cannot be achieved.
I can't wrap my head around how to make two buttons the same width, without resorting to ugly hacks like GeometryReader. What is otherwise easy to implement using UIStackView or AutoLayout, becomes a nightmare in SwiftUI.
I tried the following, plus some other variations, but nothing works. What is the "official way" to make two vertically aligned buttons of the same width?
1)
VStack(alignment: .leading) {
Button("Short", action: {})
.frame(maxWidth: .infinity)
Button("Long title", action: {})
.frame(maxWidth: .infinity)
}
.frame(maxWidth: .infinity)
2)
VStack(alignment: .leading) {
Button(action: {}) {
Text("Short")
.frame(maxWidth: .infinity)
}
Button(action: {}) {
Text("Long title")
.frame(maxWidth: .infinity)
}
}
.frame(maxWidth: .infinity)
3)
VStack(alignment: .leading) {
Button(action: {}) {
Text("Short")
}.frame(maxWidth: .infinity)
Button(action: {}) {
Text("Long title")
}.frame(maxWidth: .infinity)
}
.frame(maxWidth: .infinity)
I'm trying to make a Swift Chart where 24 AreaMarks an hour apart on X axis over a day display a vertical gradient.
The gradient is vertical and is essentially [Color.opacity(0.1),Colour,Color.opacity(0.1]
The idea here is where the upper and lower points of each AreaMark are the same or close to each other in the Y axis, the chart essentially displays a line, where they are far apart you get a nice fading vertical gradient.
However, it seems that the .alignsMarkStylesWithPlotArea modifier is always set for AreaMarks even if manually applying it false.
Investigating further, I've learnt that with AreaMarks in a series, Swift Charts seems to only listen to the first foreground style set in. I've created some sample code to demonstrate this.
struct DemoChartView: View {
var body: some View {
Chart {
AreaMark(x: .value("Time", Date().addingTimeInterval(0)), yStart: .value("1", 40), yEnd: .value("2", 60))
.foregroundStyle(LinearGradient(colors: [.pink, .teal], startPoint: .top, endPoint: .bottom))
.alignsMarkStylesWithPlotArea(false)
AreaMark(x: .value("Time", Date().addingTimeInterval(3600)), yStart: .value("1", 44), yEnd: .value("2", 58))
.foregroundStyle(LinearGradient(colors: [.orange, .yellow], startPoint: .top, endPoint: .bottom))
.alignsMarkStylesWithPlotArea(false)
AreaMark(x: .value("Time", Date().addingTimeInterval(03600*2)), yStart: .value("1", 50), yEnd: .value("2", 90))
.foregroundStyle(LinearGradient(colors: [.green, .blue], startPoint: .top, endPoint: .bottom))
.alignsMarkStylesWithPlotArea(false)
}
}
}
Which produces this:
So here, all the different .foregroundStyle LinearGradients are being ignored AND the .alignsMarkStylesWithPlotArea(false) is also ignored - the amount of pink on the first mark is different to the second and third 🤷♂️
Has anyone encountered this. Are AreaMarks the correct choice or are they just not setup to create this type of data display. Thanks
Hey there,
Create Live activity in my project, after executing the creation method, back to the background, real-time activity UI is not displayed, but click Smart Island is effective,
now do not know where the problem appears?
Has anyone experienced this problem?
Thanks
In the development environment, if I disable and then enable the Network Connection permission to my app in the Setting on my device, my app is denied the network connection permission permanently. The error message is The Internet connection appears to be offline.
Please advise me what to do.
I've got a UIKit app with a collapsible trailing-edge child view controller, implemented sort of like UISplitViewController but it's got a bunch of custom behavior - moving to the bottom edge in portrait orientation, etc. It exposes a couple of different app functions via a UITabBar on the bottom edge on iOS.
When I run the app on visionOS, that tab bar transforms to a leading-edge ornament. This would be great, but that means it tries to overlap the trailing-edge content of its parent view controller, which isn't ideal.
Is there a way to get the tab bar to lay out on the trailling edge of the child view controller? Or can I create a custom ornament that has the same auto-expand behavior as the tab bar, where it shows a vertical column of icons that expands to show titles when you're gazing at it?