Construct and manage a graphical, event-driven user interface for your macOS app using AppKit.

AppKit Documentation

Post

Replies

Boosts

Views

Activity

Replicate Command-Q in SwiftUI
I'm building a menuBarExtra app for macOS, and I want to make a Quit menu available from a sub menu in the menuBarExtra, because the main window may be closed. When I try to add .keyboardShorcut("q") to the Button within Menu{}, the shortcut doesn't display, presumably because it's taken by the Quit menu item in the Application Menu. Any way to tell SwiftUI that they're doing the same thing so it will share the keyboard shortcut?
1
0
413
Sep ’23
drawRect broken in Xcode 15/Sonoma
I'm manually placing a subclass of NSView into the parent view using addSubview:positioned:relativeTo. The dirtyRect passed to drawRect: is wildly incorrect. Can folks attempt to reproduce and file bugs? This is awfully close to the release of Sonoma, and I feel like folks with bezier curves (or maybe other drawing code?) in their NSView subclasses are going to experience problems. To reproduce, place a view (I'm using an NSImageView) as a subview within a view. Then, create a subclass of NSView and draw a bezier curve in the drawRect method. Add an instance of this subclass as a subview of your original view. I'm offsetting the x value for clarity. When I build with Xcode 15 and run on Ventura or earlier, I get the correct result. Or, if I build with Xcode 14.3 and run on Sonoma I get the correct result. However, when I build in Xcode 15 and run on the RC build of Sonoma, I get a whacky result. I get something like (origin = (x = -264, y = -146), size = (width = 480, height = 388)) for the dirtyRect in the error case, while the rect is supposed to be (origin = (x = 0, y = 0), size = (width = 48, height = 48)) (I'm basing the frame of the new view on the original image.) Thanks!
4
1
1.3k
Sep ’23
transparent window can't click through in macos sonoma
i crate a fully transparent NSWindow like this: NSWindowStyleMask styleMask = NSBorderlessWindowMask | NSFullSizeContentViewWindowMask; NSWinod *window = [[BrowserNSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 500, 600) styleMask:styleMask backing:NSBackingStoreBuffered defer:NO]; [window setBackgroundColor:[NSColor clearColor]]; [window setOpaque:NO]; [window setHasShadow:NO]; NSCustomView *view = [[NSCustomView alloc] initWithFrame:NSMakeRect(0, 0, 500, 600) andBrowserWindow:this]; [view setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)]; [view setAutoresizesSubviews: true]; [window.contentView addSubview:view]; and override the NSView drawRect function: - (void)drawRect:(NSRect)rect { [[NSColor clearColor] set]; NSRectFill(rect); NSRectFillUsingOperation(rect, NSCompositingOperationSourceOver); } i call setNeedDisplay:YES to redraw the view. in macos sonoma, i found that when after multiple calls setNeedDisplay:YES, the transparent window can't click through. This feature run correctly in previous versions, like macos 13,
4
0
648
Sep ’23
How to drag an item using NSItemProviderWriting using async
Scenario: The following Swift code uses NSItemProviderWriting to load a file from some data source async (The code actually just uses a for loop to simulate the time it needs to load the file). It returns the file url then. This code is used for drag & drop behavior in a macOS app from an app to another app. As the other app does only support file URLs as drop types, I can't send over the data itself. class AnyFile: NSObject, NSItemProviderWriting { let url: URL init(url: URL) { self.url = url } static var writableTypeIdentifiersForItemProvider: [String] { return [UTType.fileURL.identifier] } func loadData(withTypeIdentifier typeIdentifier: String, forItemProviderCompletionHandler completionHandler: @escaping @Sendable (Data?, Error?) -> Void) -> Progress? { let count = 100000 let progress = Progress(totalUnitCount: Int64(count)) print("a") Task { print("b") for i in 0...100000 { progress.completedUnitCount = Int64(i) print(i) } print("c") completionHandler(url.dataRepresentation, nil) print("d") } print("e") return progress } } Problem: Drag & drop works, but when I start to drag the view (SwiftUI view using .onDrag), the view gets stuck as long as the loop is running. It is not clear to me why this happens as the loop us running inside a task. The console output also shows that progress is returned before the loop as finished. But still, it is stuck until the end of the loop. So the user experience is like not using async and the task. Log output (shortened) a e b 0 ... 100000 c d Actual Question: Why is this Swift code for dragging files not behaving asynchronously even though it uses Task, completionHandler, and async/await constructs? Alternatives tried: I'm not bound to NSItemProviderWriting in particular. I have tried other ways, like Transferable, .draggable(), and NSItemProvider.registerFileRepresentation. But either they won't return a URL, or do not allow async at all. I also tried AppKit instead of SwiftUI with similar issues.
2
0
669
Sep ’23
Drag URL from my app to another using a promise (in Swift)
Hi All, I have successfully implemented drag & drop of files from and to other apps on macOS successfully using different methods. Including NSFilePromiseProvider for example. There is one app however, that I use on a regular basis, that only support file urls as drop types. So I have to use public.file-url to drag & drop files there. The problem is that the file does not exist when dragging starts. That's why I would like to send a URL promise to the app, instead of a file promise. I can't create the file beforehand because then I would need to create hundreds of large files which will just take up space. So whenever I drag an item from my app to the other app, then the file shall be created and the url shall be sent to that app to be opened. But as the other app only checks the pasteboard for urls without handling promises, this is not working. I do have their code available, but can't change the code. Question: Is there a way in Swift on macOS to drag and drop a an item to another app so that upon mouse up on the other app some async tasks is executed and at the end the other app receives the URL as a result of the async task?
0
1
497
Sep ’23
Sonoma beta - app's dialog buttons grayed out - NSTextField wont allow edits
I have a macOS app built with Xcode 14.1 that works perfectly on Catalina through Ventura. Works on Apple Silicon and Intel machines. When it runs under Sonoma (9/12/23 release and earlier) controls in dialog boxes no longer highlight blue but can be pressed. Text fields can not be edited. Radio buttons can be selected but they all stay gray. This happens to not only the app's custom dialogs but Apple's NSSavePanel() and others. It happens in Sonoma with Apple Silicon or Intel versions under Rosetta. An earlier version built with Xcode 13 works just fine (except WebKit has issues). I made a small app that just tries to do a NSAlert() and it works correctly in Sonoma built with Xcode 14.1. I have not seen any other apps do this under Sonoma. In order to rule out some sort of byzantine focus problem with the view controllers in the app, I removed everything from applicationDidFinishLaunching() and put an NSAlert() in there. Same thing, the default button comes out gray and not blue. I've tried bumping up the minimum release to macOS 12.x. No luck. It's nothing to do with Appearance, I have removed all of that code. Deleted all the prefs. I've rebuilt the project file in Xcode 14.1 from scratch, same thing - no blue focus buttons. I've tried building it with the latest versions of Xcode and the same problem. Any ideas what in the world can cause this?
2
0
734
Sep ’23
F2 key press event for macOS
Why kVK_F2 is not equivalent to constant NSF2FunctionKey for F2 key press event, What is equivalent constant of kVK_F2, since carbon framework is deprecated. When I printed the keyCode, The [Event keyCode] against NSF2FunctionKey is 63237(0xF705) whereas for kVK_F2, it prints is 120 which is 0x78. 0x78 seems to be the standard keyboard value for F2 key. Sample code : //@property (nonatomic, strong) id eventMonitor; NSEvent* (^handler)(NSEvent*) = ^(NSEvent *theEvent) { NSEvent *result = theEvent; NSUInteger flags = [theEvent modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask; if ((flags & NSEventModifierFlagFunction) && (flags & NSEventModifierFlagCommand) && ([theEvent keyCode] == NSF2FunctionKey)) { NSLog(@"Command + F2 key pressed."); } return result; }; _eventMonitor = [NSEvent addLocalMonitorForEventsMatchingMask:(NSEventModifierFlagFunction | NSEventMaskKeyDown) handler:handler];
1
0
441
Sep ’23
No console output when project Is built and action is triggered
This is my first Xcode application, I'm building a simple MacOS chatbox application that uses python scrips, PythonKit, and swift to handle serverSide operations and accessing open's api and is meant to trigger these two methods I have in a function called executeProcess() that is meant to invoke other functions in another file when a question is types in the text field and the 'enter' key on a keyboard is hit via the onCommit function, however im getting no console output. here is my relevant code from my contentView.swift file I can provide more code from other files if needed.(I will just be showing the non SwiftUI specific code here) import Cocoa import Foundation import PythonKit import AppKit protocol runPyRunnable { func runPyServer(completion: @escaping(String) -> Void) func sendRequest(userInput: String, completion: @escaping(String) -> Void) } func runPyServer() -> String { print("server run") return "server run" } struct MyPyTypePlaceHolder: runPyRunnable { func runPyServer(completion: @escaping(String) -> Void) { } func sendRequest(userInput: String, completion: @escaping (String) -> Void) { } } struct ContentView: View { var ViewController: runPyRunnable? = MyPyTypePlaceHolder() as? runPyRunnable @State private var text: String = "" @State private var filePath = "" @State private var inputText = "" var body: some View { makeContent() .onAppear{ NSApp.mainWindow?.makeFirstResponder(NSApp.mainWindow?.contentView) } } ZStack { Spacer() TextField("Ask Mac GPT...", text: $inputText, onCommit: { executeProcess(withInput: inputText) { response in print(response) } }) .font(Font.custom("Futura", size: 17.4)) .padding(.horizontal, 25) .padding(.vertical, 15) .background(Color.white) .cornerRadius(29) .overlay( RoundedRectangle(cornerRadius: 27.9).stroke(Color.gray, lineWidth: 1.0) ) .offset(y: -200) .padding(.horizontal, 35) } } func executeProcess(withInput input: String, completion: @escaping (String) -> Void ) { DispatchQueue.global().async { DispatchQueue.main.async { guard !input.isEmpty else { print("TextField is empty, enter input in the text field") return } if let myPyTypeInstance = self.ViewController { myPyTypeInstance.runPyServer { responseFromRunPyServer in myPyTypeInstance.sendRequest(userInput: input) { responseFromSendRequest in completion(responseFromSendRequest) } } } } } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } } }
0
0
436
Sep ’23
Multiple NSMenu issues in Sonoma
Sonoma beta release notes mention that NSMenu was rewritten from scratch using AppKit, however, it seems like a lot of behavior was removed along the way which breaks applications. I've filed several requests using Feedback Assistant, but none of them were fixed in the 3 following betas. FB12867496: NSMenu no longer receives keyboard events from GetEventDispatcherTarget (there is a workaround) FB12867573: NSMenuItem custom view window is nil FB12887219 : NSMenu performSelector highlightItem doesn't highlight menu item FB12938907: NSMenu not properly updated when adding/removing NSMenuItem I wonder if anyone else has experienced similar problems and can share workarounds for them:
6
2
1k
Aug ’23
NSSpellServer example
Is there any modern example of how to create a sandboxed application that provides a spelling service to other macOS applications? The example out there are all in Objective-C and doesn't work when run in modern Xcode.
2
1
310
Aug ’23
Using NSApplicationActivationPolicyAccessory does not hide the icon in dock
I have an application which will launches another application as a child process. The child application does not need the dock icon, we use [NSApp setActivationPolicy: NSApplicationActivationPolicyAccessory]; to achieve it. However, I have discovered that the dock icon cannot be perfectly hidden. The number of recently used apps that aren’t already in dock(not choose keep in dock) less than three: The icon of the child application remains in the dock without being hidden. The number of recently used apps that aren’t already in dock(not choose keep in dock) more than three: The icon of the child application appears a few milliseconds. Even though add LSUIElement key in the Info.plist can work, we are seeking a programmatic modification.
3
0
714
Aug ’23
Converting macOS system colors to iOS system colors in NSAttributedString
When syncing an NSAttributedString between devices, it seems that macOS system colors are decoded as "UIExtendedGrayColorSpace" black color on iOS. For example, if I have text on the Mac and chose systemColorRed, this is converted to UIExtendedGrayColorSpace black on iOS. I would like to convert the macOS system red (for example) to the iOS system red, but I'm not sure the best way to do this. My question is: has anyone discovered an efficient and clean way to convert macOS system colors to iOS system colors when syncing between devices? I have seen that the system colors on both devices have a consistent hex value when reading the color components. A possible solution would be to save the hex value of the colors in the attributed string. We could then enumerate the hex values and exchange the attributed string foreground color for the appropriate system color of whatever device is being used. I would greatly appreciate thoughts regarding this. Thank you everyone!
2
0
515
Aug ’23
Determinate spinning NSProgressIndicator doesn't adapt to frame size and gets cut off
The following code should produce 6 spinning progress indicators of varying sizes: 3 indeterminate and 3 determinate ones. The first two of the 3 determinate ones are either entirely or partially cut off, which doesn't happen with the indeterminate ones. What's the problem? var progress = NSProgressIndicator(frame: CGRect(x: 0, y: 0, width: 16, height: 16)) progress.style = .spinning view.addSubview(progress) progress = NSProgressIndicator(frame: CGRect(x: 50, y: 0, width: 24, height: 24)) progress.style = .spinning view.addSubview(progress) progress = NSProgressIndicator(frame: CGRect(x: 100, y: 0, width: 32, height: 32)) progress.style = .spinning view.addSubview(progress) progress = NSProgressIndicator(frame: CGRect(x: 150, y: 0, width: 16, height: 16)) progress.style = .spinning progress.isIndeterminate = false progress.doubleValue = 50 progress.maxValue = 100 view.addSubview(progress) progress = NSProgressIndicator(frame: CGRect(x: 200, y: 0, width: 24, height: 24)) progress.style = .spinning progress.isIndeterminate = false progress.doubleValue = 50 progress.maxValue = 100 view.addSubview(progress) progress = NSProgressIndicator(frame: CGRect(x: 250, y: 0, width: 32, height: 32)) progress.style = .spinning progress.isIndeterminate = false progress.doubleValue = 50 progress.maxValue = 100 view.addSubview(progress)
1
0
422
Aug ’23
If NSImage is not Sendable, how should async functions return images?
I saw that the macOS 14 SDK added this: @available(*, unavailable) extension NSImage : @unchecked Sendable { } Do I interpret this correctly to mean that NSImage is not Sendable and this extension’s sole purpose is to document this fact? I understand why NSImage isn’t safe to use from multiple threads at the same time. But what is the best way to pass around images in async contexts, then? CGImage is Sendable and is a fine substitute for pixel-based images, but what about PDFs? Is the only feasible way to create a PDF-based NSImage by doing everything on the main thread? (Except maybe load the file into a Data?) On the other hand, UIImage is Sendable, but I suppose that is because it uses a CGImage under the hood?
3
4
1.4k
Aug ’23
c++ NS::Application please help me aim at a total loss
hi all, so I have followed this on how to set up a metal c++ project in Xcode: https://developer.apple.com/metal/cpp/ i have also downloaded the learn apple cpp examples: https://developer.apple.com/metal/LearnMetalCPP.zip To get to a point of basic fundamental knowledge of how it works I've tried to go through the process of creating a basic window in the same way that its done in these examples, I can't how ever not get Xcode to recognize evin the basic NS::Application component. Do anyone know what I am doing wrong, and also is there a source somewhere with some kind of basic examples online. I do not have to be c++ Ive added a screenshot of Xcode not recognizing NS::Application evinthrough I have followed project guide at the top. thank you so much for looking at this :)
1
0
594
Aug ’23
Change MapKit region update animation duration on macOS
I'm writing a multiplatform app that uses MapKit with custom tiles via MKTileOverlay. The map should have buttons for zooming in and out. Those buttons set the region of the MKMapView with animation parameter. I want to make this animation faster. While good for generic change of a region, it feels too slow when changing the region for the zooming purposes. In general, I'm working with SwiftUI. But because MKTileOverlay is not available there, the MKMapView is being accessed via the UIViewRepresentable and NSViewRepresentable respectively. On iOS, to make animation faster (reduce animation time), I'm using UIView.animate(withDuration: 0.2) { mapView.setRegion(region, animated: true) } and it achieves the goal. On macOS, I tried: NSAnimationContext.runAnimationGroup { context in context.duration = 0.2 mapView.setRegion(region, animated: true) } and: CATransaction.begin() CATransaction.setAnimationDuration(0.2) mapView.setRegion(region, animated: true) CATransaction.commit() but without success. The default animation duration is not overridden. I appreciate any input you could give me. Alexey
0
0
751
Aug ’23
Bookmark Creation With Security Scope Fails in Xcode Cloud
I have an macOS app, where the user can open/drag a folder so that the contents can be listed and used. The app saves the bookmark data for these folders and restores them the next time the app runs. This works perfect on the development machines and on thousands of users' Macs. Recently I added UI tests which perform a couple if happy path tests and they are helping a lot. One of the tests adds a folder and tries to use an image which is in the folder. The folder is copied from the test bundle to the Desktop at the beginning of the test. This works both locally (on my Mac) and on two CI "servers" (latest macOS, Xcode Server). At the moment I try to migrate to Xcode Cloud. Unit tests run fine (after disabling the Hardened Runtime). However, I do not get the UI tests to succeed. They run and add the folder, however, the URL's bookmark data creation fails. I tried to track the differences during the build and found Xcode Cloud builds always being adhoc-signed. Running the UI tests locally but signing the app (and the tests) adhoc too does not result in the same problem. Problem in short: user selects folder (using NSOpenPanel or Drag'n'Drop) url.bookmarkData() works locally and in Xcode Cloud url.bookmarkData(options: [.withSecurityScope]) only works locally but not in Xcode Cloud This is easily reproducible with a very simple project which I can hand-out if needed. Anybody a hint or idea? Since those folders are essential for the app, not solving this would render Xcode Cloud completely useless for me. Thanks! Daniel
1
0
642
Aug ’23
CARemoteLayer Refusing To Draw Hosted Contents
I'm exploring using the CARemoteLayerClient/Server API to render a layer from another process as is described in the docs, but can't seem to get a very simple example to work. Here's a very simple example of what I'd expect to work: // Run with `swift file.swift` import AppKit let app = NSApplication.shared class AppDelegate: NSObject, NSApplicationDelegate { let window = NSWindow( contentRect: NSMakeRect(200, 200, 400, 200), styleMask: [.titled, .closable, .miniaturizable, .resizable], backing: .buffered, defer: false, screen: nil ) func applicationDidFinishLaunching(_ notification: Notification) { window.makeKeyAndOrderFront(nil) let view = NSView() view.frame = NSRect(x: 0, y: 0, width: 150, height: 150) view.layerUsesCoreImageFilters = true view.wantsLayer = true let server = CARemoteLayerServer.shared() let client = CARemoteLayerClient(serverPort: server.serverPort) print(client.clientId) client.layer = CALayer() client.layer?.backgroundColor = NSColor.red.cgColor // Expect red rectangle client.layer?.bounds = CGRect(x: 0, y: 0, width: 100, height: 100) let serverLayer = CALayer(remoteClientId: client.clientId) serverLayer.bounds = CGRect(x: 0, y: 0, width: 100, height: 100) view.layer?.addSublayer(serverLayer) view.layer?.backgroundColor = NSColor.blue.cgColor // Background blue to confirm parent layer exists window.contentView?.addSubview(view) } } let delegate = AppDelegate() app.delegate = delegate app.run() In this example I'd expect there to be a red rectangle appearing as the remote layer. If I inspect the server's layer hierarchy I see the correct CALayerHost with the correct client ID being created, but it doesn't display the correct contents being set from the client side. After investigating this thread: https://bugs.chromium.org/p/chromium/issues/detail?id=312462 and some demo projects, I've found that the workarounds previously found to make this API work no longer seem to work on my machine (M1 Pro, Ventura). Am I missing something glaringly obvious in my simple implementation or is this a bug?
0
0
592
Jul ’23