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

Window title bar in macOS 26 is drawn even if titlebarAppearsTransparent = true
macOS 26 sometimes draws the title bar background even when setting NSWindow.titlebarAppearsTransparent = true and I don't understand the logic behind it, or how I can turn this off. I'm trying to do something similar to Xcode's "Welcome to Xcode" window which has a left view and a right table view. In my simplified example, the window contains a label and a text view. This used to work in macOS 15, but in macOS 26 the text view is partially covered by the title bar: As soon as I remove the line scrollView.hasVerticalScroller = true, the title bar isn't drawn anymore: The title bar also isn't drawn when removing the view on the left of the text view: I created FB20341654. This may be related to this other issue: NSWindow.titlebarAppearsTransparent only works after collapsing and expanding sidebar @main class AppDelegate: NSObject, NSApplicationDelegate { func applicationDidFinishLaunching(_ aNotification: Notification) { let window = NSWindow(contentViewController: ViewController()) window.titlebarAppearsTransparent = true window.titleVisibility = .hidden window.styleMask = [.titled, .closable, .fullSizeContentView] window.makeKeyAndOrderFront(nil) } } class ViewController: NSViewController { override func loadView() { view = NSView(frame: CGRect(x: 0, y: 0, width: 400, height: 200)) let scrollView = NSScrollView() scrollView.hasVerticalScroller = true // commenting this line out solves the issue scrollView.translatesAutoresizingMaskIntoConstraints = false scrollView.automaticallyAdjustsContentInsets = false let documentView = NSTextView() documentView.string = (0..<10).map({ "\($0)" }).joined(separator: "\n") scrollView.documentView = documentView let stack = NSStackView(views: [ NSTextField(labelWithString: "asdfasdfasdfasdf"), // commenting this line out also solves the issue scrollView ]) stack.orientation = .horizontal view.addSubview(stack) NSLayoutConstraint.activate([stack.topAnchor.constraint(equalTo: view.topAnchor), stack.leadingAnchor.constraint(equalTo: view.leadingAnchor), stack.trailingAnchor.constraint(equalTo: view.trailingAnchor), stack.bottomAnchor.constraint(equalTo: view.bottomAnchor)]) } }
Topic: UI Frameworks SubTopic: AppKit Tags:
2
0
252
Sep ’25
Did GCD change in macOS 26
Some users of my Mac app are complaining of redrawing delays. Based on what I see in logs, my GCD timer event handlers are not being run in a timely manner although the runloop is still pumping events: sometimes 500ms pass before a 15ms timer runs. During this time, many keypresses are routed through -[NSApplication sendEvent:], which is how I know it's not locked up in synchronous code. This issue has not been reported in older versions of macOS. I start the timer like this: _gcdUpdateTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue()); dispatch_source_set_timer(_gcdUpdateTimer, dispatch_time(DISPATCH_TIME_NOW, period * NSEC_PER_SEC), period * NSEC_PER_SEC, 0.0005 * NSEC_PER_SEC); dispatch_source_set_event_handler(_gcdUpdateTimer, ^{ …redraw… });
1
0
166
Sep ’25
Why isn't Liquid Glass effect applied when using pyobjc?
I can compile this #import <Cocoa/Cocoa.h> @interface AppDelegate : NSObject <NSApplicationDelegate> @property (strong) NSWindow *window; @property (strong) NSSlider *slider; @end @implementation AppDelegate - (void)applicationDidFinishLaunching:(NSNotification *)notification { // Window size NSRect frame = NSMakeRect(0, 0, 400, 300); NSUInteger style = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskResizable; self.window = [[NSWindow alloc] initWithContentRect:frame styleMask:style backing:NSBackingStoreBuffered defer:NO]; [self.window setTitle:@"Centered Slider Example"]; [self.window makeKeyAndOrderFront:nil]; // Slider size CGFloat sliderWidth = 200; CGFloat sliderHeight = 32; CGFloat windowWidth = self.window.frame.size.width; CGFloat windowHeight = self.window.frame.size.height; CGFloat sliderX = (windowWidth - sliderWidth) / 2; CGFloat sliderY = (windowHeight - sliderHeight) / 2; self.slider = [[NSSlider alloc] initWithFrame:NSMakeRect(sliderX, sliderY, sliderWidth, sliderHeight)]; [self.slider setMinValue:0]; [self.slider setMaxValue:100]; [self.slider setDoubleValue:50]; [self.window.contentView addSubview:self.slider]; } @end int main(int argc, const char * argv[]) { @autoreleasepool { NSApplication *app = [NSApplication sharedApplication]; AppDelegate *delegate = [[AppDelegate alloc] init]; [app setDelegate:delegate]; [app run]; } return 0; } with (base) johnzhou@Johns-MacBook-Pro liquidglasstest % clang -framework Foundation -framework AppKit testobjc.m and get this neat liquid glass effect: https://github.com/user-attachments/assets/4199493b-6011-4ad0-9c9f-25db8585e547 However if I use pyobjc to make an equivalent import sys from Cocoa import ( NSApplication, NSApp, NSWindow, NSSlider, NSMakeRect, NSWindowStyleMaskTitled, NSWindowStyleMaskClosable, NSWindowStyleMaskResizable, NSBackingStoreBuffered, NSObject ) class AppDelegate(NSObject): def applicationDidFinishLaunching_(self, notification): # Create the main window window_size = NSMakeRect(0, 0, 400, 300) style = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskResizable self.window = NSWindow.alloc().initWithContentRect_styleMask_backing_defer_( window_size, style, NSBackingStoreBuffered, False ) self.window.setTitle_("Centered Slider Example") self.window.makeKeyAndOrderFront_(None) # Slider size and positioning slider_width = 200 slider_height = 32 window_width = self.window.frame().size.width window_height = self.window.frame().size.height slider_x = (window_width - slider_width) / 2 slider_y = (window_height - slider_height) / 2 self.slider = NSSlider.alloc().initWithFrame_(NSMakeRect(slider_x, slider_y, slider_width, slider_height)) self.slider.setMinValue_(0) self.slider.setMaxValue_(100) self.slider.setDoubleValue_(50) self.window.contentView().addSubview_(self.slider) if __name__ == "__main__": app = NSApplication.sharedApplication() delegate = AppDelegate.alloc().init() app.setDelegate_(delegate) app.run() I get a result shown at https://github.com/user-attachments/assets/7da022bc-122b-491d-9e08-030dcb9337c3 which does not have the new liquid glass effect. Why is this? Is this perhaps related to the requirement that you must compile on latest Xcode as indicated in the docs? Why, is the compiler doing some magic?
3
0
348
Sep ’25
What is SwiftUI API equivalent to NSSplitViewItemAccessoryViewController in macOS?
On macOS Tahoe 26, NSSplitViewController introduced the NSSplitViewItemAccessoryViewController and related-APIs in NSSplitViewController, such as addBottomAlignedAccessoryViewController(_:). Those APIs allow you to place accessory views at the top and bottom of a split view with a nice edge effect. I understand how to use them with AppKit. However, I’m not sure how to achieve the same functionality with SwiftUI.
1
0
188
Sep ’25
SwiftUI TextField selects all text when it gains focus — how to move caret to the end like in AppKit?
I’m running into an issue with TextField focus behavior in SwiftUI. By default, when I set focus to a TextField programmatically (using @FocusState), SwiftUI behaves like AppKit — the entire contents of the text field are selected. This is causing problems for my use case, because I want the caret placed at the end of the text without selecting everything. How I solved this in AppKit In AppKit, I worked around this by subclassing NSTextField and overriding becomeFirstResponder to adjust the editor’s selection: override func becomeFirstResponder() -> Bool { let responderStatus = super.becomeFirstResponder() // Ensure caret is placed at the end, no text selected if let editor = self.currentEditor() { let selectedRange = editor.selectedRange editor.selectedRange = NSRange(location: selectedRange.length, length: 0) } return responderStatus } This successfully prevented AppKit from auto-selecting the entire string when focus changed. The problem in SwiftUI Now I see the same auto-select behavior in SwiftUI when I toggle focus with @FocusState. But unlike AppKit, SwiftUI doesn’t expose the underlying NSTextView or UITextField APIs, so I can’t directly adjust the selection or caret position. Questions: Is there a way in SwiftUI to control the caret/selection behavior when a TextField becomes focused? Is there a built-in modifier or @FocusState trick I’m missing? Has anyone found a reliable SwiftUI-idiomatic approach to ensure the caret is placed at the end of the text instead of selecting all text? update: adding my swiftUI code below: struct TextFieldUI: View { @ObservedObject var pModel:TextFieldModel @FocusState private var pIsFocusedState: Bool var body: some View { VStack(spacing: 20) { TextField(pModel.placeholder, text: $pModel.text) .textFieldStyle(RoundedBorderTextFieldStyle()) .padding() .focused($pIsFocusedState) .onChange(of: pModel.isFocused) { old, newValue in pIsFocusedState = newValue } .onChange(of: pIsFocusedState) { old, newValue in pModel.isFocused = newValue } .onAppear { pIsFocusedState = pModel.isFocused } Toggle("Secure Mode", isOn: $pModel.isSecure) .padding() } .padding() } }
0
0
119
Sep ’25
Icon for some menu items cannot be removed on macOS 26
create a sample XCode project using Objective-C and stroybook (xib) using latest XCode beta open MainMenu.xib, and select Main Menu → File → Print... remove the image like below 4. build it 5. run it on macOS 26 beta 7 6. The menu item "print.." still have "Image" Is there any way to remove image for one menu item. I have also tried NSMenuItem.image = nil, but still not work. The issue I met on my own app is that I cannot remove icons for "Zoom In", "Zoom Out" and many other menu items, which makes the menu items not aligned properly.
1
0
337
Sep ’25
Bug or Feature: Changes to Window Reopen Behavior in macOS 26
Since macOS 26 Beta 1, I notice that the window reopening behavior had changed. Say there are two desktops (spaces), one might: open an app window in desktop 1 close that window switch to desktop 2 reopen the app window (by click on dock tile, spotlight search...) Prior to macOS 26, that window will always reopen in current desktop. This is IMO the right behavior because these windows are most likely transient (message app, chat app, utilities app or note app). In macOS 26, however, will switch to desktop 1 (where the window is closed) and reopen the window in desktop 1. This is weird to me because: Window is "closed", hence it should not be attached to desktop 1 anymore, unlike minimize. Switching desktop interrupts user's current workflow. It's annoying to switch back specially when there're many desktops. This behavior is inconsistent. Some reopen in current desktop, some reopen in previous desktop. Apps like Music, Notes and Calendar reopened in previous desktop, while Mail, Messages, and Freeform reopened in current desktop. I did a little bit of experiment, and find out that apps that reopened in current desktop are most likely because they take an extra step to release the window when it's closed. I believe this is a bug, so I fire a feedback (FB18016497) back in beta 1. But I did not get any response or similar report from others, to a point that I kinda wonder if this is intended. I can easily force my app to reopen in current desktop by nullifying my window controller in windowWillClose, but this behavior essentially change how one can use the Spaces feature that I think I should bring this up to the community and see what other developers or engineers thinks about it.
Topic: UI Frameworks SubTopic: AppKit Tags:
3
0
206
Sep ’25
Liquid Glass icons appear differently in Dock
I just played around on macOS with the new icons created by Icon Composer, and I noticed that the Dock displays programmatically set icons differently. Try this: Make sure you have the Mail app in your Dock. Set the icon appearance to "Tinted/Light" and set a dark (black) background for the Desktop. Run this code: let image = NSWorkspace.shared.icon(forFile: "/System/Applications/Mail.app") if image.isValid { NSApp.applicationIconImage = image } You'll get something like this: When the icon appearance is set to "Default" or "Dark," everything works as expected, and the "Clear/Dark" and "Tinted/Dark" modes seem to work as well. It seems like the Dock uses a special blend mode depending on the selected background, but this does not seem to be the case if the icon is set programmatically. I filed feedback FB20291186.
0
2
720
Sep ’25
I need to access information about the apps installed in my system
How do I get the FileManager in SwiftUI to read information about the apps in the Applications folder. Lots of apps do it, Alfred, Raycast. It's not something that is unheard of, and yet I cannot for the life of me, using every kind of guide on the internet figure out how to achieve this. Please somebody help, this is legitimately affecting my mental health.
1
0
170
Sep ’25
Default document-based app menu items missing icons
In a new document-based macOS app project created in Xcode, some of the default system-provided menu commands appear without their standard icons in the menu bar. Steps to Reproduce: 1. In Xcode, create a new macOS “Document App” project (using Swift/SwiftUI or AppKit template). 2. Build and run the project. 3. Open the app’s main menu bar and examine the default items such as New Document, Open…, Save, Duplicate, etc. Expected Results: System-provided menu items (e.g. Open…, Save, Duplicate) should display their standard SF Symbol–based icons automatically, as they do in TextEdit and other system apps. Actual Results: Some of these menu items display only text, with no icon namely: Services Open Recent Revert To Share This happens even though the items are the system-managed defaults generated by the document-based app template. Notes: • No code modifications were made — this occurs in a fresh, unedited template project. • Behavior seen on macOS 26.0 (25A354). • Xcode Version 26.0 (17A324) used.
1
0
173
Sep ’25
NSWindow.titlebarAppearsTransparent only works after collapsing and expanding sidebar
I'm using the simplified code below to create a window with 4 split view items, some of them collapsed. I would expect the title bar to be transparent since I'm using window.titlebarAppearsTransparent = true, but it seems that this particular view configuration causes the title bar to be visible until I collapse and expand the sidebar again. Removing any of the split view items, uncollapsing any of them, or changing the view of any of the view controllers, causes the title bar to be consistently visible or hidden, although I don't understand the logic, since I'm telling the window that it should be transparent. When launching the app in light mode, it's more difficult to notice the issue since the title bar background is equal to the content background and only the separator is visible (even though the code sets window.titlebarSeparatorStyle = .none): After collapsing and expanding the sidebar, the separator is gone: In dark mode the title bar is more visible: After collapsing and expanding the sidebar, the title bar background and separator are gone: I created FB20306872. @main class AppDelegate: NSObject, NSApplicationDelegate, NSToolbarDelegate { var splitViewController: NSSplitViewController! func applicationDidFinishLaunching(_ aNotification: Notification) { let splitViewItem1 = NSSplitViewItem(sidebarWithViewController: ViewController1()) let splitViewItem2 = NSSplitViewItem(viewController: ViewController2()) let splitViewItem3 = NSSplitViewItem(viewController: NSViewController()) splitViewItem3.isCollapsed = true let splitViewItem4 = NSSplitViewItem(viewController: NSViewController()) splitViewItem4.isCollapsed = true splitViewController = NSSplitViewController() splitViewController.splitViewItems = [splitViewItem1, splitViewItem2, splitViewItem3, splitViewItem4] let window = NSWindow(contentViewController: splitViewController) window.styleMask = [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView] window.titlebarAppearsTransparent = true let toolbar = NSToolbar(identifier: "") toolbar.delegate = self toolbar.displayMode = .iconOnly window.toolbar = toolbar window.titlebarSeparatorStyle = .none window.makeKeyAndOrderFront(nil) } func toolbarAllowedItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] { return [.space, .flexibleSpace, .sidebarTrackingSeparator, .init("item")] } func toolbarDefaultItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] { return [.init("item"), .sidebarTrackingSeparator] } func toolbar(_ toolbar: NSToolbar, itemForItemIdentifier itemIdentifier: NSToolbarItem.Identifier, willBeInsertedIntoToolbar flag: Bool) -> NSToolbarItem? { switch itemIdentifier.rawValue { case "item": let item = NSToolbarItem(itemIdentifier: itemIdentifier) item.image = NSImage(systemSymbolName: "sidebar.leading", accessibilityDescription: nil) item.action = #selector(toggleSidebar(_:)) item.target = self return item default: return nil } } @objc func toggleSidebar(_ sender: Any?) { splitViewController.splitViewItems[0].animator().isCollapsed = !splitViewController.splitViewItems[0].isCollapsed } } class ViewController1: NSViewController { override func loadView() { view = NSView(frame: CGRect(x: 0, y: 0, width: 300, height: 200)) } } class ViewController2: NSViewController { override func loadView() { let textView = NSTextView() let scrollView = NSScrollView(frame: CGRect(x: 0, y: 0, width: 400, height: 200)) scrollView.hasVerticalScroller = true scrollView.documentView = textView view = scrollView } }
Topic: UI Frameworks SubTopic: AppKit Tags:
0
0
89
Sep ’25
Language detection
I have prepared a NSSpellServer spelling and grammar checker for Slovenian proofing in macOS. My proofing service gets used when I explicitly set keyboard spelling language to "Slovenian (Besana)" (my proofing tool). When I set keyboard language to Automatic by Language, system does the language detection. Since it has limited support for Slovenian language, it doesn't recognize the text as Slovenian and never asks my proofing service to check the spelling. It does consult my proofing service for spelling suggestions and when it does, I see the language parameter there is set to anything but Slovenian. Is it possible to install own language detector to macOS? Or, place some language dictionary files somewhere, the system could use to extend language detection to new languages?
1
0
109
Sep ’25
NSBrowser Column Resizing Causes NSWindowWillStartLiveResizeNotification to be posted even though the window isn't being resized.
I have an NSBrowser inside a window. When I start resizing a column I noticed a peculiar behavior: it causes NSWindowWillStartLiveResizeNotification to get posted for the NSWindow the browser is inside (and did end gets posted when column resizing finishes). The browser is not the NSWindow contentView but a descendant of the contentView. I have my reasons for caring (I'm currently listening for these window resize notifications) but my code naively assumes that NSWindowWillStartLiveResizeNotification - NSWindowDidEndLiveResizeNotification indicates a window resizing session, not a column resizing session for the NSBrowser. This is in contrast to NSOutlineView. When resizing columns in NSOutlineView the window resize notifications do not get posted. NSBrowser deliberately kicks it off: -[NSWindow _startLiveResize]; -[NSBrowser _resizeColumn:withEvent:] () So this seems quite intentional but is it necessary in modern macOS? Should I file a bug? I already did FB20298148
Topic: UI Frameworks SubTopic: AppKit Tags:
0
0
118
Sep ’25
Document title/proxy shifts left when adding an empty SwiftUI/AppKit toolbar - how to keep it centered?
I’m building a document-based macOS app using SwiftUI with an AppKit NSDocument. By default, when the window has no toolbar, the document title and proxy icon (with the edited state dot and standard saving controls) appear nicely centered in the title bar. However, as soon as I attach a toolbar - even an empty one - the document proxy moves to the leading edge of the title bar. Is there a way to keep the document proxy/title centered in a document-based SwiftUI app while also using a toolbar? Or is the left-alignment now the only supported behavior when a toolbar is present? Thanks in advance for any guidance.
2
0
122
Sep ’25
Sidebar created on macOS 26 with NSSplitViewItem(sidebarWithViewController:) is cut off at the top in fullscreen mode
I noticed that when I have a fullscreen window in macOS 26, sidebars look like they are cut off at the top: they suddenly stop where the title bar/toolbar would appear when moving the mouse to the top of the screen, leaving a wide empty gap. Am I the only one who finds this ugly? Is this intended, or is there a workaround? This is how it looks in fullscreen (the sidebar borders are not easy to distinguish, look for the drop shadow): And this when moving the mouse to the top screen border to show the menu bar: I created FB20291636. @main class AppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate { func applicationDidFinishLaunching(_ aNotification: Notification) { let splitViewController = NSSplitViewController() splitViewController.addSplitViewItem(NSSplitViewItem(sidebarWithViewController: ViewController())) splitViewController.addSplitViewItem(NSSplitViewItem(viewController: ViewController())) let window = NSWindow(contentViewController: splitViewController) window.styleMask = [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView] window.toolbar = NSToolbar() window.delegate = self window.makeKeyAndOrderFront(nil) } func window(_ window: NSWindow, willUseFullScreenPresentationOptions proposedOptions: NSApplication.PresentationOptions = []) -> NSApplication.PresentationOptions { return [.autoHideToolbar, .autoHideMenuBar, .fullScreen] } } class ViewController: NSViewController { override func loadView() { let stack = NSStackView(views: [ NSTextField(labelWithString: "asdf") ]) stack.orientation = .vertical stack.alignment = .leading view = stack view.frame = CGRect(x: 0, y: 0, width: 300, height: 300) } }
Topic: UI Frameworks SubTopic: AppKit Tags:
1
0
127
Sep ’25
NSButtons with NSBezelStyleGlass Sometimes Very Long Delay Before Adjusting Appearance After Toggling Dark Mode
I have some buttons. I set the bezelStyle to NSBezelStyleGlass. I'm sometimes experiencing the following issue: Put the system in dark mode. Some glass buttons still draw with the light appearance. One or more of the following actions usually makes the appearance redraw proper: -Clicking the button -Deactivating and then reactivating the window. -Close and then reopen the window. I tried setNeedsDisplay YES etc. but that didn't work The delay is quite noticeable. Everything else is in dark mode except one or two glass buttons. This seems to workaround the issue: BOOL didToggleGlass = NO; if (self.bezelStyle == NSBezelStyleGlass) { // Turn glass off just for a sec. self.bezelStyle = NSBezelStyleToolbar; didToggleGlass = YES; } if (didToggleGlass) { // Put glass back on. self.bezelStyle = NSBezelStyleGlass; } Apparently toggling glass cause the effective appearance to change so you can't use the above workaround in a -viewDidChangeEffectiveAppearance b/c you'll create an infinite loop unless you guard against it.
Topic: UI Frameworks SubTopic: AppKit Tags:
0
0
75
Sep ’25
Draw SwiftUI.Form style pop-up button with NSPopUpButton in AppKit
In SwiftUI on macOS, A menu-style Picker is drawn as a pop-up button. It generally looks and behaves the same as an NSPopUpButton in AppKit. SwiftUI introduced iOS-like looking UI for settings in macOS, and consequently, the Picker also has its own style when placed inside a Form. A Form-style Picker displays only up/down chevrons and draws the background only when the mouse hovers over it. It also changes its width dynamically based on the selected item. Form { Picker("Animal:", selection: $selection) { ForEach(["Dog", "Cow"], id: \.self) { Text($0) } .pickerStyle(.menu) } You can find it, for instance, in the Print dialog. My question is: I couldn't find a way to draw an NSPopUpButton in AppKit with this style. Does anyone know how to achieve this in AppKit? Some might say I should just use SwiftUI straightforwardly, but I would like to use it in a print panel accessory that currently still avoids using SwiftUI but its dialog has SwiftUI.Form-looking.
4
1
213
Sep ’25
NSCollectionView Liquid Glass Section Headers Don't Show After Fading Out on Scroll Sometimes
I'm noticing some weird glitches with my collection view headers on macOS Tahoe. The sections headers are pinned to the visible region. I headers fade out when scrolling and are supposed to fade back in but sometimes they don't fade back in and the header remains but the header text doesn't come back (until I scroll again). How can I turn off this scroll animation thingy?
Topic: UI Frameworks SubTopic: AppKit Tags:
4
0
138
Sep ’25
macOS Tahoe: NSView -cacheDisplayInRect:toBitmapImageRep: Doesn't Work on NSButton that uses NSBezelStyleGlass
If I try making a bitmap of a NSButton using the following code: NSBitmapImageRep *rep = [button bitmapImageRepForCachingDisplayInRect:button.bounds]; [button cacheDisplayInRect:button.bounds toBitmapImageRep:rep]; NSData *tiffData = rep.TIFFRepresentation; I get a blank image if the NSButton has its bezelStyle set to NSBezelStyleGlass. If I change the bezel style to something else like NSBezelStyleFlexiblePush I do get an image
Topic: UI Frameworks SubTopic: AppKit Tags:
1
0
73
Sep ’25