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.
Explore the various UI frameworks available for building app interfaces. Discuss the use cases for different frameworks, share best practices, and get help with specific framework-related questions.
Post
Replies
Boosts
Views
Activity
I'm looking at a case where a handler for NSWindowDidBecomeMain gets the NSWindow* from the notification object and verifies that window.isVisible == YES, window.windowNumber > 0 and window.screen != nil. However, window.windowNumber is missing from the array [NSWindow windowNumbersWithOptions: NSWindowNumberListAllSpaces] and from CGWindowListCopyWindowInfo( kCGWindowListOptionOnScreenOnly, kCGNullWindowID ), how can that be?
The window number is in the array returned by CGWindowListCopyWindowInfo( kCGWindowListOptionAll, kCGNullWindowID ).
I'm seeing this issue in macOS 15, maybe 14, but not 13.
Hi,
WWDC24 videos have a lot of references to an "Image Playground" API, and the "What's New in AppKit" session even shows it in action, with a "ImagePlaygroundViewController". However, there doesn't seem to be any access to the new API, even with Xcode 16.2 beta. Am I missing something, or is that 'coming later'?
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 am making a swift app supporting multi language ,showing proper language ui according user's phone setting language, I want to launch different screen (showing different image, boot-en.jpg, boot-ja.jpg) according language,i created two LaunchScreen files ,LaunchScreen-en.storyboard and LaunchScreen-ja.storyboard and localize them ,and add a different UIImage to them,
then create two InfoPlist.strings file with congfiging
."UILaunchStoryboardName" = "LaunchScreen_en"; //
"UILaunchStoryboardName" = "LaunchScreen_ja";//
and then **config info.plist ** with
UILaunchStoryboardName
LaunchScreen
above all steps ,build and run,hope to see launch screen showing boot-ja.jpg when phone's language is Japanese, showing boot-en.jpg when phone's language is English, but it shows black screen, how to fix this problem, thank you.
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?
0 CoreFoundation 0x0000000183f687cc ___exceptionPreprocess + 164
1 libobjc.A.dylib 0x000000018123b2e4 _objc_exception_throw + 88
2 CoreFoundation 0x000000018406e5f0 +[NSObject(NSObject) doesNotRecognizeSelector:] + 0
3 UIKitCore 0x0000000186849a48 -[UIButtonLegacyVisualProvider _newLabelWithFrame:] + 60
4 UIKitCore 0x00000001867652b0 -[UIButtonLegacyVisualProvider _setupTitleViewRequestingLayout:] + 84
5 UIKitCore 0x0000000186763ba4 -[UIButtonLegacyVisualProvider titleViewCreateIfNeeded:] + 44
6 UIKitCore 0x00000001867d3f74 -[UIButton titleLabel] + 36
Hello bro, in IOS 18 our team find issue ,We created a button like this:
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.titleLabel.font = [UIFont fontWithName:paramFontName size: fontSize];
Please tell me whether we need to set button frame before we call button.titleLabe?
As of macOS Sequoia 15.1 (and probably earlier), in System Settings under Accessibility -> Display, there's a Text Size option that looks an awful lot like Dynamic Type on iOS:
I have an iOS app with robust support for Dynamic Type that I've brought to the Mac via Catalyst. Is there any way for me to opt this app into supporting this setting, maybe with some Info.plist key?
Calendar's Info.plist has a CTIgnoreUserFonts value set to true, but the Info.plist for Notes has no such value.
I would like to implement the same kind of behavior as the Dropoverapp application, specifically being able to perform a specific action when files are dragged (such as opening a window, for example).
I have written the code below to capture the mouse coordinates, drag, drop, and click globally. However, I don't know how to determine the nature of what is being dropped. Do you have any ideas on how to detect the nature of what is being dragged outside the application's scope?
Here is my current code:
import SwiftUI
import CoreGraphics
struct ContentView: View {
@State private var mouseX: CGFloat = 0.0
@State private var mouseY: CGFloat = 0.0
@State private var isClicked: Bool = false
@State private var isDragging: Bool = false
private var mouseTracker = MouseTracker.shared
var body: some View {
VStack {
Text("Mouse coordinates: \(mouseX, specifier: "%.2f"), \(mouseY, specifier: "%.2f")")
.padding()
Text(isClicked ? "Mouse is clicked" : "Mouse is not clicked")
.padding()
Text(isDragging ? "Mouse is dragging" : "Mouse is not dragging")
.padding()
}
.frame(width: 400, height: 200)
.onAppear {
mouseTracker.startTracking { newMouseX, newMouseY, newIsClicked, newIsDragging in
self.mouseX = newMouseX
self.mouseY = newMouseY
self.isClicked = newIsClicked
self.isDragging = newIsDragging
}
}
}
}
class MouseTracker {
static let shared = MouseTracker()
private var eventTap: CFMachPort?
private var runLoopSource: CFRunLoopSource?
private var isClicked: Bool = false
private var isDragging: Bool = false
private var callback: ((CGFloat, CGFloat, Bool, Bool) -> Void)?
func startTracking(callback: @escaping (CGFloat, CGFloat, Bool, Bool) -> Void) {
self.callback = callback
let mask: CGEventMask = (1 << CGEventType.mouseMoved.rawValue) |
(1 << CGEventType.leftMouseDown.rawValue) |
(1 << CGEventType.leftMouseUp.rawValue) |
(1 << CGEventType.leftMouseDragged.rawValue)
// Pass 'self' via 'userInfo'
let selfPointer = UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque())
guard let eventTap = CGEvent.tapCreate(
tap: .cghidEventTap,
place: .headInsertEventTap,
options: .defaultTap,
eventsOfInterest: mask,
callback: MouseTracker.mouseEventCallback,
userInfo: selfPointer
) else {
print("Failed to create event tap")
return
}
self.eventTap = eventTap
runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0)
CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, .commonModes)
CGEvent.tapEnable(tap: eventTap, enable: true)
}
// Static callback function
private static let mouseEventCallback: CGEventTapCallBack = { _, eventType, event, userInfo in
guard let userInfo = userInfo else {
return Unmanaged.passUnretained(event)
}
// Retrieve the instance of MouseTracker from userInfo
let tracker = Unmanaged<MouseTracker>.fromOpaque(userInfo).takeUnretainedValue()
let location = NSEvent.mouseLocation
// Update the click and drag state
switch eventType {
case .leftMouseDown:
tracker.isClicked = true
tracker.isDragging = false
case .leftMouseUp:
tracker.isClicked = false
tracker.isDragging = false
case .leftMouseDragged:
tracker.isDragging = true
default:
break
}
// Call the callback on the main thread
DispatchQueue.main.async {
tracker.callback?(location.x, location.y, tracker.isClicked, tracker.isDragging)
}
return Unmanaged.passUnretained(event)
}
}
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?
So I was trying to use an NSArrayController to bind the contents of a property , first I tried using NSDictionary and it worked great, here's what I did:
@interface ViewController : NSViewController
@property IBOutlet ArrayController * tableCities;
@end
...
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSString* filePath = @"/tmp/city_test.jpeg";
NSDictionary *obj = @{@"image": [[NSImage alloc] initByReferencingFile:filePath],
@"name": @"NYC",
@"filePath": filePath};
NSDictionary *obj2 = @{@"image": [[NSImage alloc] initByReferencingFile:filePath],
@"name": @"Chicago",
@"filePath": filePath};
NSDictionary *obj3 = @{@"image": [[NSImage alloc] initByReferencingFile:filePath],
@"name": @"Little Rock",
@"filePath": filePath};
[_tableCities addObjects:@[obj, obj2, obj3]];
}
@end
Now for an NSPopUpButton, binding the Controller Key to the ArrayController and the ModelKeyPath to "name" works perfectly and the popupbutton will show the cities as I expected.
But now, instead of using an NSDictionary I wanted to use a custom class for these cities along with an NSMutableArray which holds the objects of this custom class. I'm having some trouble going about this.
We have to draw polygons inside a MKMapView based on coordinates retrieved from external source.
It seems that MapKit does not behave correctly where polygons have single-vertex self-intersection.
Here it's a simple point list example (every element is a pair of latitude and longitude values):
[(0, 0), (20, 0), (10, 10), (20, 20), (0, 20), (10, 10), (0, 0)]
The next image shows the rendering issue.
But if the list is slightly changed in this way
[(0, 0), (20, 0), (10, 10), (20, 20), (0, 20), (15, 10), (0, 0)]
the issue disappears. The next image shows it.
So it's not a self-intersection and self-tangency problem, but we think single-vertex self-intersection is a buggy edge case for MapKit.
Right now we fixed this problem by finding the duplicated coordinates and applying a small offset (1e-8) to one of them, but it's a temporary solution and adds rendering delay.
The problem is not due to iOS versions, since iOS 17 and 18 have the same issue. Also it happens on simulators and real devices.
Here is the playground example, based mostly on the "Map Playground" template Xcode offers. If you run it without modifying it, the playground shows the "bugged" polygon. If you use notBugPoints instead of the default bugPoints for the polygon, the playground shows the "not-bugged" polygon.
import MapKit
import PlaygroundSupport
// Create an MKMapViewDelegate to provide a renderer for our overlay
class MapViewDelegate: NSObject, MKMapViewDelegate {
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
if let overlay = overlay as? MKPolygon {
let polygonRenderer = MKPolygonRenderer(overlay: overlay)
polygonRenderer.fillColor = .red
return polygonRenderer
}
return MKOverlayRenderer(overlay: overlay)
}
}
// Create a strong reference to a delegate
let delegate = MapViewDelegate()
// Create an MKMapView
let mapView = MKMapView(frame: CGRect(x: 0, y: 0, width: 800, height: 800))
mapView.delegate = delegate
// Configure The Map elevation and emphasis style
let configuration = MKStandardMapConfiguration(elevationStyle: .realistic, emphasisStyle: .default)
mapView.preferredConfiguration = configuration
// Create an overlay
let bugPoints = [
MKMapPoint(CLLocationCoordinate2DMake(0, 0)),
MKMapPoint(CLLocationCoordinate2DMake(20, 0)),
MKMapPoint(CLLocationCoordinate2DMake(10, 10)),
MKMapPoint(CLLocationCoordinate2DMake(20, 20)),
MKMapPoint(CLLocationCoordinate2DMake(0, 20)),
MKMapPoint(CLLocationCoordinate2DMake(10, 10)),
MKMapPoint(CLLocationCoordinate2DMake(0, 0))
]
let notBugPoints = [
MKMapPoint(CLLocationCoordinate2DMake(0, 0)),
MKMapPoint(CLLocationCoordinate2DMake(20, 0)),
MKMapPoint(CLLocationCoordinate2DMake(10, 10)),
MKMapPoint(CLLocationCoordinate2DMake(20, 20)),
MKMapPoint(CLLocationCoordinate2DMake(0, 20)),
MKMapPoint(CLLocationCoordinate2DMake(15, 10)),
MKMapPoint(CLLocationCoordinate2DMake(0, 0))
]
let polygon = MKPolygon(points: bugPoints, count: notBugPoints.count)
mapView.addOverlay(polygon)
// Frame our annotation and overlay
mapView.camera = MKMapCamera(lookingAtCenter: CLLocationCoordinate2DMake(10, 10), fromDistance: 5000000, pitch: 0, heading: 0)
// Add the created mapView to our Playground Live View
PlaygroundPage.current.liveView = mapView
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.
Hi there!
I’m experiencing an issue while loading images with Kingfisher in a LazyVStack containing around 500 items. When I use low-resolution images, everything loads correctly. However, when I switch to higher quality images, only some of them load successfully, while the rest remain stuck in a loading state, and I see the following log:
nw_connection_add_timestamp_locked_on_nw_queue [C1] Hit maximum timestamp count, will start dropping events
Interestingly, if I switch from WiFi to 5G, the images start loading again, but the loading stalls once more after a few additional images.
Could you help me understand why this happens with high-quality images and how to resolve it?
Thank you!
I have an app with looks at the @Environment(\.horizontalSizeClass) variable and it's mate vertical. On the iPhone 16 sim, if I'm in portrait orientation, It says my vertical class is .regular and horizontal is .compact.
If I rotate to landscape, it says vertical is now compact, and horizontal is still compact. That seems inconsistent.
I'm trying to wrap my head around designing for size class, how am I supposed to think about this?
What I want is two areas of the screen: The main area, which shows a graphic, and a much smaller control and data area, which has a button or two and a very narrow text display, which in my current app counts from 1 to 4. The button area
These areas ought never move from where they are, but their contents ought to rotate in place to reflect the orientation. If portrait, the button area is on the bottom, if landscapeLeft, the button are is to the right, if landscapeRight, the button area is to the left.
This currently sort of works if I test for the max of height or width from a Geometry Reader, but it doesn't handle landscapeRight or portraitUpsideDown correctly.
I have a Catalyst app that supports multiple scenes / windows. It has one "main" window type and lots of other secondary windows that can be opened. I'm using the system window restoration functionality via NSQuitAlwaysKeepsWindows to restore windows with their user activity data after the app is quit and restarted.
Normally, this works great. If I open my app, change the size and position of my window, quit, and reopen it, the window size and position comes back as expected. But if I close the window using the red stoplight button and then click the app icon to bring it back, it comes back at the default position and size.
This isn't how other system apps work - if I close the system Calendar app with the stoplight button, it comes back at the same size and position. How do I get this behavior with my Catalyst app? Is there some identifier property I need to set somewhere? I don't see such a property on UISceneConfiguration.
If it matters, I'm using the configurationForConnectingSceneSession method to configure my windows when they open, instead of setting it up in the Info.plist.
Hi all,
Is this allowed:
environment(\.container, MyContainer() as Any)
While injecting Model container into the environment we use Type . Is there any universal injection type that can inject container as set of any types rather than array similar to navigationPath() type-eraser ?
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?