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)
}
}
AppKit
RSS for tagConstruct and manage a graphical, event-driven user interface for your macOS app using AppKit.
Posts under AppKit tag
187 Posts
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
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.
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.
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?
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
Previously I was able to "snapshot" view that were not part of any window hierarchy using the following:
NSImage *buttonImage = [NSImage imageWithSystemSymbolName:@"49.circle.fill" accessibilityDescription:nil];
NSButton *aButton = [NSButton buttonWithImage:buttonImage target:nil action:nil];
[aButton sizeToFit];
NSBitmapImageRep *rep = [aButton bitmapImageRepForCachingDisplayInRect:aButton.bounds];
if (rep == nil) {
NSLog(@"Failed to get bitmap image rep.");
return;
}
[aButton cacheDisplayInRect:aButton.bounds toBitmapImageRep:rep];
NSData *tiffData = rep.TIFFRepresentation;
NSImage *snapShotOfImage = [[NSImage alloc]initWithData:tiffData];
Now on macOS Tahoe I get a non nil image, but the image is blank.
However if I add aButton NSWindow's view hiearchy just before the call to -cacheDisplayInRect:toBitmapImageRep: I do get a proper image.
Is this behavior intended or is this considered a bug? Is it documented anywhere that a view must be in a NSWindow for -cacheDisplayInRect:toBitmapImageRep: to work? Thanks
Crashlog-0916-071225.log
I have an app that crashes on OSX 26 only. I have a @StateObject which is an observer of the NSColorPanel.
When I call
let panel = NSColorPanel.shared
in init(), SwiftUI will crash - apparently with an update while view is being updated. See crash log.
I was able to work around it by adding
let _ = NSColorPanel.shared
in my AppDelegate before SwiftUI is initialized.
The exact code worked fine in all previous OSX versions.
Hi all,
In my AppKit app, I sometimes simulate events programmatically, for example:
func simulateKeyPress(characters: String, keyCode: UInt16) {
guard let keyDown = NSEvent.keyEvent(
with: .keyDown,
location: .zero,
modifierFlags: [],
timestamp: 0,
windowNumber: NSApp.mainWindow?.windowNumber ?? 0,
context: nil,
characters: characters,
charactersIgnoringModifiers: characters,
isARepeat: false,
keyCode: keyCode
) else { return }
NSApp.postEvent(keyDown, atStart: false)
}
At the same time, I install a local event monitor:
NSEvent.addLocalMonitorForEvents(matching: .any) { event in
// Ideally, detect whether this event came from a real user
// (mouse, keyboard, trackpad, etc.)
// or was programmatically generated via NSEvent + postEvent.
return event
}
The problem:
Events I generate with NSEvent.* factory methods and post using NSApp.postEvent look the same as real system events when received in the monitor.
My question:
Is there a supported way to tell whether an incoming NSEvent is system/user-generated vs programmatically posted?
Hi everyone,
I’ve run into a strange localization issue with macOS document-based apps in SwiftUI/AppKit. I created a standard document-based macOS app in Xcode (SwiftUI template) and added a French localization to the project.
All system-generated menu bar commands (File → New, Close, Print, etc.) are correctly translated into French… except for “Save”, which remains in English.
To rule out problems in my own code, I created a fresh, unmodified document-based app project in Xcode, and immediately added French localization without touching any code. Same result: all commands are translated except “Save”.
This suggests the issue isn’t specific to my app code, but either the project template, or possibly macOS itself.
My environment
• Xcode version: 16.4
• macOS version: 15.6.1 Sequoia]
• Swift: Swift 6
Questions
1. Has anyone else seen this issue with the “Save” command not being localized?
2. Is this expected behavior (maybe “Save” is handled differently from other menu items)?
3. If it’s a bug in the template or OS, is there a known workaround?
Thanks for any insights
P.S. Please note that I'm a total beginner
I have an NSWindow that isn't entirely opaque. When presenting a sheet AppKit overlays the window with NSSheetEffectDimmingView.
The problem is the entire window frame is used so NSSheetEffectDimmingView overlays the transparent areas of the window and it looks bad. Is there a clean way to inset NSSheetEffectDimmingView or even perhaps disable this behavior completely so I can draw my own?
I'm looking for a clean solution (other than modifying the view hierarchy of NSNextStepFrame) or swizzles which I might have to resort to if there is no other way.
The NSWindow collection behavior is supposed to allow for a window to appear in all spaces, even when another window is full screen in that space. However, I cannot get this to work as expected with any combination.
This should be as simple as:
window.level = .screenSaver
window.collectionBehavior = [
.canJoinAllSpaces,
.fullScreenAuxiliary,
.canJoinAllApplications,
.stationary,
.ignoresCycle
]
If I have a window (Safari for example) which is full screen in its own space, run my app and change to the Safari window's space, my app's window is not visible at all; it will only float on top of windows in non-fullscreen spaces.
What am I misunderstanding?
Hi,
I have a NSToolbar in my Mac Catalyst app with a space and flexible space item in it (https://developer.apple.com/documentation/appkit/nstoolbaritem/identifier/space).
On macOS Tahoe the space item is being rendered with a Liquid Glass effect and seems to be automatically grouped with the previous item. Is there a way to prevent this?
It basically adds some undesired padding next to the previous item and looks add. The flexible space is rendered normally and as before.
I am talking about the space right next to the back chevron item.
Thanks for any hints!
I have a document-based macOS app written in Objective-C, and each document window contains a scrollable NSTextView. I know that printing can get complicated if you want to do nice pagination, but is there a quick and dirty way to get basic printing working? As it is, the print panel shows up, but its preview area is totally blank. Here's the current printing part of my NSDocument subclass.
- (NSPrintInfo *)printInfo
{
NSPrintInfo *printInfo = [super printInfo];
[printInfo setHorizontalPagination: NSPrintingPaginationModeFit];
[printInfo setHorizontallyCentered: NO];
[printInfo setVerticallyCentered: NO];
[printInfo setLeftMargin: 72.0];
[printInfo setRightMargin: 72.0];
[printInfo setTopMargin: 72.0];
[printInfo setBottomMargin: 72.0];
return printInfo;
}
- (void)printDocumentWithSettings:(NSDictionary<NSPrintInfoAttributeKey, id> *)printSettings
showPrintPanel:(BOOL)showPrintPanel
delegate:(id)delegate
didPrintSelector:(SEL)didPrintSelector
contextInfo:(void *)contextInfo
{
NSPrintInfo* thePrintInfo = [self printInfo];
[thePrintInfo setVerticallyCentered: NO ];
NSPrintOperation *op = [NSPrintOperation
printOperationWithView: _textView
printInfo: thePrintInfo ];
[op runOperationModalForWindow: _docWindow
delegate: delegate
didRunSelector: didPrintSelector
contextInfo: contextInfo];
}
I implemented a subclass of NSCollectionViewItem:
class ViewItem: NSCollectionViewItem {
override func loadView() {
self.view = NSView()
}
}
and registed to NSCollectionView:
class PictureFrameThemeListView: NSCollectionView {
init(viewModel: PictureFrameViewModel) {
super.init(frame: .zero)
self.register(ViewItem.self, forItemWithIdentifier: .item)
}
However, when calling makeItem(withIdentifier:for:), the following error is prompted:
FAULT: NSInternalInconsistencyException: -[NSNib _initWithNibNamed:bundle:options:] could not load the nib 'Item' in bundle NSBundle
What confuses me is that I registered the subclass of NSCollectionViewItem, why do NSCollectionView to init the NSNib?
When I try to make a unit test target for my macOS app that uses Objective-C, running tests fails, and the debugging log shows a message "Creating more than one Application". If, on the other hand, when I create the unit test target, I select "None" as the target to be tested, and then add all my sources to that target, my tests work. So, I can get my testing done, but I think I must be doing something wrong.
By the way, along with the error message, there is a stack crawl:
0 CoreFoundation 0x00007ff8140410aa __exceptionPreprocess + 242
1 libobjc.A.dylib 0x00007ff813b660b7 objc_exception_throw + 48
2 Foundation 0x00007ff814f19bd8 -[NSCalendarDate initWithCoder:] + 0
3 AppKit 0x00007ff817030062 -[NSApplication init] + 1718
4 XCTestCore 0x000000010774b0df -[XCTestDriver _createTestBundlePrincipalClassInstance] + 82
5 XCTestCore 0x0000000107749338 -[XCTestDriver _runTests] + 111
6 XCTestCore 0x000000010770f194 _XCTestMain + 126
7 libXCTestBundleInject.dylib 0x0000000106e8982d __copy_helper_block_e8_32s + 0
8 CoreFoundation 0x00007ff813fc9a91 __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12
9 CoreFoundation 0x00007ff813fc99ca __CFRunLoopDoBlocks + 398
10 CoreFoundation 0x00007ff813fc883d __CFRunLoopRun + 898
11 CoreFoundation 0x00007ff813fc7e51 CFRunLoopRunSpecific + 560
12 HIToolbox 0x00007ff81da52f3d RunCurrentEventLoopInMode + 292
13 HIToolbox 0x00007ff81da52b84 ReceiveNextEventCommon + 199
14 HIToolbox 0x00007ff81da52aa8 _BlockUntilNextEventMatchingListInModeWithFilter + 64
15 AppKit 0x00007ff8170689d8 _DPSNextEvent + 858
16 AppKit 0x00007ff817067882 -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 1214
17 AppKit 0x00007ff817059ef7 -[NSApplication run] + 586
18 AppKit 0x00007ff81702e111 NSApplicationMain + 817
19 PlainCalc 0x00000001057d0a91 main + 65
20 dyld 0x00007ff813b93418 start + 1896
This method on UIEvent gets you more touch positions, and I think it's useful for a drawing app, to respond with greater precision to the position of the Pencil stylus.
Is there a similar thing in macOS, for mouse or tablet events? I found this property mouseCoalescingEnabled, but the docs there don't describe how to get the extra events.
I have a voice chat app that frequently writes to the universal clipboard. This works fine most of the time, but I've noticed that if I don't touch the screen for a long time, the universal clipboard information I read on my Mac won't update until I touch the app screen again. How can I fix this?
I have a table view where each row has two labels, one left-aligned and one right-aligned. I would like to reload a single row, but doing so causes the right-aligned label to hug the left-aligned label.
Before the reload:
After the reload:
Reloading the whole table view instead, or disabling automatic row height, solves the issue. Can a single row be reloaded without resorting to these two workarounds?
I created FB13534100 1.5 years ago but got no response.
class ViewController: NSViewController, NSTableViewDataSource, NSTableViewDelegate {
override func loadView() {
let tableView = NSTableView()
tableView.translatesAutoresizingMaskIntoConstraints = false
tableView.dataSource = self
tableView.delegate = self
tableView.usesAutomaticRowHeights = true
let column = NSTableColumn()
column.width = 400
tableView.addTableColumn(column)
let scrollView = NSScrollView(frame: CGRect(x: 0, y: 0, width: 500, height: 500))
scrollView.translatesAutoresizingMaskIntoConstraints = false
scrollView.documentView = tableView
view = scrollView
Timer.scheduledTimer(withTimeInterval: 2, repeats: false) { _ in
print("reload")
tableView.reloadData(forRowIndexes: IndexSet(integer: 2), columnIndexes: IndexSet(integer: 0))
// tableView.reloadData()
}
}
func numberOfRows(in tableView: NSTableView) -> Int {
return 5
}
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
let cell = NSTableCellView()
let textField1 = NSTextField(labelWithString: "hello")
textField1.translatesAutoresizingMaskIntoConstraints = false
let textField2 = NSTextField(wrappingLabelWithString: "world")
textField2.translatesAutoresizingMaskIntoConstraints = false
textField2.alignment = .right
let stack = NSStackView(views: [
textField1,
textField2
])
stack.translatesAutoresizingMaskIntoConstraints = false
stack.distribution = .fill
cell.addSubview(stack)
NSLayoutConstraint.activate([stack.topAnchor.constraint(equalTo: cell.topAnchor, constant: 0), stack.leadingAnchor.constraint(equalTo: cell.leadingAnchor, constant: 0), stack.bottomAnchor.constraint(equalTo: cell.bottomAnchor, constant: 0), stack.trailingAnchor.constraint(equalTo: cell.trailingAnchor, constant: 0)])
return cell
}
}
When using NSTableView or NSOutlineView, if you use an NSTableCellView and wire up the .imageView and .textField properties then you get some "free" behaviour with respect to styling and sizing of those fields. (ex: They reflect the user's preferred "Sidebar Icon Size" as selected in Settings. )
If I'm using a SwiftUI View inside an NSTableCellView, is there any way to connect a Text or Image to those properties?
Consider the following pseudo code:
struct MyCellView: View {
let text: String
let url: URL?
var body: some View {
HStack {
Image(...) // How to indicate this is .imageView?
Text(...) // How to indicate this is .textField?
}
}
}
final class MyTableCellView: NSTableCellView {
private var hostingView: NSHostingView<MyCellView>!
init() {
self.hostingView = NSHostingView(rootView: MyCellView(text: "", url: nil))
self.addSubview(self.hostingView)
}
func configureWith(text: String, url: URL) {
let rootView = MyCellView(text: text, url: url)
hostingView.rootView = rootView
// How can I make this connection?
self.textField = rootView.???
self.imageView = rootView.???
}
}
I'm ideally looking for a solution that works on macOS 15+.
I'm using IB to create an NSOutlineView.
I configure it:
[_outlineView setStyle:NSTableViewStyleSourceList]
I put it in an NSSplitView.
What I get is an old-style sidebar with a VisualEffect background and no rounded rect border.