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

Posts under AppKit tag

200 Posts

Post

Replies

Boosts

Views

Activity

NSMenuItem.separator() appears as blank space in Finder Sync extension context menu
Hi, I’m developing a macOS Finder Sync extension and noticed that NSMenuItem.separator() does not appear to render as a standard separator line when used inside the menu returned from FIFinderSyncController. In a normal AppKit NSMenu, the separator renders as expected. However, when the same kind of menu is returned from the Finder Sync extension, the separator appears as a blank/full-height empty row rather than a thin dividing line. Example: override func menu(for menuKind: FIMenuKind) -> NSMenu { let menu = NSMenu(title: "") menu.addItem(NSMenuItem( title: "First Action", action: #selector(firstAction(_:)), keyEquivalent: "" )) menu.addItem(NSMenuItem.separator()) menu.addItem(NSMenuItem( title: "Second Action", action: #selector(secondAction(_:)), keyEquivalent: "" )) return menu } Expected result: The separator should render as a normal macOS menu separator line between the two menu items. Actual result: In Finder’s context menu, the separator is displayed as blank vertical space / an empty menu row. I understand that Finder Sync menus are rendered by Finder and may not support every NSMenuItem feature. However, NSMenuItem.separator() is a very standard way to visually group menu commands, so I wanted to ask: Is this a known limitation of Finder Sync extension menus? Is there a supported way to display a real separator line in Finder Sync context menus? Should this be filed as a Feedback Assistant issue against Finder Sync / AppKit? I’m trying to avoid fake separators such as disabled menu items with "────" as the title, since that does not feel native and may not behave well with different fonts, accessibility settings, or appearance modes. Thanks!
0
0
22
11h
Various menu bar NSStatusItem issues with macOS 27
It seems like macOS 27 beta 2 has some issues with NSStatusItem buttons added to the menu bar - this creates difficulties for some menu bar extra apps. NSStatusItem buttons does not receive mouse hover/movement events - FB23329983 On macOS 27, views inside an NSStatusItem button no longer receive hover or mouse-movement events. The same code works correctly on macOS 26. What I tried: An NSTrackingArea attached to a subview of NSStatusBarButton An NSTrackingArea attached directly to the status-bar button Replacing NSStatusItem.view with a custom view Embedding an NSHostingView and using SwiftUI onHover/onContinuousHover NSStatusItem button highlight cannot be set programmatically. - FB23330269 The following code no longer has any effect (does not provide the highlight capsule): NSStatusItem.button?.highlight(true) NSStatusItem window occlusionState no longer reflects hidden menu bar visibility - FB23349447 The following no longer works: statusItem.button?.window?.occlusionState.contains(.visible) These changes may be related to some of the touch related changes or maybe it's about how menu items are now seemingly more "managed" in a way that their position, visibility may change in a way that is transparent/undetectable to the app.
0
0
28
20h
Does @IBSegueAction still not work for AppKit relationship segues from NSWindowController?
I’m working on a storyboard-based AppKit application that uses an NSWindowController containing an NSSplitViewController with multiple child view controllers. The hierarchy is roughly: NSWindowController └── NSSplitViewController ├── NSViewController ├── NSViewController └── NSViewController I am trying to provide dependencies during storyboard instantiation using either @IBSegueAction or instantiateInitialController(creator:), rather than configuring everything after initialisation. What I attempted I added custom initialisers to my view controllers so I can pass dependencies at creation time: class SplitViewController: NSSplitViewController { let dependency: Dependency init?(coder: NSCoder, dependency: Dependency) { self.dependency = dependency super.init(coder: coder) } required init?(coder: NSCoder) { print("init(coder:) was called") fatalError("init(coder:) is not supported") } } I then attempted to intercept storyboard instantiation using @IBSegueAction, trying it in both the window controller and the split view controller: @IBSegueAction func makeSplitViewController(_ coder: NSCoder) -> NSSplitViewController? { SplitViewController(coder: coder, dependency: dependency) } I also tried attaching the segue action at different points in the storyboard, but the behaviour did not change. Observed behaviour Regardless of where I place the segue action, AppKit still appears to call: required init?(coder: NSCoder) This means my custom initialiser is never used for the split view controller or its children. Background reference I found this older known issue in the Xcode 11 release notes: “A Segue Action on a relationship segue between a NSWindowController and a View Controller is currently not supported and ignored. (48252727)” This suggests that, at least historically, AppKit relationship segues ignored segue actions entirely. Has this limitation since been fixed in modern Xcode/macOS SDK releases, or are relationship segues involving NSWindowController still incompatible with @IBSegueAction? More generally, what is the intended way to provide dependencies to an NSSplitViewController and its child view controllers in a storyboard-based AppKit application? I am also unclear whether instantiateInitialController(creator:) participates in the creation of container hierarchies like split view controllers, or only top-level controllers.
2
0
386
2d
NSTableView: checking for mouse-driven selection changes on macOS 27
I have an NSTableView used as a source list and, alongside it, two editors. When the user selects anything in the table view, its content is opened in the editor that has the focus. When the user Opt-clicks an item in the table, though, the content is opened in the other editor, making it easy for the user to load something in the other editor without having to change the focus first. This has worked for many years using NSTableView.selectiondDidChange / the NSTableViewDelegate as follows: func tableViewSelectionDidChange(_ notification: Notification) { if let event = tableView.window?.currentEvent, event.type == .leftMouseUp || event.type == .leftMouseDown, // (Real app does some other checks here too.) event.modifierFlags.contains(.option) { openInOtherEditor() return } openInCurrentEditor() } However, on macOS 27, it seems that things need to be done differently because of the transition to gesture recognisers for event handling. According to the WWDC video "Modernise Your AppKit App", and to Tech Note TN3212, currentEvent can no longer be relied upon to provide the event that actually triggered an action in NSControl subclasses: The transition to gesture recognizers on NSControl objects changes the timing of when AppKit delivers control action messages with respect to event processing. As a result, currentEvent no longer returns the event that triggered an action. It's unclear whether this new limitation refers only to NSControl.action or to all mouse-driven actions, but from the context and what the rest of the Tech Note has to say, I assume it's the latter. (Especially since you are no longer supposed to override mouseDown(with:), and the Console warns about gestures being disabled if you do override mouseDown(with:) in an NSTableView subclass on macOS 27.) currentEvent still seems to work fine in this situation in the first macOS 27 beta, but it sounds as though we cannot rely on this continuing to be the case. If we should no longer be using currentEvent, then, what should we use instead to determine whether a selection change was triggered by a mouse click? The Tech Note and WWDC video have nothing to say about this. They simply say that instead of overriding mouseDown(with:), you should use the selection-did-change delegate methods, which is of no help here. (By contrast, checking the modifier flags is still straightforward; the Tech Note says to use NSEvent.modifierFlags instead of currentEvent.modifierFlags.) Two solutions sprung to mind, but neither worked: Check tableView.clickedRow != -1 in the selectionDidChange delegate method/notification response. This doesn't work, however, because clickedRow has been reset to -1 by the time NSTableView.selectionDidChange is sent. Add an action to the table view and check clickedRow there. This doesn't work either, though, because although clickedRow is available in the action method, I would now have to load content in response to both an action and a selection change, and since the selection changes before the action is called, there is no way of telling my selection-did-change method not to load in the main editor if Option is held down in the action. The only solution I have found is to override selectRowIndexes(_:byExtendingSelection:), check for clickedRow != -1 there, set a didChangeSelectionWithMouse flag to true if so, and check that in the selection-did-change delegate method. That works, but it's not the most elegant of solutions. So: Am I misunderstanding the Tech Note? Can currentEvent still in fact be used safely in tableViewSelectionDidChange(_:) in macOS 27 and beyond? If not, what is the recommended way of checking that the table selection has been changed by a mouse click? Many thanks!
Topic: UI Frameworks SubTopic: AppKit Tags:
8
0
161
3d
IKPictureTaker shows blank panel on macOS 26 — popUpRecentsMenu silently fails with no callback
We're using IKPictureTaker to let users pick a room avatar image. The flow worked correctly on macOS 13–15, but breaks on macOS 26 (Tahoe). Symptoms popUpRecentsMenu(for:withDelegate:didEnd:contextInfo:) — no UI appears at all, and the didEnd selector is never called runModal() — a window appears but its content is completely blank (empty gray rectangle). The app freezes until the user force-quits Minimal reproduction import Quartz let pictureTaker = IKPictureTaker.pictureTaker() pictureTaker?.setCommonValuesForKeys(allowsVideoCapture: true) // Attempt 1 — silent fail, no UI, no callback pictureTaker?.popUpRecentsMenu(for: someButton, withDelegate: self, didEnd: #selector(pictureTakerDidEnd), contextInfo: nil) // Attempt 2 — window appears but content is blank let result = pictureTaker?.runModal() // result is never returned while window is visible; app is frozen Environment macOS 26.0 (Tahoe) — reproducible by QA on multiple machines Xcode 16, Swift 5, deployment target macOS 10.14 Camera permission granted (AVAuthorizationStatus.authorized) App is sandboxed What I've ruled out Camera permission is authorized before the call The view passed to popUpRecentsMenu has a valid, visible, key window Same code works on macOS 13, 14, 15 Question Is this a known regression in macOS 26? Is IKPictureTaker expected to stop working, or is there a required entitlement / initialization step that changed? If the API is effectively unsupported, is NSOpenPanel with allowedContentTypes: [.image] the recommended migration path?
3
0
150
3d
How to override NSTextView dragging behaviour without overriding mouseDown:?
I have an NSTextView subclass that overrides mouseDown: to allow for image resizing. If a user clicks and drags on the edges of an image, I implement custom behaviour that resizes the image (and shows resizing cursors). If the user clicks anywhere else, super's implementation is called. This all works great. As of macOS 27, however, the transition to gesture recognisers instead of overriding mouseDown: means that I should probably be moving away from the above approach. NSTextView now uses the new NSTextSelectionManager to implement selection and dragging via gesture recognisers, although, according to the release notes: Existing NSTextView subclasses that override mouseDown: continue to work through a binary-compatible fallback path. (163365571) It's unclear whether this means that we therefore should still override mouseDown: for custom behaviour in NSTextView, but to me, this, along with the content of Tech Note TN3212, strongly implies that, although it will continue to work thanks to "a binary-compatible fallback", we should entirely move away from overriding mouseDown: in the future. If that is indeed the case, how do we implement custom dragging behaviour--such as for resizing images as in my example--in NSTextView? There still seems to be no way of doing it other than overriding mouseDown:. I had thought that I might be able to add an NSPanGestureRecognizer to the text view and have it fail via its delegate methods if the clicks were outside of an image's edges, but a pan gesture recogniser added to an NSTextView is entirely ignored, presumably because of the private gestures already added. Fortunately everything continues to work for now, but I would like to update my code as much as possible.
Topic: UI Frameworks SubTopic: AppKit Tags:
4
0
106
4d
NSTextView.menuForEvent - getting the affected range on macOS 27
I have an NSTextView subclass that replaces the standard context menu with a custom one by building its own menu in an menuForEvent: override. The context menu that is shown depends on what is selected in the text view, so it checks the current selectedRange to determine which commands should be included. (I could do much the same via the NSTextViewDelegate method textView(_:menu:for:at:), but since my text view subclass is used in several areas, each with their own delegate, it's better to do it in menuForEvent(_:).) This has all worked fine for years, but with NSTextView's transition to gesture recognisers and NSTextSelectionManager for handling text selections in macOS 27, the timings have changed. Previously, if you Ctrl-clicked on a word so that the word is selected and the context menu appears, setSelectedRanges:affinity:stillSelecting: would be called first and then menuForEvent: would be called. On macOS 27, however, the order of events is reversed: menuForEvent: is called first, before setSelectedRanges:affinity:stillSelecting:. (If you implement NSMenuDelegate.menuNeedsUpdate:, that is also called before setSelectedRanges:....) This means that you can no longer rely on selectedRanges in menuForEvent:, because on macOS 27, selectedRanges in menuForEvent: represents the previous selection, not the selection you will actually see on screen when the menu appears. This makes building a custom context menu somewhat tricky. I suspect this is a bug and have reported it as such (FB23251873, with apologies to the engineers for the pleading tone in that report; it was at the end of a long week of getting my head around the gesture recogniser changes. :) ). But it occurs to me that there is nothing in the documentation that guarantees that selectedRanges will be accurate in menuForEvent:; it's just always worked this way. So am I missing something here? Is there a better or more reliable way of getting the range that will be affected by the contextual menu in NSTextView? (The delegate method only provides a single character index, which isn't enough information for spelling corrections and such which require a range.) My current workaround is to rebuild the context menu in setSelectedRanges:affinity:stillSelecting: if it is called between menuForEvent: and didCloseMenu:withEvent:.
Topic: UI Frameworks SubTopic: AppKit Tags:
2
0
60
4d
How do you correctly use a SwiftUI View inside an NSToolbarItem?
I've been struggling to get consistent UI and UX behaviour of SwiftUI Views inside NSToolbarItems and was wondering if there is an official way to use them. I've now revisited this issue in macOS 27 and continue to see some idiosyncrasies. In the attached screenshot, you can see that the highlight area on mouse down between to the two buttons is different. This is the easiest example I've come up with that shows SwiftUI Views exhibiting different behaviour than AppKit Views. Two questions: Is an NSHostingView a valid and supported view type for NSToolbarItem.view? If so, are there any rules that govern how the SwiftUI view should be configured? (ex: frame, sizing options, supported SwiftUI Views, preferred "root view" types, etc?) Sample code that created the two NSToolbarItem buttons in the screenshot. macOS 27 ZY21R0CMGL (Public Beta 1) Xcode 27.0 beta Minimum Deployment target: 27.0 // Left-Top SwiftUI Button (Clipped Highlighting) let item = NSToolbarItem(itemIdentifier: itemIdentifier) let rootView = Button { } label: { Image(systemName: "sidebar.trailing") } item.view = NSHostingView(rootView: rootView) // ... snip .. // Right-Bottom AppKit Button (Correct Highlighting) let item = NSToolbarItem(itemIdentifier: itemIdentifier) item.image = NSImage(systemSymbolName: "sidebar.trailing", accessibilityDescription: nil) Both screenshots are taken on mouse down.
2
0
78
4d
Annoying popup window in Xcode Previews when the initial controller of the main storyboard is a macOS window
I started a project targeting macOS and used Storyboard app lifecycle. I also used Xcode Previews in this project. If I: Keep the entry point of the main storyboard to a window controller. (as default setup in macOS), Turn the Xcode window into full-screen, That window controller would pop up its window every time Xcode Previews refreshes. I tested in Xcode 26.3 RC and many versions before.
7
0
316
1w
Quick Look Plugin for Mac and Internet Access
I'd like to create a Quick Look extension for a file type for which a location or region on a Map should be shown as preview. However the MapView would only show a grid without any map. From within the MapKit delegate I can see from the "Error" parameter (a server with this domain can not be found) that this seems to be a network issue. The Quick Look extension seems to have no access to the internet and therefore the MapView can not load any map data. I've then also done some other tests via URLSession, which also only fails with connection errors. I haven't seen any limitations or restrictions mentioned in the API documentation. Is this the expected behavior? Is this a bug? Or am I missing something?
6
0
529
1w
Are NSStatusItem Interactions Still Allowed?
We have a status item which works fine on macOS 26 and earlier, which has the following properties: Supports left-click to open main UI (a popover) Supports left-click (while open) to toggle (close) the main UI Supports right-click to show "app" menu (e.g. About, Quit) Supports a drop destination to accept files and folders, which then triggers the main UI for more interaction In macOS 27: left-click seems ok if we use expanded interface session, but otherwise broken left-click while open no longer toggles (event is missing?) right click is no longer operational, to the point that it seems the Menu Bar doesn't forward the event at all. Other (Apple-provided) items work fine, and expose new context menus Dragging now triggers Mission Control, which seems wrong given the destination was in the Menu Bar (FB23018381). Are these interactions now forbidden, and are there lists or documentation of the new rules? As an additional bug, it looks like popovers don't pick up appearance changes. The child scroll view claims to be in light appearance in the View Debugger, but is clearly showing the wrong background color, this is a new (as-yet unreported) issue. One last bug: expanded interface session seems to suppress the popover's animation when shown.
Topic: UI Frameworks SubTopic: AppKit Tags:
7
1
155
1w
[NSWorkspace desktopImageOptionsForScreen:] does not return key "Show on all spaces"
It seems this method is not updated for the new "Show on all Spaces" option in system wallpaper preferences. I encounter this problem because one customer reported that every time my app sets a new wallpaper, this option is turned off. NSDictionary* options = [SHARED_WORKSPACE desktopImageOptionsForScreen:screen]; [SHARED_WORKSPACE setDesktopImageURL:imageFileURL forScreen:screen options:options error:&error]; This can be easily verified by dumping the returned dictionary - which only contains 3 keys. Is this a known bug?
1
0
160
1w
NSTokenField - How To Tell If I'm Editing an Existing Token in -tokenField:representedObjectForEditingString: ?
I'm trying to use NSTokenField for the first time. So my custom 'representedObject' for a token has additional model data tied to it (not just the editing/display string). I noticed when I edit an existing token, type text, and hit the enter key I get the following delegate callback: - (nullable id)tokenField:(NSTokenField *)tokenField representedObjectForEditingString:(NSString *)editingString; This same delegate method is called when I type a brand new token. Is there a way to distinguish if I'm editing a token vs. creating a new one? My expectation is to be able to do something like this (made up enhancement): - (nullable id)tokenField:(NSTokenField *)tokenField representedObjectForEditingString:(NSString *)editingString atIndex:(NSUInteger)existingTokenIndex { if (existingTokenIndex == NSNotFound) { // Token is new, create a new instance MyTokenObject *newToken = //create and configure. return newToken; } else { // This would update the editing string but wouldn't discard existing data held by the token. MyTokenObject *tokenObj = [self existingTokenAtIndex:existingTokenIndex]; tokenObj.editingString = editingString; return tokenObj; } }
2
0
170
1w
How do I get SwiftUI to let me determine a custom frame size for NSTextField
I have a NSViewRepresentable that wraps an NSTextField subclass which is displayed as larger than your typical text field. SwiftUI doesn't seem to allow me to set the size of the view when the underlying is an NSTextField. It forces it as a single line field. I've tried both setting the frame on creation as well as using SwiftUI .frame(width:height:) on the represented view. I always end up with a single line field. struct BigTextField: NSViewRepresentable { @Binding var text: String class Coordinator: NSObject, NSTextFieldDelegate { var parent: BigTextField init(_ parent: BigTextField) { self.parent = parent } func controlTextDidChange(_ obj: Notification) { if let textField = obj.object as? NSTextField { parent.text = textField.stringValue } } } func makeCoordinator() -> Coordinator { Coordinator(self) } func makeNSView(context: Context) -> NSTextField { //let frame = NSRect(x: 0, y: 0, width: 350, height: 140) //let textField = NSTextField(frame: frame) let textField = NSTextField() textField.isEditable = true textField.isBordered = true textField.isBezeled = true textField.delegate = context.coordinator // Assign the coordinator return textField } func updateNSView(_ nsView: NSTextField, context: Context) { if nsView.stringValue != text { nsView.stringValue = text } } } I've also included the SwiftUI declaration which demonstrates the problem. struct ContentView: View { @State var text : String = "Test string" var body: some View { VStack { BigTextField(text: $text) .frame(width: 350, height: 140) } .padding() } } NSTextField can be any arbitrary frame size. I already do this from AppKit but am trying to adapt this custom field to work within SwiftUI. SwiftUI seems to override the sizing of this NSViewRepresentable that I give it. Am I missing something here? Is there some way to override SwiftUI's sizing behavior? Thank you.
0
0
90
1w
TextKit 2 + SwiftUI (NSViewRepresentable): NSTextLayoutManager rendering attributes don’t reliably draw/update
I’m embedding an NSTextView (TextKit 2) inside a SwiftUI app using NSViewRepresentable. I’m trying to highlight dynamic subranges (changing as the user types) by providing per-range rendering attributes via NSTextLayoutManager’s rendering-attributes mechanism. The issue: the highlight is unreliable. Often, the highlight doesn’t appear at all even though the delegate/data source is returning attributes for the expected range. Sometimes it appears once, but then it stops updating even when the underlying “highlight range” changes. This feels related to SwiftUI - AppKit layout issue when using NSViewRepresentable (as said in https://developer.apple.com/documentation/swiftui/nsviewrepresentable). What I’ve tried Updating the state that drives the highlight range and invalidating layout fragments / asking for relayout Ensuring all updates happen on the main thread. Calling setNeedsDisplay(_:) on the NSViewRepresentable’s underlying view. Toggling the SwiftUI view identity (e.g. .id(...)) to force reconstruction (works, but too expensive / loses state). Question In a SwiftUI + NSViewRepresentable setup with TextKit 2, what is the correct way to make NSTextLayoutManager re-query and redraw rendering attributes when my highlight ranges change? Is there a recommended invalidation call for TextKit 2 to trigger re-rendering of rendering attributes? Or is this a known limitation when hosting NSTextView inside SwiftUI, where rendering attributes aren’t reliably invalidated? If this approach is fragile, is there a better pattern for dynamic highlights that avoids mutating the attributed string (to prevent layout/scroll jitter)?
4
0
464
1w
Debugging multi-window AppKit apps: Identifying the window associated with a breakpoint
When working on a multi-window AppKit app, how do you identify which window instance is associated with the current breakpoint? The same question applies when using LLDB. If execution stops inside an object that can exist in more than one window, such as a shared NSViewController subclass, how do you know which window’s object you are currently inspecting? Does Xcode provide a mechanism for showing the NSWindow associated with the current view, view controller or responder while debugging? My current approach is to print object identities and compare them manually. For example, if several identical windows are open, I might print the current object and its window: print(self, #function) Then I interact with one window, make a note of the printed memory addresses in the console, switch to another window and compare the output. This works, but it feels manual. I am not dealing with different window subclasses. The windows may be instances of the same class and may contain instances of the same view controller classes. I simply want an easier way to distinguish which window instance I am debugging. Is there a recommended Xcode, LLDB or AppKit workflow for this?
1
0
156
1w
How to dynamically update an existing AVComposition when users add a new custom video clip?
I’m building a macOS video editor that uses AVComposition and AVVideoComposition. Initially, my renderer creates a composition with some default video/audio tracks: @Published var composition: AVComposition? @Published var videoComposition: AVVideoComposition? @Published var playerItem: AVPlayerItem? Then I call a buildComposition() function that inserts all the default video segments. Later in the editing workflow, the user may choose to add their own custom video clip. For this I have a function like: private func handlePickedVideo(_ url: URL) { guard url.startAccessingSecurityScopedResource() else { print("Failed to access security-scoped resource") return } let asset = AVURLAsset(url: url) let videoTracks = asset.tracks(withMediaType: .video) guard let firstVideoTrack = videoTracks.first else { print("No video track found") url.stopAccessingSecurityScopedResource() return } renderer.insertUserVideoTrack(from: asset, track: firstVideoTrack) url.stopAccessingSecurityScopedResource() } What I want to achieve is the same behavior professional video editors provide, after the composition has already been initialized and built, the user should be able to add a new video track and the composition should update live, meaning the preview player should immediately reflect the changes without rebuilding everything from scratch manually. How can I structure my AVComposition / AVMutableComposition and my rendering pipeline so that adding a new clip later updates the existing composition in real time (similar to Final Cut/Adobe Premiere), instead of needing to rebuild everything from zero? You can find a playable version of this entire setup at :- https://github.com/zaidbren/SimpleEditor
1
0
543
2w
NSMenuItem.separator() appears as blank space in Finder Sync extension context menu
Hi, I’m developing a macOS Finder Sync extension and noticed that NSMenuItem.separator() does not appear to render as a standard separator line when used inside the menu returned from FIFinderSyncController. In a normal AppKit NSMenu, the separator renders as expected. However, when the same kind of menu is returned from the Finder Sync extension, the separator appears as a blank/full-height empty row rather than a thin dividing line. Example: override func menu(for menuKind: FIMenuKind) -> NSMenu { let menu = NSMenu(title: "") menu.addItem(NSMenuItem( title: "First Action", action: #selector(firstAction(_:)), keyEquivalent: "" )) menu.addItem(NSMenuItem.separator()) menu.addItem(NSMenuItem( title: "Second Action", action: #selector(secondAction(_:)), keyEquivalent: "" )) return menu } Expected result: The separator should render as a normal macOS menu separator line between the two menu items. Actual result: In Finder’s context menu, the separator is displayed as blank vertical space / an empty menu row. I understand that Finder Sync menus are rendered by Finder and may not support every NSMenuItem feature. However, NSMenuItem.separator() is a very standard way to visually group menu commands, so I wanted to ask: Is this a known limitation of Finder Sync extension menus? Is there a supported way to display a real separator line in Finder Sync context menus? Should this be filed as a Feedback Assistant issue against Finder Sync / AppKit? I’m trying to avoid fake separators such as disabled menu items with "────" as the title, since that does not feel native and may not behave well with different fonts, accessibility settings, or appearance modes. Thanks!
Replies
0
Boosts
0
Views
22
Activity
11h
Various menu bar NSStatusItem issues with macOS 27
It seems like macOS 27 beta 2 has some issues with NSStatusItem buttons added to the menu bar - this creates difficulties for some menu bar extra apps. NSStatusItem buttons does not receive mouse hover/movement events - FB23329983 On macOS 27, views inside an NSStatusItem button no longer receive hover or mouse-movement events. The same code works correctly on macOS 26. What I tried: An NSTrackingArea attached to a subview of NSStatusBarButton An NSTrackingArea attached directly to the status-bar button Replacing NSStatusItem.view with a custom view Embedding an NSHostingView and using SwiftUI onHover/onContinuousHover NSStatusItem button highlight cannot be set programmatically. - FB23330269 The following code no longer has any effect (does not provide the highlight capsule): NSStatusItem.button?.highlight(true) NSStatusItem window occlusionState no longer reflects hidden menu bar visibility - FB23349447 The following no longer works: statusItem.button?.window?.occlusionState.contains(.visible) These changes may be related to some of the touch related changes or maybe it's about how menu items are now seemingly more "managed" in a way that their position, visibility may change in a way that is transparent/undetectable to the app.
Replies
0
Boosts
0
Views
28
Activity
20h
Does @IBSegueAction still not work for AppKit relationship segues from NSWindowController?
I’m working on a storyboard-based AppKit application that uses an NSWindowController containing an NSSplitViewController with multiple child view controllers. The hierarchy is roughly: NSWindowController └── NSSplitViewController ├── NSViewController ├── NSViewController └── NSViewController I am trying to provide dependencies during storyboard instantiation using either @IBSegueAction or instantiateInitialController(creator:), rather than configuring everything after initialisation. What I attempted I added custom initialisers to my view controllers so I can pass dependencies at creation time: class SplitViewController: NSSplitViewController { let dependency: Dependency init?(coder: NSCoder, dependency: Dependency) { self.dependency = dependency super.init(coder: coder) } required init?(coder: NSCoder) { print("init(coder:) was called") fatalError("init(coder:) is not supported") } } I then attempted to intercept storyboard instantiation using @IBSegueAction, trying it in both the window controller and the split view controller: @IBSegueAction func makeSplitViewController(_ coder: NSCoder) -> NSSplitViewController? { SplitViewController(coder: coder, dependency: dependency) } I also tried attaching the segue action at different points in the storyboard, but the behaviour did not change. Observed behaviour Regardless of where I place the segue action, AppKit still appears to call: required init?(coder: NSCoder) This means my custom initialiser is never used for the split view controller or its children. Background reference I found this older known issue in the Xcode 11 release notes: “A Segue Action on a relationship segue between a NSWindowController and a View Controller is currently not supported and ignored. (48252727)” This suggests that, at least historically, AppKit relationship segues ignored segue actions entirely. Has this limitation since been fixed in modern Xcode/macOS SDK releases, or are relationship segues involving NSWindowController still incompatible with @IBSegueAction? More generally, what is the intended way to provide dependencies to an NSSplitViewController and its child view controllers in a storyboard-based AppKit application? I am also unclear whether instantiateInitialController(creator:) participates in the creation of container hierarchies like split view controllers, or only top-level controllers.
Replies
2
Boosts
0
Views
386
Activity
2d
Apple Developer Program? Nah,
Why should we get apple developer program for appkit and to publish apps?
Replies
0
Boosts
0
Views
53
Activity
2d
NSTableView: checking for mouse-driven selection changes on macOS 27
I have an NSTableView used as a source list and, alongside it, two editors. When the user selects anything in the table view, its content is opened in the editor that has the focus. When the user Opt-clicks an item in the table, though, the content is opened in the other editor, making it easy for the user to load something in the other editor without having to change the focus first. This has worked for many years using NSTableView.selectiondDidChange / the NSTableViewDelegate as follows: func tableViewSelectionDidChange(_ notification: Notification) { if let event = tableView.window?.currentEvent, event.type == .leftMouseUp || event.type == .leftMouseDown, // (Real app does some other checks here too.) event.modifierFlags.contains(.option) { openInOtherEditor() return } openInCurrentEditor() } However, on macOS 27, it seems that things need to be done differently because of the transition to gesture recognisers for event handling. According to the WWDC video "Modernise Your AppKit App", and to Tech Note TN3212, currentEvent can no longer be relied upon to provide the event that actually triggered an action in NSControl subclasses: The transition to gesture recognizers on NSControl objects changes the timing of when AppKit delivers control action messages with respect to event processing. As a result, currentEvent no longer returns the event that triggered an action. It's unclear whether this new limitation refers only to NSControl.action or to all mouse-driven actions, but from the context and what the rest of the Tech Note has to say, I assume it's the latter. (Especially since you are no longer supposed to override mouseDown(with:), and the Console warns about gestures being disabled if you do override mouseDown(with:) in an NSTableView subclass on macOS 27.) currentEvent still seems to work fine in this situation in the first macOS 27 beta, but it sounds as though we cannot rely on this continuing to be the case. If we should no longer be using currentEvent, then, what should we use instead to determine whether a selection change was triggered by a mouse click? The Tech Note and WWDC video have nothing to say about this. They simply say that instead of overriding mouseDown(with:), you should use the selection-did-change delegate methods, which is of no help here. (By contrast, checking the modifier flags is still straightforward; the Tech Note says to use NSEvent.modifierFlags instead of currentEvent.modifierFlags.) Two solutions sprung to mind, but neither worked: Check tableView.clickedRow != -1 in the selectionDidChange delegate method/notification response. This doesn't work, however, because clickedRow has been reset to -1 by the time NSTableView.selectionDidChange is sent. Add an action to the table view and check clickedRow there. This doesn't work either, though, because although clickedRow is available in the action method, I would now have to load content in response to both an action and a selection change, and since the selection changes before the action is called, there is no way of telling my selection-did-change method not to load in the main editor if Option is held down in the action. The only solution I have found is to override selectRowIndexes(_:byExtendingSelection:), check for clickedRow != -1 there, set a didChangeSelectionWithMouse flag to true if so, and check that in the selection-did-change delegate method. That works, but it's not the most elegant of solutions. So: Am I misunderstanding the Tech Note? Can currentEvent still in fact be used safely in tableViewSelectionDidChange(_:) in macOS 27 and beyond? If not, what is the recommended way of checking that the table selection has been changed by a mouse click? Many thanks!
Topic: UI Frameworks SubTopic: AppKit Tags:
Replies
8
Boosts
0
Views
161
Activity
3d
IKPictureTaker shows blank panel on macOS 26 — popUpRecentsMenu silently fails with no callback
We're using IKPictureTaker to let users pick a room avatar image. The flow worked correctly on macOS 13–15, but breaks on macOS 26 (Tahoe). Symptoms popUpRecentsMenu(for:withDelegate:didEnd:contextInfo:) — no UI appears at all, and the didEnd selector is never called runModal() — a window appears but its content is completely blank (empty gray rectangle). The app freezes until the user force-quits Minimal reproduction import Quartz let pictureTaker = IKPictureTaker.pictureTaker() pictureTaker?.setCommonValuesForKeys(allowsVideoCapture: true) // Attempt 1 — silent fail, no UI, no callback pictureTaker?.popUpRecentsMenu(for: someButton, withDelegate: self, didEnd: #selector(pictureTakerDidEnd), contextInfo: nil) // Attempt 2 — window appears but content is blank let result = pictureTaker?.runModal() // result is never returned while window is visible; app is frozen Environment macOS 26.0 (Tahoe) — reproducible by QA on multiple machines Xcode 16, Swift 5, deployment target macOS 10.14 Camera permission granted (AVAuthorizationStatus.authorized) App is sandboxed What I've ruled out Camera permission is authorized before the call The view passed to popUpRecentsMenu has a valid, visible, key window Same code works on macOS 13, 14, 15 Question Is this a known regression in macOS 26? Is IKPictureTaker expected to stop working, or is there a required entitlement / initialization step that changed? If the API is effectively unsupported, is NSOpenPanel with allowedContentTypes: [.image] the recommended migration path?
Replies
3
Boosts
0
Views
150
Activity
3d
How to override NSTextView dragging behaviour without overriding mouseDown:?
I have an NSTextView subclass that overrides mouseDown: to allow for image resizing. If a user clicks and drags on the edges of an image, I implement custom behaviour that resizes the image (and shows resizing cursors). If the user clicks anywhere else, super's implementation is called. This all works great. As of macOS 27, however, the transition to gesture recognisers instead of overriding mouseDown: means that I should probably be moving away from the above approach. NSTextView now uses the new NSTextSelectionManager to implement selection and dragging via gesture recognisers, although, according to the release notes: Existing NSTextView subclasses that override mouseDown: continue to work through a binary-compatible fallback path. (163365571) It's unclear whether this means that we therefore should still override mouseDown: for custom behaviour in NSTextView, but to me, this, along with the content of Tech Note TN3212, strongly implies that, although it will continue to work thanks to "a binary-compatible fallback", we should entirely move away from overriding mouseDown: in the future. If that is indeed the case, how do we implement custom dragging behaviour--such as for resizing images as in my example--in NSTextView? There still seems to be no way of doing it other than overriding mouseDown:. I had thought that I might be able to add an NSPanGestureRecognizer to the text view and have it fail via its delegate methods if the clicks were outside of an image's edges, but a pan gesture recogniser added to an NSTextView is entirely ignored, presumably because of the private gestures already added. Fortunately everything continues to work for now, but I would like to update my code as much as possible.
Topic: UI Frameworks SubTopic: AppKit Tags:
Replies
4
Boosts
0
Views
106
Activity
4d
NSTextView.menuForEvent - getting the affected range on macOS 27
I have an NSTextView subclass that replaces the standard context menu with a custom one by building its own menu in an menuForEvent: override. The context menu that is shown depends on what is selected in the text view, so it checks the current selectedRange to determine which commands should be included. (I could do much the same via the NSTextViewDelegate method textView(_:menu:for:at:), but since my text view subclass is used in several areas, each with their own delegate, it's better to do it in menuForEvent(_:).) This has all worked fine for years, but with NSTextView's transition to gesture recognisers and NSTextSelectionManager for handling text selections in macOS 27, the timings have changed. Previously, if you Ctrl-clicked on a word so that the word is selected and the context menu appears, setSelectedRanges:affinity:stillSelecting: would be called first and then menuForEvent: would be called. On macOS 27, however, the order of events is reversed: menuForEvent: is called first, before setSelectedRanges:affinity:stillSelecting:. (If you implement NSMenuDelegate.menuNeedsUpdate:, that is also called before setSelectedRanges:....) This means that you can no longer rely on selectedRanges in menuForEvent:, because on macOS 27, selectedRanges in menuForEvent: represents the previous selection, not the selection you will actually see on screen when the menu appears. This makes building a custom context menu somewhat tricky. I suspect this is a bug and have reported it as such (FB23251873, with apologies to the engineers for the pleading tone in that report; it was at the end of a long week of getting my head around the gesture recogniser changes. :) ). But it occurs to me that there is nothing in the documentation that guarantees that selectedRanges will be accurate in menuForEvent:; it's just always worked this way. So am I missing something here? Is there a better or more reliable way of getting the range that will be affected by the contextual menu in NSTextView? (The delegate method only provides a single character index, which isn't enough information for spelling corrections and such which require a range.) My current workaround is to rebuild the context menu in setSelectedRanges:affinity:stillSelecting: if it is called between menuForEvent: and didCloseMenu:withEvent:.
Topic: UI Frameworks SubTopic: AppKit Tags:
Replies
2
Boosts
0
Views
60
Activity
4d
How do you correctly use a SwiftUI View inside an NSToolbarItem?
I've been struggling to get consistent UI and UX behaviour of SwiftUI Views inside NSToolbarItems and was wondering if there is an official way to use them. I've now revisited this issue in macOS 27 and continue to see some idiosyncrasies. In the attached screenshot, you can see that the highlight area on mouse down between to the two buttons is different. This is the easiest example I've come up with that shows SwiftUI Views exhibiting different behaviour than AppKit Views. Two questions: Is an NSHostingView a valid and supported view type for NSToolbarItem.view? If so, are there any rules that govern how the SwiftUI view should be configured? (ex: frame, sizing options, supported SwiftUI Views, preferred "root view" types, etc?) Sample code that created the two NSToolbarItem buttons in the screenshot. macOS 27 ZY21R0CMGL (Public Beta 1) Xcode 27.0 beta Minimum Deployment target: 27.0 // Left-Top SwiftUI Button (Clipped Highlighting) let item = NSToolbarItem(itemIdentifier: itemIdentifier) let rootView = Button { } label: { Image(systemName: "sidebar.trailing") } item.view = NSHostingView(rootView: rootView) // ... snip .. // Right-Bottom AppKit Button (Correct Highlighting) let item = NSToolbarItem(itemIdentifier: itemIdentifier) item.image = NSImage(systemSymbolName: "sidebar.trailing", accessibilityDescription: nil) Both screenshots are taken on mouse down.
Replies
2
Boosts
0
Views
78
Activity
4d
Annoying popup window in Xcode Previews when the initial controller of the main storyboard is a macOS window
I started a project targeting macOS and used Storyboard app lifecycle. I also used Xcode Previews in this project. If I: Keep the entry point of the main storyboard to a window controller. (as default setup in macOS), Turn the Xcode window into full-screen, That window controller would pop up its window every time Xcode Previews refreshes. I tested in Xcode 26.3 RC and many versions before.
Replies
7
Boosts
0
Views
316
Activity
1w
Quick Look Plugin for Mac and Internet Access
I'd like to create a Quick Look extension for a file type for which a location or region on a Map should be shown as preview. However the MapView would only show a grid without any map. From within the MapKit delegate I can see from the "Error" parameter (a server with this domain can not be found) that this seems to be a network issue. The Quick Look extension seems to have no access to the internet and therefore the MapView can not load any map data. I've then also done some other tests via URLSession, which also only fails with connection errors. I haven't seen any limitations or restrictions mentioned in the API documentation. Is this the expected behavior? Is this a bug? Or am I missing something?
Replies
6
Boosts
0
Views
529
Activity
1w
Are NSStatusItem Interactions Still Allowed?
We have a status item which works fine on macOS 26 and earlier, which has the following properties: Supports left-click to open main UI (a popover) Supports left-click (while open) to toggle (close) the main UI Supports right-click to show "app" menu (e.g. About, Quit) Supports a drop destination to accept files and folders, which then triggers the main UI for more interaction In macOS 27: left-click seems ok if we use expanded interface session, but otherwise broken left-click while open no longer toggles (event is missing?) right click is no longer operational, to the point that it seems the Menu Bar doesn't forward the event at all. Other (Apple-provided) items work fine, and expose new context menus Dragging now triggers Mission Control, which seems wrong given the destination was in the Menu Bar (FB23018381). Are these interactions now forbidden, and are there lists or documentation of the new rules? As an additional bug, it looks like popovers don't pick up appearance changes. The child scroll view claims to be in light appearance in the View Debugger, but is clearly showing the wrong background color, this is a new (as-yet unreported) issue. One last bug: expanded interface session seems to suppress the popover's animation when shown.
Topic: UI Frameworks SubTopic: AppKit Tags:
Replies
7
Boosts
1
Views
155
Activity
1w
[NSWorkspace desktopImageOptionsForScreen:] does not return key "Show on all spaces"
It seems this method is not updated for the new "Show on all Spaces" option in system wallpaper preferences. I encounter this problem because one customer reported that every time my app sets a new wallpaper, this option is turned off. NSDictionary* options = [SHARED_WORKSPACE desktopImageOptionsForScreen:screen]; [SHARED_WORKSPACE setDesktopImageURL:imageFileURL forScreen:screen options:options error:&error]; This can be easily verified by dumping the returned dictionary - which only contains 3 keys. Is this a known bug?
Replies
1
Boosts
0
Views
160
Activity
1w
NSTokenField - How To Tell If I'm Editing an Existing Token in -tokenField:representedObjectForEditingString: ?
I'm trying to use NSTokenField for the first time. So my custom 'representedObject' for a token has additional model data tied to it (not just the editing/display string). I noticed when I edit an existing token, type text, and hit the enter key I get the following delegate callback: - (nullable id)tokenField:(NSTokenField *)tokenField representedObjectForEditingString:(NSString *)editingString; This same delegate method is called when I type a brand new token. Is there a way to distinguish if I'm editing a token vs. creating a new one? My expectation is to be able to do something like this (made up enhancement): - (nullable id)tokenField:(NSTokenField *)tokenField representedObjectForEditingString:(NSString *)editingString atIndex:(NSUInteger)existingTokenIndex { if (existingTokenIndex == NSNotFound) { // Token is new, create a new instance MyTokenObject *newToken = //create and configure. return newToken; } else { // This would update the editing string but wouldn't discard existing data held by the token. MyTokenObject *tokenObj = [self existingTokenAtIndex:existingTokenIndex]; tokenObj.editingString = editingString; return tokenObj; } }
Replies
2
Boosts
0
Views
170
Activity
1w
How do I get SwiftUI to let me determine a custom frame size for NSTextField
I have a NSViewRepresentable that wraps an NSTextField subclass which is displayed as larger than your typical text field. SwiftUI doesn't seem to allow me to set the size of the view when the underlying is an NSTextField. It forces it as a single line field. I've tried both setting the frame on creation as well as using SwiftUI .frame(width:height:) on the represented view. I always end up with a single line field. struct BigTextField: NSViewRepresentable { @Binding var text: String class Coordinator: NSObject, NSTextFieldDelegate { var parent: BigTextField init(_ parent: BigTextField) { self.parent = parent } func controlTextDidChange(_ obj: Notification) { if let textField = obj.object as? NSTextField { parent.text = textField.stringValue } } } func makeCoordinator() -> Coordinator { Coordinator(self) } func makeNSView(context: Context) -> NSTextField { //let frame = NSRect(x: 0, y: 0, width: 350, height: 140) //let textField = NSTextField(frame: frame) let textField = NSTextField() textField.isEditable = true textField.isBordered = true textField.isBezeled = true textField.delegate = context.coordinator // Assign the coordinator return textField } func updateNSView(_ nsView: NSTextField, context: Context) { if nsView.stringValue != text { nsView.stringValue = text } } } I've also included the SwiftUI declaration which demonstrates the problem. struct ContentView: View { @State var text : String = "Test string" var body: some View { VStack { BigTextField(text: $text) .frame(width: 350, height: 140) } .padding() } } NSTextField can be any arbitrary frame size. I already do this from AppKit but am trying to adapt this custom field to work within SwiftUI. SwiftUI seems to override the sizing of this NSViewRepresentable that I give it. Am I missing something here? Is there some way to override SwiftUI's sizing behavior? Thank you.
Replies
0
Boosts
0
Views
90
Activity
1w
Am I disallowed to use Glass in the Dock in any means?
I tried Glass in NSApp.dockTile.contentView. Any Glass there isn't shown like it normally is in windows. Does this limitation exist intentionally?
Replies
1
Boosts
0
Views
66
Activity
1w
TextKit 2 + SwiftUI (NSViewRepresentable): NSTextLayoutManager rendering attributes don’t reliably draw/update
I’m embedding an NSTextView (TextKit 2) inside a SwiftUI app using NSViewRepresentable. I’m trying to highlight dynamic subranges (changing as the user types) by providing per-range rendering attributes via NSTextLayoutManager’s rendering-attributes mechanism. The issue: the highlight is unreliable. Often, the highlight doesn’t appear at all even though the delegate/data source is returning attributes for the expected range. Sometimes it appears once, but then it stops updating even when the underlying “highlight range” changes. This feels related to SwiftUI - AppKit layout issue when using NSViewRepresentable (as said in https://developer.apple.com/documentation/swiftui/nsviewrepresentable). What I’ve tried Updating the state that drives the highlight range and invalidating layout fragments / asking for relayout Ensuring all updates happen on the main thread. Calling setNeedsDisplay(_:) on the NSViewRepresentable’s underlying view. Toggling the SwiftUI view identity (e.g. .id(...)) to force reconstruction (works, but too expensive / loses state). Question In a SwiftUI + NSViewRepresentable setup with TextKit 2, what is the correct way to make NSTextLayoutManager re-query and redraw rendering attributes when my highlight ranges change? Is there a recommended invalidation call for TextKit 2 to trigger re-rendering of rendering attributes? Or is this a known limitation when hosting NSTextView inside SwiftUI, where rendering attributes aren’t reliably invalidated? If this approach is fragile, is there a better pattern for dynamic highlights that avoids mutating the attributed string (to prevent layout/scroll jitter)?
Replies
4
Boosts
0
Views
464
Activity
1w
Debugging multi-window AppKit apps: Identifying the window associated with a breakpoint
When working on a multi-window AppKit app, how do you identify which window instance is associated with the current breakpoint? The same question applies when using LLDB. If execution stops inside an object that can exist in more than one window, such as a shared NSViewController subclass, how do you know which window’s object you are currently inspecting? Does Xcode provide a mechanism for showing the NSWindow associated with the current view, view controller or responder while debugging? My current approach is to print object identities and compare them manually. For example, if several identical windows are open, I might print the current object and its window: print(self, #function) Then I interact with one window, make a note of the printed memory addresses in the console, switch to another window and compare the output. This works, but it feels manual. I am not dealing with different window subclasses. The windows may be instances of the same class and may contain instances of the same view controller classes. I simply want an easier way to distinguish which window instance I am debugging. Is there a recommended Xcode, LLDB or AppKit workflow for this?
Replies
1
Boosts
0
Views
156
Activity
1w
How to dynamically update an existing AVComposition when users add a new custom video clip?
I’m building a macOS video editor that uses AVComposition and AVVideoComposition. Initially, my renderer creates a composition with some default video/audio tracks: @Published var composition: AVComposition? @Published var videoComposition: AVVideoComposition? @Published var playerItem: AVPlayerItem? Then I call a buildComposition() function that inserts all the default video segments. Later in the editing workflow, the user may choose to add their own custom video clip. For this I have a function like: private func handlePickedVideo(_ url: URL) { guard url.startAccessingSecurityScopedResource() else { print("Failed to access security-scoped resource") return } let asset = AVURLAsset(url: url) let videoTracks = asset.tracks(withMediaType: .video) guard let firstVideoTrack = videoTracks.first else { print("No video track found") url.stopAccessingSecurityScopedResource() return } renderer.insertUserVideoTrack(from: asset, track: firstVideoTrack) url.stopAccessingSecurityScopedResource() } What I want to achieve is the same behavior professional video editors provide, after the composition has already been initialized and built, the user should be able to add a new video track and the composition should update live, meaning the preview player should immediately reflect the changes without rebuilding everything from scratch manually. How can I structure my AVComposition / AVMutableComposition and my rendering pipeline so that adding a new clip later updates the existing composition in real time (similar to Final Cut/Adobe Premiere), instead of needing to rebuild everything from zero? You can find a playable version of this entire setup at :- https://github.com/zaidbren/SimpleEditor
Replies
1
Boosts
0
Views
543
Activity
2w
Remove MacOS Tahoe Sidebar + Inspector Chrome
Is it possible to remove the ugly sidebar and inspector chrome with AppKit? I don't care if it's a hack or a swizzle or something, but I need to get rid of this. I want to convert this: Into this (photoshopped): Thanks for your help!
Topic: UI Frameworks SubTopic: AppKit Tags:
Replies
1
Boosts
1
Views
426
Activity
2w