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

[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
431
Jun ’26
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
382
Jun ’26
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
184
Jun ’26
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
622
Jun ’26
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
463
Jun ’26
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
732
Jun ’26
NSTextView -cleanUpAfterDragOperation Being Called When Dragging Session Is Not Finished
I have an NSTextView subclass and implements drag and drop for custom draggable data, so I override -writablePasteboardTypes and add my own type as described in the header file: // Returns an array of pasteboard types that can be provided from the current selection. Overriders should copy the result from super and add their own new types. @property (readonly, copy) NSArray<NSPasteboardType> *writablePasteboardTypes; Now my textview also accepts the drop. Drag and drop can be used to move the custom data to a different location in the text view's character range. Like grabbing a block of text and moving it. So I accept the drop in -readSelectionFromPasteboard:type: I have a variable I cache at the start of dragging like: _myDraggingItem = // Set at the start of dragging. Then when I accept the drop I just use _myDraggingItem to move it to the drop location in the text view. I don't need to actually serialize the entire object and write it on the pasteboard I can just use _myDraggingItem to move from the source location to destination location. This is local only drag and drop. it works, except when the mouse leaves the text view briefly during the dragging session. This is because I override NSTextView's - (void)cleanUpAfterDragOperation // If you set up persistent state that should go away when the drag operation finishes, you can clean it up here. Such state is usually set up in -dragOperationForDraggingInfo:type:. You should probably never need to call this except to message super in an override. - (void)cleanUpAfterDragOperation; So documentation indicates -cleanUpAfterDragOperation is for clean up after drag operation finishes so I nil out _myDraggingItem here. But -cleanUpAfterDragOperation is getting called from [NSDragDestination _draggingExited]. -draggingExited: means the drag location moved outside the view it does not mean that the dragging session is over. The drag can move back inside the view after briefly exiting, so this isn't a usable place to clean up state tied to the dragging session as the header file indicates. I must override -draggingEnded: instead. If that sounds like a bug let me know.
1
0
159
Jun ’26
macOS 26: titlebar accessory can visually cover sidebar content with Reduce Transparency enabled
I’m seeing a macOS 26 AppKit issue with a sidebar + full-size content window + titlebar accessory setup. The main problem is that an NSTitlebarAccessoryViewController can visually cover the first item in the sidebar when System Settings > Accessibility > Display > Reduce Transparency is enabled. In my app this made the first sidebar/menu item look blacked out/covered by the titlebar/accessory area. While investigating possible workarounds, I also compared NSTitlebarAccessoryViewController with NSSplitViewItemAccessoryViewController and found two related issues that make the split-view accessory hard to use as a replacement. I could not attach the full sample project directly, so I included the two relevant Swift files below. The screenshots were taken from the same minimal AppKit repro with Reduce Transparency enabled. Repro setup The sample project shows: a fixed-width sidebar one content pane using NSTitlebarAccessoryViewController one content pane using NSSplitViewItemAccessoryViewController both accessories use the same custom view both custom views request the same intrinsic height each accessory displays its requested and actual height main.swift AppDelegate.swift Issue 1: titlebar accessory can cover sidebar content With Reduce Transparency enabled, the titlebar/accessory area can visually cover content at the top of the sidebar. This is the original issue I’m trying to solve. Expected: the sidebar content should not be covered by the titlebar accessory/material. Actual: the top sidebar item can appear blacked out/covered. In the first attached screenshot, "First sidebar row" is hidden/covered while "Second row" and the following rows are still visible. Issue 2: split-view accessory does not get the same hard separator As a possible workaround, I tried using NSSplitViewItemAccessoryViewController instead of NSTitlebarAccessoryViewController. Both controllers are configured with: if #available(macOS 26.1, *) { accessory.preferredScrollEdgeEffectStyle = .hard } The titlebar accessory shows the expected hard boundary/separator behavior, but the split-view item accessory does not appear to get the same hard edge treatment. The second attached screenshot shows the workaround comparison between the titlebar accessory and the split-view accessory. Expected: preferredScrollEdgeEffectStyle = .hard should produce a comparable hard separator for the split-view accessory. Actual: the split-view accessory still looks visually different and does not show the same hard boundary. Issue 3: split-view accessory is inset differently The NSSplitViewItemAccessoryViewController also appears to be laid out with spacing/insets around it. In the repro, the accessory custom view has a faint red background. Both accessory views request and receive the same height: requested 36 pt, actual 36.0 pt So the mismatch does not seem to be caused by the accessory view’s own intrinsic height. Instead, the split-view accessory appears to be hosted inside an inset container, with spacing around it, while the titlebar accessory is flush with the titlebar/content edge. Expected: if both accessories host the same view with the same intrinsic height, their effective placement should be comparable, or there should be a documented way to remove/control the split accessory insets. Actual: the split-view accessory is visually inset on multiple sides, making it unsuitable as a drop-in workaround for the titlebar accessory issue. The second attached screenshot also shows this: the split-view accessory has the same requested and actual height as the titlebar accessory, but it is still visually inset and does not align the same way. Question Is this expected behavior on macOS 26, especially with Reduce Transparency enabled? If so, what is the recommended AppKit approach for placing a filter/search accessory below the toolbar/titlebar without covering sidebar content, while still getting a hard separator and predictable layout?
Topic: UI Frameworks SubTopic: AppKit Tags:
1
0
394
May ’26
Challenges using SwiftUI views inside an NSToolbarItem
I'm trying to use SwiftUI views inside an NSToolbarItem, and I feel like I'm fighting the system. The goal is to create custom toolbar controls. I don't want AppKit or SwiftUI to recognize that there's a SwiftUI view in the toolbar and then try to style it automatically, which is what I think is happening. Consider this hierarchy: - NSToolbar - NSToolbarItem - view -> MyCustomNSView - addSubview(NSHostingView<CustomView>) So CustomView is inside an NSHostingView, which is inside an NSView, which is assigned to the .view property of an NSToolbarItem. For a while, I struggled to get this working at all because SwiftUI's layout metrics appeared to be affected by safe area insets. SwiftUI's ignoresSafeArea() only seemed to move the problem around. For now, I've disabled full-size content view, which I don't really need anyway. However, a SwiftUI Button or Menu still doesn't behave or style the way I would expect when placed inside an NSToolbarItem. They don't seem to honor many of the styling attributes or view modifiers that work elsewhere. Is there a way to tell AppKit to "ignore" the children of my NSToolbarItem and not apply toolbar-specific styling to them? Am I even correct in thinking that AppKit is recognizing a Button or Menu in the toolbar and forcibly applying styling to it? Previously, I tried implementing my "custom toolbar" entirely outside of NSToolbar, but then SwiftUI struggled with placing views under the transparent, non-existent toolbar. I'd appreciate any direction or hints here. It would be really nice to use SwiftUI for the controls I have in mind, but at the moment I can't get close to the result I'm aiming for.
0
0
254
May ’26
How do I get content to blur behind a floating input bar, like Mail, Messages and other native apps do?
I have a chat app with a floating composer pill (NSGlassEffectView) pinned to the bottom of my content area. Messages scroll behind it. The pill looks fine but content behind it is completely clear. Fully legible text showing through, no frosting at all. Mail, Messages, Notes all have this frosted look where content behind a floating bar is blurred enough that you can't read it. That's what I'm going for. My scroll view has wantsLayer = true. I tried hasVerticalScroller = true + scrollerStyle = .overlay based on a tip I saw in another thread. No change. Is NSGlassEffectView supposed to blur what's behind it, or is the frosting in Apple's apps coming from the scroll edge effect? If it's the scroll edge effect, is there any way to trigger it for a custom floating view at the bottom of a scroll view? I can't find any AppKit API for this. I also spent time trying this in SwiftUI using .glassEffect() on macOS. Same result, the material renders nearly clear with no way to control the frosting level via any public API. If I'm missing something obvious I'd love to know. I've been stuck on this one for a while. Thanks for any advice! I've attached photos of my input bar (clearly transparent) and Apple Messages, which has a style that I see all over iOS and Mac OS 26.
0
0
505
May ’26
NSTextView.shouldDrawInsertionPoint doesn't work with TextKit 2
The following code only ever causes shouldDrawInsertionPoint to be printed (no drawInsertionPoint), but even if that method returns false, the blinking insertion point is still drawn. On the other hand, with TextKit 1 it works as expected. Is there a way to hide the default insertion point in TextKit 2? My app draws its own. I've filed FB13684251. class TextView: NSTextView { override var shouldDrawInsertionPoint: Bool { print("shouldDrawInsertionPoint") return false } override func drawInsertionPoint(in rect: NSRect, color: NSColor, turnedOn flag: Bool) { print("drawInsertionPoint", flag) } } ``
Topic: UI Frameworks SubTopic: AppKit Tags:
11
0
851
May ’26
AppKit & State Restoration: Windows Auto Closing On App Quit Breaks State Restoration
I probably should know the answer to this but I don't, so I'll ask. When I enable state restoration and have like three windows open, and I quit the app (via Quit menu, not 'Stop In Xcode') the following happens: -NSApplication calls _closeForTermination on all the windows and this causes state restoration to fail to restore these open windows on next app launch. This behavior is not aligned with the behavior of apps like Mail. If I have two "Viewer Windows" open in Mail and I quit the app, when I relaunch the two viewer windows are restored. I can of course track this and write data to restore for these auto closed window myself but shouldn't there be an easy way to opt in to this behavior?
1
0
343
May ’26
After binding to NSBrowser indexPaths the browser assumes I'm using NSBrowserCell and calls unimplemented methods on my NSCell subclass
So after binding to NSBrowser selectionIndexPaths: https://developer.apple.com/library/archive/documentation/Cocoa/Reference/CocoaBindingsRef/BindingsText/NSBrowser.html this causes NSBrowser to do some weird stuff that seems completely unrelated to this particular binding. It starts calling NSBrowserCell methods on my cells but my cell is not a NSBrowserCell. My cell is actually a subclass of NSTextFieldCell. But NSBrowser starts sending setIsLeaf: (which I don't implement). In any case if I implement the -setLeaf: that solves that unrecognized selector, but now my cells don't draw titles. Not sure why binding to selectionIndexPaths causes this behavior? The cell stuff seems unrelated to this particular binding. I am of course using the newer but still pretty old item based APIs... do these bindings only support using NSMatrix? I do set the binding after calling -setCellClass: but makes no difference. I also just tried overriding -setSelectionIndexPaths: but NSBrowser does not use the setter.
2
0
404
May ’26
Overlay window above all windows, even when moving spaces
Hi! I would like to overlay a macOS application window above all windows, even when moving spaces or moving to a fullscreen app, similar in function to the DropOver app for macOS. What I have tried: Overwriting the default app delegate in SwiftUI and creating the NSWindow myself. Then setting the window.collectionBehavior to [.canJoinAllApplications, .canJoinAllSpaces, .fullScreenAuxiliary] and the window.level to .floating or .statusBar. This works for moving between Spaces, but still does not display above apps in fullscreen mode. I also registered a notification observer for NSWorkspace.activeSpaceDidChangeNotification, where I call window.orderFrontRegardless() to always have my window frontmost. Still not displaying above fullscreen apps. What am I missing to make this work? Best regards
2
0
485
May ’26
How do I make an editable NSTextField wrap inside an NSTableView cell?
Hi, I’m pretty new to AppKit and I’m trying to make an NSTextField inside an NSTableView both: Editable Multi-line / wrapping Right now, wrapping works fine until I set: tf.isEditable = true Then the text becomes a single line. How do I make it editable while still wrapping correctly? import AppKit final class ViewController: NSViewController, NSTableViewDataSource, NSTableViewDelegate { let tableView = NSTableView() let text = String(repeating: "A", count: 500) override func viewDidLoad() { super.viewDidLoad() view = tableView tableView.addTableColumn(NSTableColumn()) tableView.usesAutomaticRowHeights = true tableView.dataSource = self tableView.delegate = self } func numberOfRows(in tableView: NSTableView) -> Int { 1 } func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? { let cell = NSTableCellView() let tf = NSTextField(wrappingLabelWithString: text) tf.lineBreakMode = .byCharWrapping if let tableColumn { tf.preferredMaxLayoutWidth = tableColumn.width } tf.isEditable = true // comment this out and wrapping works cell.addSubview(tf) tf.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ tf.leadingAnchor.constraint(equalTo: cell.leadingAnchor), tf.trailingAnchor.constraint(equalTo: cell.trailingAnchor), tf.topAnchor.constraint(equalTo: cell.topAnchor), tf.bottomAnchor.constraint(equalTo: cell.bottomAnchor), ]) return cell } }
4
0
508
May ’26
SwiftUI + AppKit context menu wedges window-level mouse events when the menu's anchor view is deleted by the menu's own action
I'm on macOS 26.4 (SwiftUI + SwiftData + AppKit bridging). I have a SwiftUI canvas where each child view (a card) carries a per-card AppKit context menu via an NSViewRepresentable overlay (a small NSView subclass that overrides menu(for:) and returns an NSMenu whose items invoke a Swift closure). The closure for the "Delete" item removes the underlying model object. SwiftData mutates → SwiftUI re-emits the canvas → the card containing the menu's anchor NSView unmounts → that anchor NSView is removed from the AppKit view hierarchy. After this happens, the entire window's SwiftUI gestures stop receiving mouse events: pan, zoom, taps on a separate background Color view all go silent. The window's first responder ends up at the NSWindow itself. The wedge persists across switching to a sibling SwiftUI view in the same window (different SwiftData root), so the bad state is at the window/event-routing level, not in any one SwiftUI subtree. The wedge is reliably cleared by another right-click that successfully shows + dismisses any menu — strongly suggesting AppKit's menu/event-tracking cleanup is left in a half-finished state because the anchor view went away during the cleanup window. I've already verified: Switching from explicit NSMenu.popUpContextMenu(_:with:for:) to overriding menu(for:) does not change the behavior. Deferring the model deletion via DispatchQueue.main.async, asyncAfter (30 ms), or RunLoop.main.perform(inModes: [.default]) either doesn't help or only avoids the wedge if the delay is long enough to be perceptible (seconds), implying the cleanup window is event-driven, not time-driven. Triggering the same deletion from a SwiftUI Button (no AppKit menu involved) never wedges. My current understanding is that the standard AppKit pattern (e.g., NSTableView, NSOutlineView) attaches the context menu to a stable parent view, never to the per-row view itself, precisely so the menu's anchor outlives any single row's deletion. Restructuring my code so a single canvas-level AppKitContextMenuRegion returns the appropriate menu via hit-testing in menu(for:) should avoid the issue, but I'd like to confirm: Is the assumption that an NSMenu's anchor view must outlive the menu's tracking-end cleanup documented anywhere, or is it implicit? Is there a supported way to safely use a per-row anchor view that gets deleted by the menu's own action, or is the canvas-level / parent-level menu attachment the only correct pattern? 3. Are there any post-tracking notifications or APIs that guarantee AppKit's cleanup is complete before the anchor view is allowed to be torn down (so a per-row anchor could be made safe with the right ordering)? Thanks!
0
0
486
May ’26
NSCollectionView's 'selection box' freezes if you right-click during dragging
So in NSCollectionView I left click the background and start dragging to make the 'selection box' (is that what we call it?) I have a mouse with separate left and right click buttons (i.e., not an Apple Magic Mouse). Now if I accidentally hit the right click while I'm still dragging the selection box..... the right click context menu shows up in the middle of mouse dragging and the selection box freezes on screen. Besides the visual disruption this sometimes results in weird behavior. Sometimes mouse clicks stop responding for awhile in the window and I gotta click around a bunch of times until I guess the run loop "unclogs." I'm able to reproduce in Finder Icon view so it isn't just me. Steps to Reproduce: A mouse with separate buttons for left and right click. Open Finder window in icon view. Left click the background and start dragging to make the gray selection box. While dragging the mouse as you are selecting click right-click in the middle of the drag. The selection box freezes on screen. Expected Behavior: -Right click event and left mouse drag event normally shouldn't overlap. If left mouse is being dragged the right click event should be blocked. Let me know if this is Feedback worthy.
5
0
456
May ’26
[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
431
Activity
Jun ’26
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
382
Activity
Jun ’26
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
184
Activity
Jun ’26
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
282
Activity
Jun ’26
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
622
Activity
Jun ’26
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
463
Activity
Jun ’26
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
732
Activity
Jun ’26
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
524
Activity
Jun ’26
NSTextView -cleanUpAfterDragOperation Being Called When Dragging Session Is Not Finished
I have an NSTextView subclass and implements drag and drop for custom draggable data, so I override -writablePasteboardTypes and add my own type as described in the header file: // Returns an array of pasteboard types that can be provided from the current selection. Overriders should copy the result from super and add their own new types. @property (readonly, copy) NSArray<NSPasteboardType> *writablePasteboardTypes; Now my textview also accepts the drop. Drag and drop can be used to move the custom data to a different location in the text view's character range. Like grabbing a block of text and moving it. So I accept the drop in -readSelectionFromPasteboard:type: I have a variable I cache at the start of dragging like: _myDraggingItem = // Set at the start of dragging. Then when I accept the drop I just use _myDraggingItem to move it to the drop location in the text view. I don't need to actually serialize the entire object and write it on the pasteboard I can just use _myDraggingItem to move from the source location to destination location. This is local only drag and drop. it works, except when the mouse leaves the text view briefly during the dragging session. This is because I override NSTextView's - (void)cleanUpAfterDragOperation // If you set up persistent state that should go away when the drag operation finishes, you can clean it up here. Such state is usually set up in -dragOperationForDraggingInfo:type:. You should probably never need to call this except to message super in an override. - (void)cleanUpAfterDragOperation; So documentation indicates -cleanUpAfterDragOperation is for clean up after drag operation finishes so I nil out _myDraggingItem here. But -cleanUpAfterDragOperation is getting called from [NSDragDestination _draggingExited]. -draggingExited: means the drag location moved outside the view it does not mean that the dragging session is over. The drag can move back inside the view after briefly exiting, so this isn't a usable place to clean up state tied to the dragging session as the header file indicates. I must override -draggingEnded: instead. If that sounds like a bug let me know.
Replies
1
Boosts
0
Views
159
Activity
Jun ’26
macOS 26: titlebar accessory can visually cover sidebar content with Reduce Transparency enabled
I’m seeing a macOS 26 AppKit issue with a sidebar + full-size content window + titlebar accessory setup. The main problem is that an NSTitlebarAccessoryViewController can visually cover the first item in the sidebar when System Settings > Accessibility > Display > Reduce Transparency is enabled. In my app this made the first sidebar/menu item look blacked out/covered by the titlebar/accessory area. While investigating possible workarounds, I also compared NSTitlebarAccessoryViewController with NSSplitViewItemAccessoryViewController and found two related issues that make the split-view accessory hard to use as a replacement. I could not attach the full sample project directly, so I included the two relevant Swift files below. The screenshots were taken from the same minimal AppKit repro with Reduce Transparency enabled. Repro setup The sample project shows: a fixed-width sidebar one content pane using NSTitlebarAccessoryViewController one content pane using NSSplitViewItemAccessoryViewController both accessories use the same custom view both custom views request the same intrinsic height each accessory displays its requested and actual height main.swift AppDelegate.swift Issue 1: titlebar accessory can cover sidebar content With Reduce Transparency enabled, the titlebar/accessory area can visually cover content at the top of the sidebar. This is the original issue I’m trying to solve. Expected: the sidebar content should not be covered by the titlebar accessory/material. Actual: the top sidebar item can appear blacked out/covered. In the first attached screenshot, "First sidebar row" is hidden/covered while "Second row" and the following rows are still visible. Issue 2: split-view accessory does not get the same hard separator As a possible workaround, I tried using NSSplitViewItemAccessoryViewController instead of NSTitlebarAccessoryViewController. Both controllers are configured with: if #available(macOS 26.1, *) { accessory.preferredScrollEdgeEffectStyle = .hard } The titlebar accessory shows the expected hard boundary/separator behavior, but the split-view item accessory does not appear to get the same hard edge treatment. The second attached screenshot shows the workaround comparison between the titlebar accessory and the split-view accessory. Expected: preferredScrollEdgeEffectStyle = .hard should produce a comparable hard separator for the split-view accessory. Actual: the split-view accessory still looks visually different and does not show the same hard boundary. Issue 3: split-view accessory is inset differently The NSSplitViewItemAccessoryViewController also appears to be laid out with spacing/insets around it. In the repro, the accessory custom view has a faint red background. Both accessory views request and receive the same height: requested 36 pt, actual 36.0 pt So the mismatch does not seem to be caused by the accessory view’s own intrinsic height. Instead, the split-view accessory appears to be hosted inside an inset container, with spacing around it, while the titlebar accessory is flush with the titlebar/content edge. Expected: if both accessories host the same view with the same intrinsic height, their effective placement should be comparable, or there should be a documented way to remove/control the split accessory insets. Actual: the split-view accessory is visually inset on multiple sides, making it unsuitable as a drop-in workaround for the titlebar accessory issue. The second attached screenshot also shows this: the split-view accessory has the same requested and actual height as the titlebar accessory, but it is still visually inset and does not align the same way. Question Is this expected behavior on macOS 26, especially with Reduce Transparency enabled? If so, what is the recommended AppKit approach for placing a filter/search accessory below the toolbar/titlebar without covering sidebar content, while still getting a hard separator and predictable layout?
Topic: UI Frameworks SubTopic: AppKit Tags:
Replies
1
Boosts
0
Views
394
Activity
May ’26
Challenges using SwiftUI views inside an NSToolbarItem
I'm trying to use SwiftUI views inside an NSToolbarItem, and I feel like I'm fighting the system. The goal is to create custom toolbar controls. I don't want AppKit or SwiftUI to recognize that there's a SwiftUI view in the toolbar and then try to style it automatically, which is what I think is happening. Consider this hierarchy: - NSToolbar - NSToolbarItem - view -> MyCustomNSView - addSubview(NSHostingView<CustomView>) So CustomView is inside an NSHostingView, which is inside an NSView, which is assigned to the .view property of an NSToolbarItem. For a while, I struggled to get this working at all because SwiftUI's layout metrics appeared to be affected by safe area insets. SwiftUI's ignoresSafeArea() only seemed to move the problem around. For now, I've disabled full-size content view, which I don't really need anyway. However, a SwiftUI Button or Menu still doesn't behave or style the way I would expect when placed inside an NSToolbarItem. They don't seem to honor many of the styling attributes or view modifiers that work elsewhere. Is there a way to tell AppKit to "ignore" the children of my NSToolbarItem and not apply toolbar-specific styling to them? Am I even correct in thinking that AppKit is recognizing a Button or Menu in the toolbar and forcibly applying styling to it? Previously, I tried implementing my "custom toolbar" entirely outside of NSToolbar, but then SwiftUI struggled with placing views under the transparent, non-existent toolbar. I'd appreciate any direction or hints here. It would be really nice to use SwiftUI for the controls I have in mind, but at the moment I can't get close to the result I'm aiming for.
Replies
0
Boosts
0
Views
254
Activity
May ’26
How do I get content to blur behind a floating input bar, like Mail, Messages and other native apps do?
I have a chat app with a floating composer pill (NSGlassEffectView) pinned to the bottom of my content area. Messages scroll behind it. The pill looks fine but content behind it is completely clear. Fully legible text showing through, no frosting at all. Mail, Messages, Notes all have this frosted look where content behind a floating bar is blurred enough that you can't read it. That's what I'm going for. My scroll view has wantsLayer = true. I tried hasVerticalScroller = true + scrollerStyle = .overlay based on a tip I saw in another thread. No change. Is NSGlassEffectView supposed to blur what's behind it, or is the frosting in Apple's apps coming from the scroll edge effect? If it's the scroll edge effect, is there any way to trigger it for a custom floating view at the bottom of a scroll view? I can't find any AppKit API for this. I also spent time trying this in SwiftUI using .glassEffect() on macOS. Same result, the material renders nearly clear with no way to control the frosting level via any public API. If I'm missing something obvious I'd love to know. I've been stuck on this one for a while. Thanks for any advice! I've attached photos of my input bar (clearly transparent) and Apple Messages, which has a style that I see all over iOS and Mac OS 26.
Replies
0
Boosts
0
Views
505
Activity
May ’26
NSTextView.shouldDrawInsertionPoint doesn't work with TextKit 2
The following code only ever causes shouldDrawInsertionPoint to be printed (no drawInsertionPoint), but even if that method returns false, the blinking insertion point is still drawn. On the other hand, with TextKit 1 it works as expected. Is there a way to hide the default insertion point in TextKit 2? My app draws its own. I've filed FB13684251. class TextView: NSTextView { override var shouldDrawInsertionPoint: Bool { print("shouldDrawInsertionPoint") return false } override func drawInsertionPoint(in rect: NSRect, color: NSColor, turnedOn flag: Bool) { print("drawInsertionPoint", flag) } } ``
Topic: UI Frameworks SubTopic: AppKit Tags:
Replies
11
Boosts
0
Views
851
Activity
May ’26
AppKit & State Restoration: Windows Auto Closing On App Quit Breaks State Restoration
I probably should know the answer to this but I don't, so I'll ask. When I enable state restoration and have like three windows open, and I quit the app (via Quit menu, not 'Stop In Xcode') the following happens: -NSApplication calls _closeForTermination on all the windows and this causes state restoration to fail to restore these open windows on next app launch. This behavior is not aligned with the behavior of apps like Mail. If I have two "Viewer Windows" open in Mail and I quit the app, when I relaunch the two viewer windows are restored. I can of course track this and write data to restore for these auto closed window myself but shouldn't there be an easy way to opt in to this behavior?
Replies
1
Boosts
0
Views
343
Activity
May ’26
After binding to NSBrowser indexPaths the browser assumes I'm using NSBrowserCell and calls unimplemented methods on my NSCell subclass
So after binding to NSBrowser selectionIndexPaths: https://developer.apple.com/library/archive/documentation/Cocoa/Reference/CocoaBindingsRef/BindingsText/NSBrowser.html this causes NSBrowser to do some weird stuff that seems completely unrelated to this particular binding. It starts calling NSBrowserCell methods on my cells but my cell is not a NSBrowserCell. My cell is actually a subclass of NSTextFieldCell. But NSBrowser starts sending setIsLeaf: (which I don't implement). In any case if I implement the -setLeaf: that solves that unrecognized selector, but now my cells don't draw titles. Not sure why binding to selectionIndexPaths causes this behavior? The cell stuff seems unrelated to this particular binding. I am of course using the newer but still pretty old item based APIs... do these bindings only support using NSMatrix? I do set the binding after calling -setCellClass: but makes no difference. I also just tried overriding -setSelectionIndexPaths: but NSBrowser does not use the setter.
Replies
2
Boosts
0
Views
404
Activity
May ’26
Overlay window above all windows, even when moving spaces
Hi! I would like to overlay a macOS application window above all windows, even when moving spaces or moving to a fullscreen app, similar in function to the DropOver app for macOS. What I have tried: Overwriting the default app delegate in SwiftUI and creating the NSWindow myself. Then setting the window.collectionBehavior to [.canJoinAllApplications, .canJoinAllSpaces, .fullScreenAuxiliary] and the window.level to .floating or .statusBar. This works for moving between Spaces, but still does not display above apps in fullscreen mode. I also registered a notification observer for NSWorkspace.activeSpaceDidChangeNotification, where I call window.orderFrontRegardless() to always have my window frontmost. Still not displaying above fullscreen apps. What am I missing to make this work? Best regards
Replies
2
Boosts
0
Views
485
Activity
May ’26
How do I make an editable NSTextField wrap inside an NSTableView cell?
Hi, I’m pretty new to AppKit and I’m trying to make an NSTextField inside an NSTableView both: Editable Multi-line / wrapping Right now, wrapping works fine until I set: tf.isEditable = true Then the text becomes a single line. How do I make it editable while still wrapping correctly? import AppKit final class ViewController: NSViewController, NSTableViewDataSource, NSTableViewDelegate { let tableView = NSTableView() let text = String(repeating: "A", count: 500) override func viewDidLoad() { super.viewDidLoad() view = tableView tableView.addTableColumn(NSTableColumn()) tableView.usesAutomaticRowHeights = true tableView.dataSource = self tableView.delegate = self } func numberOfRows(in tableView: NSTableView) -> Int { 1 } func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? { let cell = NSTableCellView() let tf = NSTextField(wrappingLabelWithString: text) tf.lineBreakMode = .byCharWrapping if let tableColumn { tf.preferredMaxLayoutWidth = tableColumn.width } tf.isEditable = true // comment this out and wrapping works cell.addSubview(tf) tf.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ tf.leadingAnchor.constraint(equalTo: cell.leadingAnchor), tf.trailingAnchor.constraint(equalTo: cell.trailingAnchor), tf.topAnchor.constraint(equalTo: cell.topAnchor), tf.bottomAnchor.constraint(equalTo: cell.bottomAnchor), ]) return cell } }
Replies
4
Boosts
0
Views
508
Activity
May ’26
SwiftUI + AppKit context menu wedges window-level mouse events when the menu's anchor view is deleted by the menu's own action
I'm on macOS 26.4 (SwiftUI + SwiftData + AppKit bridging). I have a SwiftUI canvas where each child view (a card) carries a per-card AppKit context menu via an NSViewRepresentable overlay (a small NSView subclass that overrides menu(for:) and returns an NSMenu whose items invoke a Swift closure). The closure for the "Delete" item removes the underlying model object. SwiftData mutates → SwiftUI re-emits the canvas → the card containing the menu's anchor NSView unmounts → that anchor NSView is removed from the AppKit view hierarchy. After this happens, the entire window's SwiftUI gestures stop receiving mouse events: pan, zoom, taps on a separate background Color view all go silent. The window's first responder ends up at the NSWindow itself. The wedge persists across switching to a sibling SwiftUI view in the same window (different SwiftData root), so the bad state is at the window/event-routing level, not in any one SwiftUI subtree. The wedge is reliably cleared by another right-click that successfully shows + dismisses any menu — strongly suggesting AppKit's menu/event-tracking cleanup is left in a half-finished state because the anchor view went away during the cleanup window. I've already verified: Switching from explicit NSMenu.popUpContextMenu(_:with:for:) to overriding menu(for:) does not change the behavior. Deferring the model deletion via DispatchQueue.main.async, asyncAfter (30 ms), or RunLoop.main.perform(inModes: [.default]) either doesn't help or only avoids the wedge if the delay is long enough to be perceptible (seconds), implying the cleanup window is event-driven, not time-driven. Triggering the same deletion from a SwiftUI Button (no AppKit menu involved) never wedges. My current understanding is that the standard AppKit pattern (e.g., NSTableView, NSOutlineView) attaches the context menu to a stable parent view, never to the per-row view itself, precisely so the menu's anchor outlives any single row's deletion. Restructuring my code so a single canvas-level AppKitContextMenuRegion returns the appropriate menu via hit-testing in menu(for:) should avoid the issue, but I'd like to confirm: Is the assumption that an NSMenu's anchor view must outlive the menu's tracking-end cleanup documented anywhere, or is it implicit? Is there a supported way to safely use a per-row anchor view that gets deleted by the menu's own action, or is the canvas-level / parent-level menu attachment the only correct pattern? 3. Are there any post-tracking notifications or APIs that guarantee AppKit's cleanup is complete before the anchor view is allowed to be torn down (so a per-row anchor could be made safe with the right ordering)? Thanks!
Replies
0
Boosts
0
Views
486
Activity
May ’26
NSCollectionView's 'selection box' freezes if you right-click during dragging
So in NSCollectionView I left click the background and start dragging to make the 'selection box' (is that what we call it?) I have a mouse with separate left and right click buttons (i.e., not an Apple Magic Mouse). Now if I accidentally hit the right click while I'm still dragging the selection box..... the right click context menu shows up in the middle of mouse dragging and the selection box freezes on screen. Besides the visual disruption this sometimes results in weird behavior. Sometimes mouse clicks stop responding for awhile in the window and I gotta click around a bunch of times until I guess the run loop "unclogs." I'm able to reproduce in Finder Icon view so it isn't just me. Steps to Reproduce: A mouse with separate buttons for left and right click. Open Finder window in icon view. Left click the background and start dragging to make the gray selection box. While dragging the mouse as you are selecting click right-click in the middle of the drag. The selection box freezes on screen. Expected Behavior: -Right click event and left mouse drag event normally shouldn't overlap. If left mouse is being dragged the right click event should be blocked. Let me know if this is Feedback worthy.
Replies
5
Boosts
0
Views
456
Activity
May ’26
.icon files and "imageNamed:"
Composer icons can be loaded with NSImage's imageNamed: but I haven't figured out how to make it load any variation other than the light style. Is this even possible? Thank you!
Replies
1
Boosts
0
Views
376
Activity
May ’26