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

Posts under AppKit tag

169 Posts
Sort by:

Post

Replies

Boosts

Views

Activity

trashItem, recycle, but no put back option...it depends
Hi all, I use the FileManager trashIitem function to put a file in the trash. If it is only one file, then the option to put it back is available. If, however, several files are deleted, the option to put it back is only available for the first deleted file. All others cannot be put back. The problem has been known for at least 10 years. See Put back only works for the first file. NSWorkspace recycle has the same problem. It seems to be due to .DS_Store in the trash. The files that are in the trash are stored there. This may also lead you to believe that the trashItem function is working properly because the deleted files are still in the .DS_Store file. If I call trashItem or recycle several times and wait 2 seconds between calls, then the option to put it back is available for all of them. That obviously can't be the solution. Waiting less than 2 seconds only offers to put the first file back. So trashItem and recycle are the same as remove, with the difference that you can look at the files in the trash can again, but not put them back. Are there other ways? The Finder can also delete multiple files and put them all back.
2
0
353
Feb ’25
NSAlert button background/contrast
If I use NSAlert the buttons look like this: The Cancel button has a gray background. We got complaints about the bad contrast and people pointed out that the alerts from System Settings look like this: Here the Cancel button has a white background. Unfortunately I did not find out how to make the buttons in my own alerts look like those in System Settings. Setting the button's bezel color to white did not work. Any help would be highly appreciated. Thanks. Best regards, Marc
4
0
497
Feb ’25
On macOS SwiftUI.TimelineView() inside NSViewController is causing AutoLayout recalculations
I have a complex app that requires the main SwiftUI view of the app to be embedded inside an NSHostingView which is a subview of an NSViewController's view. Then this NSViewController is wrapped using NSViewControllerRepresentable to be presented using SwiftUI's Window. And if I have a TimelineView inside my SwiftUI view hierarchy, it causes constant recalculation of the layout. Here's a simplified demo code: @main struct DogApp: App { private let dogViewController = DogViewController() var body: some Scene { Window("Dog", id: "main") { DogViewControllerUI() } } } private struct DogViewControllerUI: NSViewControllerRepresentable { let dogViewController = DogViewController () func makeNSViewController(context: Context) -> NSViewController { dogViewController } func updateNSViewController(_ nsViewController: NSViewController, context: Context) {} func sizeThatFits(_ proposal: ProposedViewSize, nsViewController: NSViewController, context: Context) -> CGSize? { debugPrint("sizeThatFits", proposal) return nil } } public class DogViewController: NSViewController { public override func viewDidLoad() { super.viewDidLoad() let mainView = MainView() let hostingView = NSHostingView(rootView: mainView) view.addSubview(hostingView) hostingView.translatesAutoresizingMaskIntoConstraints = false hostingView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true hostingView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true hostingView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true hostingView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true } } struct MainView: View { var body: some View { VStack { TimelineView(.animation) { _ in Color.random .frame(width: 100, height: 100) } } } } extension Color { static var random: Color { Color( red: .random(in: 0...1), green: .random(in: 0...1), blue: .random(in: 0...1) ) } } When running it's printing out this repeatedly (multiple times a second). "sizeThatFits" SwiftUI.ProposedViewSize(width: Optional(559.0), height: Optional(528.0)) "sizeThatFits" SwiftUI.ProposedViewSize(width: Optional(0.0), height: Optional(0.0)) "sizeThatFits" SwiftUI.ProposedViewSize(width: Optional(559.0), height: Optional(528.0)) "sizeThatFits" SwiftUI.ProposedViewSize(width: Optional(0.0), height: Optional(0.0)) "sizeThatFits" SwiftUI.ProposedViewSize(width: Optional(559.0), height: Optional(528.0)) "sizeThatFits" SwiftUI.ProposedViewSize(width: Optional(0.0), height: Optional(0.0)) "sizeThatFits" SwiftUI.ProposedViewSize(width: Optional(559.0), height: Optional(528.0)) If I run an equivalent code for an iPad, it only prints twice. If I comment out TimelineView on macOS, then it only prints out the above logs when resizing the app window. The main reason this is an issue is that it's clearly causing dramatic degradation in performance. I was told to submit a bug report after I submitted TSI so a SwiftUI engineer could investigate it. Case-ID: 7461887. FB13810482. This was back in May but I received no response. LLMs are no help, and I've experimented with all sorts of workarounds. My last hope is this forum, maybe someone has an idea of what might be going on and why the recalculation is happening constantly on macOS.
1
0
327
Feb ’25
AppKit document project reports an error when opening a new document in Swift 6
In an AppKit document-based project created by Xcode, setting canConcurrentlyReadDocuments to true allows new documents to open normally in Swift 5, but switching to Swift 6 causes an error. Judging from the error message, it seems to be a threading issue, but I’m not sure how to adjust the code to support the Swift 6 environment. The project is the most basic code from an Xcode-created document-based project without any modifications, except for changing the Swift version to 6 and setting canConcurrentlyReadDocuments to true. Source code: https://drive.google.com/file/d/1ryb2TaU6IX884q0h5joJqqZwSX95Q335/view?usp=sharing AppDelegate.swift import Cocoa @main class AppDelegate: NSObject, NSApplicationDelegate { func applicationDidFinishLaunching(_ aNotification: Notification) { // Insert code here to initialize your application } func applicationWillTerminate(_ aNotification: Notification) { // Insert code here to tear down your application } func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { return true } } Document.swift import Cocoa class Document: NSDocument { override init() { super.init() // Add your subclass-specific initialization here. } override class var autosavesInPlace: Bool { return true } override class func canConcurrentlyReadDocuments(ofType typeName: String) -> Bool { true } override func canAsynchronouslyWrite(to url: URL, ofType typeName: String, for saveOperation: NSDocument.SaveOperationType) -> Bool { true } override func makeWindowControllers() { // Returns the Storyboard that contains your Document window. let storyboard = NSStoryboard(name: NSStoryboard.Name("Main"), bundle: nil) let windowController = storyboard.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier("Document Window Controller")) as! NSWindowController self.addWindowController(windowController) } override func data(ofType typeName: String) throws -> Data { // Insert code here to write your document to data of the specified type, throwing an error in case of failure. // Alternatively, you could remove this method and override fileWrapper(ofType:), write(to:ofType:), or write(to:ofType:for:originalContentsURL:) instead. // throw NSError(domain: NSOSStatusErrorDomain, code: unimpErr, userInfo: nil) return Data() } override func read(from data: Data, ofType typeName: String) throws { // Insert code here to read your document from the given data of the specified type, throwing an error in case of failure. // Alternatively, you could remove this method and override read(from:ofType:) instead. // If you do, you should also override isEntireFileLoaded to return false if the contents are lazily loaded. // throw NSError(domain: NSOSStatusErrorDomain, code: unimpErr, userInfo: nil) } } ViewController.swift import Cocoa class ViewController: NSViewController { override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. } override var representedObject: Any? { didSet { // Update the view, if already loaded. } } }
1
1
526
Mar ’25
Screen recording detect in MACOs Apps
Hi, My MACOS app has sensitive content and dont want user to take screenshot or to record the screen. I tries window.sharingType=none. With this user can still record the screen. I know that user can record with external device. But we dont want him to record using screen capture. Can you please tell me how to detect when screen recording is active in MACOs apps? or how to prevent screen recording in MACOs apps. Thanks
0
1
352
Feb ’25
Do not have permission to open the file
In macOS, I am encountering an issue where the system API fails to grant permission to open a file despite enabling the necessary Read/Write permissions within the SandBox. Could you please elucidate the reasons behind this behavior? Thanks! func finderOpenFileSystem(at path: String) { let fileURL = URL(fileURLWithPath: path) guard FileManager.default.fileExists(atPath: path) else { print("Error: File does not exist at path: \(path)") return } let success = NSWorkspace.shared.open(fileURL) if success { print("File opened successfully: \(fileURL)") } else { print("Error: Failed to open file: \(fileURL)") } }
1
0
436
Jan ’25
NSScrollView scrolling hitch
When scrolling a basic NSScrollView there seems to be a sudden jump after each flick. Scrolling does not appear smooth and is disorientating. A scroll jump seems to happen directly after letting go of a scroll flick using a trackpad/mouse. Right at that moment the scroll turns into a momentum scroll, slowly decreasing the speed. But the first frame after the gesture the content jumps forward, more than what is expected. Observations: Counterintuitively, scrolling appears to be smoother when disabling NSScrollView.isCompatibleWithResponsiveScrolling. If disabled using a custom NSScrollView subclass there is no large jump anymore. Scrolling also appears to be smoother using a SwiftUI ScrollView. I assume that has the same behaviour as a disabled isCompatibleWithResponsiveScrolling Ironically a WKWebView scrolls much smoother. No sudden jump is observable. It also seems to scroll with faster acceleration, but the individual frames do appear smoother. Why is this better than a native NSScrollView? Elastic scrolling at the bounds of the scroll view also appears much smoother for WKWebViews. When pulling to refresh there is a jump for NSScrollView/SwiftUI, but not for WKWebView. When using an NSScrollView with isCompatibleWithResponsiveScrolling disabled, scrolling appears just as smooth as WKWebView on macOS 13 Ventura and below. On macOS 14 Sonoma scrolling behaviour is suddenly different. Please see a sample project with 4 different scroll views side by side: https://github.com/floorish/ScrollTest Screen recordings show the sudden jumps when scrolling and when elastic scrolling. Tested on Intel & Arm Macs, macOS 11 Big Sur through 15 Sequoia, built with Xcode 16. Should isCompatibleWithResponsiveScrolling be disabled on Sonoma+? Are there any drawbacks? There is also no overdraw anymore since Monterey, as described in https://developer.apple.com/library/archive/releasenotes/AppKit/RN-AppKitOlderNotes/#10_9Scrolling Even with responsive scrolling disabled, why is WKWebView scrolling much smoother than NSScrollView?
Topic: UI Frameworks SubTopic: AppKit Tags:
3
1
531
Feb ’25
How to lookup keybinding translation across input sources
I have an application that binds a menu item to trigger on ⌘]. When I set the US input source, I press ⌘] in order to trigger that item. However, when I switch the input source to QWERTZ (German), the trigger changes to ⌘Ä automatically by the OS. It seems to translate keystrokes for different input sources. The problem is that I also render the keybindings in a window in my application, and my application is not aware of this translation. Furthermore, I have other key shortcuts in my application which are not bound to menu items, and I want to make sure those get translated too. Does AppKit expose a way to lookup what a keystroke will be when MacOS translates it, i.e. lookup ⌘Ä from ⌘] when the current layout is QWERTZ? I can't find anything in Apple's docs. I tried converting a character to virtual key code based on the US layout and then mapping it back to a character based on the QWERTZ layout. That doesn't seem to be the same b/c that ends up converting ] to + instead which seems to be based on physical key location, different from how the keybindings are handled. Update: I notice similar behavior for VS Code's menu bar, e.g. in their "Terminal" menu. Switching to German changes some bindings. This does not occur at all in iTerm's menu bar, I suspect b/c their menu items are specified in a different way, xib files with hard-coded key equivalents
0
0
364
Jan ’25
Validate drag operations with Transferable
Let's say I want to build a simple photo management app on Mac or iPad with Swift UI. This app has multi-window support. My photos are organized inside albums. I should be able to drag photos between windows from one album to another. I struggle to get this working properly with Swift UI. Writing modern code I would like to use Transferable. Let's say my photos are not real files. So I can't use a FileRepresentation. Instead I use CodableRepresentation and encode an identifier. This identifier is later used to drive the move operation between folders. I ran into some limitations here Transferable seems to be meant for copy-like Drag & Drop operations. I have no possible to get a "move" cursor on macOS (it's always the copy cursor with the green + sign). Also the API reads like it is about importing/exporting – not moving. When using dropDestination on ForEach, I completely lack the possibility to deny a drop (e.g. when a photo is already part of the album). I'd like to have modifier key to switch between copying and moving. Sometimes a drop should be redirected to a different index. How to do that? Is there any chance to do this with Transferable? It even doesn't seem to be easy with NSItemProvider and onDrop/onDrag? Or should we still use a plain old UICollectionView/NSCollectionView, if we want to have more sophisticated control over drag/drop validation?
4
0
392
Jan ’25
Cannot mimic fullscreen behavior when using custom event loop
Hi, we are developing a cross-platform library for creating desktop applications in C++: https://github.com/aseprite/laf For this reason, in macOS, we cannot rely on the default NSApplication.run() event loop, so we decided to implement our custom event loop using the nextEventMatchingMask method. Then, when a window is in fullscreen mode, for some reason the window stops receiving mouseMove events when the mouse pointer enters an area at the top of the window. You can see this issue in action by trying the following example project: https://github.com/martincapello/custom-event-loop-issue This project just opens one window and uses a custom event loop, it displays the current mouse position at every mouseMove event received, and when the aforementioned area is entered it suddenly stops updating. There is also a video showing how to reproduce it. I was able to see that when the position stops updating, we still receive mouseMove events, but for a different window, a borderless window that is added to the NSApplication.windows collection when switching to fullscreen, and which seems to be taken the mouseMove events before reaching the main window. Also, this issue doesn't happen when using the default NSApplication.run method, despite the borderless windows being added as well.
8
0
584
Jan ’25
Registering a macOS app for dynamic text sizing in macOS 15
macOS 15 includes a neat section in System Preferences Settings to change the dynamic text size, as outlined see: https://support.apple.com/guide/mac-help/make-text-and-icons-bigger-mchld786f2cd/mac However, it's not immediately clear a) how to get one's app in this list, and b) if the usual methods from iOS to react to text size even work on macOS. Does anyone have any experience here? Or should I implement my own controls in my app's settings and call it a day? For context, my app is a macOS-native SwiftUI app.
1
0
558
Jan ’25
Whats the Appkit equivalent of SwiftUI's NavigationSplitView?
How do I implement the same Navigation split view with a side bar in Appkit? Basically I have this code: import SwiftUI struct ContentView: View { var body: some View { NavigationSplitView { // Sidebar List { NavigationLink("Item 1", value: "Item 1 Details") NavigationLink("Item 2", value: "Item 2 Details") NavigationLink("Item 3", value: "Item 3 Details") } .navigationTitle("Items") } content: { // Main content (detail view for selected item) Text("Select an item to see details.") .padding() } detail: { // Detail view (for the selected item) Text("Select an item from the sidebar to view details.") .padding() } } } struct MyApp: App { var body: some Scene { WindowGroup { ContentView() } } } and wanted to somehow convert it to Appkit. I tried to use an NSSplitViewController but I still don't have that side bar and that button to collapse it, how do I go about this?
2
0
617
Dec ’24
NSTextField Delegates Not Triggering After Refactoring NSView to NSViewController in macOS App
I'm developing a macOS application and facing an issue with NSTextField delegates after refactoring my code. Here's the situation: I have an NSWindowController. Inside the NSWindowController, there's a container NSView named containerView. On top of containerView, I added a custom NSView subclass named MyDetailsView. MyDetailsView has two NSTextField instances, and their delegates are properly set. The delegate methods like controlTextDidChange(_:) were getting called as expected. Due to some additional requirements, I refactored MyDetailsView into MyDetailsViewController, a subclass of NSViewController. I created a corresponding .xib file for MyDetailsViewController. Updated the code to load and add MyDetailsViewController's view (view property) to containerView. Verified that the NSTextField delegates are still being set, and the fields are displayed correctly in the UI. However, after this refactor, the NSTextField delegate methods (e.g., controlTextDidChange(_:)) are no longer being triggered. **What I've Tried: ** Verified that the delegates for the NSTextField instances are correctly set after the refactor. Ensured that the MyDetailsViewController's view is added to containerView. Question: What could be causing the NSTextField delegate methods to stop working after refactoring from NSView to NSViewController? @IBOutlet weak var customeView: NSView! var myDetailsViewController: MyDetailsViewController! var myDetailsView: MyDetailsView! var isViewController: Bool = true override func windowDidLoad() { super.windowDidLoad() if isViewController { myDetailsViewController = MyDetailsViewController(nibName: "MyDetailsViewController", bundle: nil) self.customeView.addSubview(myDetailsViewController.view) } else { myDetailsView = MyDetailsView.createFromNib() self.customeView.addSubview(myDetailsView!) } } override func showWindow(_ sender: Any?) { super.showWindow(nil) window?.makeKeyAndOrderFront(nil) } override var windowNibName: NSNib.Name? { return NSNib.Name("MyWindowController") }} class MyDetailsViewController: NSViewController { @IBOutlet weak var textField: NSTextField! override func viewDidLoad() { super.viewDidLoad() // Do view setup here. } } extension MyDetailsViewController: NSTextDelegate { func controlTextDidChange(_ obj: Notification) { guard let textField = obj.object as? NSTextField else { return } print("The value is ----> (MyDetailsViewController) \(textField.stringValue)") } } TextField delegate is set in XIB.
Topic: UI Frameworks SubTopic: AppKit Tags:
0
0
351
Dec ’24
Metal-cpp-extensions isn't working inside frameworks
I am making a framework in C++ using metal-cpp, basically a small game engine. I am also consequently using metal-cpp-extensions provided in LearnMetalCPP to make applications work. For one of my classes, I needed to add AppKit.hpp inside a public header file, so I moved it and its associate headers(NSApplication.hpp, NSMenu.hpp, etc.) from Project headers to Public in Build Phases' Headers, however, it started giving me the error "cast of C pointer type 'void *' to Objective-C pointer type 'Class' requires a bridged cast" at several points in the AppKit headers. They don't appear when AppKit and its associates are in the Project headers, or when they are in the Private headers and no headers import it. I imagined that disabling Objective-C ARC and Using __bridge casts outside of ARC in Build Settings would solve it, but it didn't budge. I imagined it wouldn't involve actively changing the headers would be the answer, but even if I try to put __bridge before the problematic casts, it didn't recognize __bridge. How do I solve this? And why is it only happening in Public and not Project headers?
2
0
755
Jan ’25
Bug when entering credentials for a Mac on LAN through File -> Open... -> Network
I've been experiencing a bug when trying to open a file on a remote machine through File -> Open... -> Network -> Connect As... where the Name/Password dialog won't let me enter more than one character into its text fields. I'm able to get one more character in by toggling between the "Registered User" and "Guest" radio buttons, and it seems to fix itself entirely when I focus on another window before entering my credentials. Once it is "fixed", it doesn't happen again until the machine's restarted. I was able to reproduce this on 15.1 and 15.1.1, but not on 15.0.1 (I do not currently have access to a machine running 15.2). Here are some reproduction steps: (You will need a shared computer on LAN) Restart your machine (un-check reopen windows when logging back in) Open TextEdit From the Menu Bar, click “File > Open...” Select “Network” from the Open Dialog’s sidebar Select your shared computer on LAN and click “Connect As…” Try typing in the password field. This will only allow the first key press to produce a character in the text field. (In my case, the Name field was already populated, so the password field was automatically selected) (Filed as FB16039397)
0
0
333
Dec ’24
Screen record restriction in MacOS app
I have a MacOs AppKit app. This app we are developing for examination purposes. We dont want the user to screen record and also to take screen shot. We created a window and set the sharingType to none. also we have set window.level to CGShieldingWindowLevel() Below is the code if let window = NSApp.windows.first { window.title = "Test" window.sharingType = .none // Disable screen capture and recording window.level = NSWindow.Level(rawValue: Int(CGShieldingWindowLevel())) // } As per documentation the windows should be excluded from screen capture and also recording But the window is excluded only from screen capture and not from screen recording. Please give us a solution to prevent screen recording in MacOs native app.
Topic: UI Frameworks SubTopic: AppKit Tags:
3
0
565
Dec ’24
NSOutlineView with Diffable Data Source
Hi, On macOS, there seems to be a NSTableViewDiffableDataSource and an NSCollectionViewDiffableDataSource, but there seems to be nothing for NSOutlineView. Is it possible to somehow use NSTableViewDiffableDataSource with NSOutlineView that I'm missing? If not, is it possible to use NSTableView with NSTableViewDiffableDataSource to show a 'table' with section headers?
Topic: UI Frameworks SubTopic: AppKit Tags:
5
0
633
Dec ’24