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

AppKit Documentation

Posts under AppKit subtopic

Post

Replies

Boosts

Views

Activity

Spotlight Shows "Helper Apps" That Are Inside Main App Bundle That Are Not Intended to Be Launched By The User
I have Mac apps that embed “Helper Apps” inside their main bundle. The helper apps do work on behalf of the main application. The helper app doesn’t show a dock icon, it does show minimal UI like an open panel in certain situations (part of NSService implementation). And it does make use of the NSApplication lifecycle and auto quits after it completes all work. Currently the helper app is inside the main app bundle at: /Contents/Applications/HelperApp.app Prior to Tahoe these were never displayed to user in LaunchPad but now the Spotlight based AppLauncher displays them. What’s the recommended way to get these out of the Spotlight App list on macOS Tahoe? Thanks in advance.
4
0
95
7h
NSScrollView scrolling hitch
When scrolling a basic NSScrollView there seems to be a sudden jump after each flick. Scrolling does not appear smooth and is disorientating. A scroll jump seems to happen directly after letting go of a scroll flick using a trackpad/mouse. Right at that moment the scroll turns into a momentum scroll, slowly decreasing the speed. But the first frame after the gesture the content jumps forward, more than what is expected. Observations: Counterintuitively, scrolling appears to be smoother when disabling NSScrollView.isCompatibleWithResponsiveScrolling. If disabled using a custom NSScrollView subclass there is no large jump anymore. Scrolling also appears to be smoother using a SwiftUI ScrollView. I assume that has the same behaviour as a disabled isCompatibleWithResponsiveScrolling Ironically a WKWebView scrolls much smoother. No sudden jump is observable. It also seems to scroll with faster acceleration, but the individual frames do appear smoother. Why is this better than a native NSScrollView? Elastic scrolling at the bounds of the scroll view also appears much smoother for WKWebViews. When pulling to refresh there is a jump for NSScrollView/SwiftUI, but not for WKWebView. When using an NSScrollView with isCompatibleWithResponsiveScrolling disabled, scrolling appears just as smooth as WKWebView on macOS 13 Ventura and below. On macOS 14 Sonoma scrolling behaviour is suddenly different. Please see a sample project with 4 different scroll views side by side: https://github.com/floorish/ScrollTest Screen recordings show the sudden jumps when scrolling and when elastic scrolling. Tested on Intel & Arm Macs, macOS 11 Big Sur through 15 Sequoia, built with Xcode 16. Should isCompatibleWithResponsiveScrolling be disabled on Sonoma+? Are there any drawbacks? There is also no overdraw anymore since Monterey, as described in https://developer.apple.com/library/archive/releasenotes/AppKit/RN-AppKitOlderNotes/#10_9Scrolling Even with responsive scrolling disabled, why is WKWebView scrolling much smoother than NSScrollView?
Topic: UI Frameworks SubTopic: AppKit Tags:
8
2
659
7h
NSRulerView's background color and transparency (macOS 26)
When I compiled my legacy project with Tahoe's macOS 26 SDK, NSRulerViews are showing a very different design: Under prior macOS versions the horizontal and verrical ruler's background were blurring the content view, which was extending under the rulers, showing through their transparency. With Tahoe the horizontal ruler is always reflecting the scrollview's background color, showing the blurred content view beneath. And the vertical ruler is always completely transparent (without any blurring), showing the content together with the ruler's markers and ticks. It's difficult to describe, I'll try to replicate this behavior with a minimal test project, and probably file a bug report / enhancement request. But before I take next steps, can anyone confirm this observation? Maybe it is an intentional design decision by Apple?
6
0
240
11h
How to check if a sandboxed app already has the access permission to a URL
I want to check whether a sandboxed application already has access permission to a specific URL. Based on my investigation, the following FileManager method seems to be able to determine it: FileManager.default.isReadableFile(atPath: fileURL.path) However, the method name and description don't explicitly mention this use case, so I'm not confident there aren't any oversights. Also, since this method takes a String path rather than a URL, I'd like to know if there's a more modern API available. I want to use this information to decide whether to prompt the user about the Sandbox restriction in my AppKit-based app.
4
0
116
16h
AppKit Logging Internal inconsistency Errors on NSMenu on macOS 26.1
Appkit starting logging these warnings in macOS 26.1 about my app's MainMenu. **Internal inconsistency in menus - menu <NSMenu: 0xb91b2ff80> Title: AppName Supermenu: 0xb91a50b40 (Main Menu), autoenable: YES Previous menu: 0x0 (None) Next menu: 0x0 (None) Items: () believes it has [<NSMenuSubclassHereThisIsTheMenuBarMenuForMyApp:] 0xb91a50b40> Title: Main Menu Supermenu: 0x0 (None), autoenable: YES Previous menu: 0x0 (None) Next menu: 0x0 (None) Items: ( ) as a supermenu, but the supermenu does not seem to have any item with that submenu ** I don't what that means. The supermenu is the menu that represents the menu used for my app's menu bar (as described by NSMenuSubclassHereThisIsTheMenuBarMenuForMyApp Everything seems to work fine but log looks scary. Please don't throw!
Topic: UI Frameworks SubTopic: AppKit Tags:
1
0
32
1d
NSScrollView two finger drag being interrupted
I have a fairly robust MacOS application that has an NSScrollView that contains a canvas with various subviews (including web views and text views that contain scroll views), and a couple of peer views that track items in the scroll view (eg: screen space controls). Some of these views interrupt two finger scrolling. Every scroll view, and one of the peer views (essentially a stack view with buttons in it). I have written an additional bare bones application which does roughly the same thing, and my bare bones application works perfectly: Start two-finger dragging, scroll any of these other things under the cursor, I can continue to drag (and start dragging in any of those, and they drag without interfering with the parent scroll view). I have tried everything to recreate the interruption, including drag gestures attached to these various ancillary views, and I cannot figure out why dragging some of these views under the cursor interrupts two finger drag in our application, but not in my testbed. Does anyone have suggestions for how to debug this? I can see that there is a gesture recognizer in the NSScrollView hierarchy, but I don't see it in any of my gesture recognizer handling. I have breakpoints on every variation of hit testing and mouse motion, and none of them are getting hit in unexpected ways. I'm at my wit's end. Thanks.
Topic: UI Frameworks SubTopic: AppKit Tags:
3
1
619
2d
[CBXpcConnection _sendBarrier] iOS26 App Crash or ANR
the app crashes about 10 seconds after it goes into the background libsystem_kernel.dylib semaphore_wait_trap 100% 45 dyld start + 7116 [0x1825fa000] 100% 44 xxxx main + 76 (main.m:38) [0x104c14000] 100% 43 UIKitCore UIApplicationMain + 336 [0x18ae57000] 100% 42 UIKitCore -[UIApplication _run] + 792 [0x18ae57000] 100% 41 GraphicsServices GSEventRunModal + 120 [0x224975000] 100% 40 CoreFoundation _CFRunLoopRunSpecificWithOptions + 532 [0x185569000] 100% 39 CoreFoundation __CFRunLoopRun + 820 [0x185569000] 100% 38 CoreFoundation __CFRunLoopDoSources0 + 232 [0x185569000] 100% 37 CoreFoundation __CFRunLoopDoSource0 + 172 [0x185569000] 100% 36 CoreFoundation __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 28 [0x185569000] 100% 35 BoardServices BSServiceMainRunLoopSourceHandler + 224 [0x19c8b0000] 100% 34 BoardServices __BSSERVICEMAINRUNLOOPQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ + 52 [0x19c8b0000] 100% 33 libdispatch.dylib _dispatch_block_invoke_direct + 284 [0x1bcf40000] 100% 32 libdispatch.dylib _dispatch_client_callout + 16 [0x1bcf40000] 100% 31 FrontBoardServices -[FBSWorkspace _calloutQueue_executeCalloutFromSource:withBlock:] + 168 [0x1a4d45000] 100% 30 FrontBoardServices __94-[FBSWorkspaceScenesClient _queue_updateScene:withSettings:diff:transitionContext:completion:]_block_invoke_2 + 96 [0x1a4d45000] 100% 29 FrontBoardServices __94-[FBSWorkspaceScenesClient _queue_updateScene:withSettings:diff:transitionContext:completion:]_block_invoke_2.cold.1 + 352 [0x1a4d45000] 100% 28 FrontBoardServices -[FBSScene updater:didUpdateSettings:withDiff:transitionContext:completion:] + 708 [0x1a4d45000] 100% 27 FrontBoardServices -[FBSScene _callOutQueue_maybeCoalesceClientSettingsUpdates:] + 128 [0x1a4d45000] 100% 26 FrontBoardServices __76-[FBSScene updater:didUpdateSettings:withDiff:transitionContext:completion:]_block_invoke.129 + 380 [0x1a4d45000] 100% 25 UIKitCore -[UIApplicationSceneClientAgent scene:handleEvent:withCompletion:] + 336 [0x18ae57000] 100% 24 UIKitCore -[UIScene scene:didUpdateWithDiff:transitionContext:completion:] + 244 [0x18ae57000] 100% 23 UIKitCore -[UIScene _emitSceneSettingsUpdateResponseForCompletion:afterSceneUpdateWork:] + 208 [0x18ae57000] 100% 22 UIKitCore __64-[UIScene scene:didUpdateWithDiff:transitionContext:completion:]_block_invoke.218 + 616 [0x18ae57000] 100% 21 UIKitCore -[_UIWindowSceneFBSSceneTransitionContextDrivenLifecycleSettingsDiffAction _performActionsForUIScene:withUpdatedFBSScene:settingsDiff:fromSettings:transitionContext:lifecycleActionType:] + 316 [0x18ae57000] 100% 20 UIKitCore _UISceneSettingsDiffActionPerformChangesWithTransitionContextAndCompletion + 224 [0x18ae57000] 100% 19 UIKitCore +[BSAnimationSettings(UIKit) tryAnimatingWithSettings:fromCurrentState:actions:completion:] + 736 [0x18ae57000] 100% 18 UIKitCore __186-[_UIWindowSceneFBSSceneTransitionContextDrivenLifecycleSettingsDiffAction _performActionsForUIScene:withUpdatedFBSScene:settingsDiff:fromSettings:transitionContext:lifecycleActionType:]_block_invoke + 148 [0x18ae57000] 100% 17 UIKitCore -[_UISceneLifecycleMultiplexer uiScene:transitionedFromState:withTransitionContext:] + 244 [0x18ae57000] 100% 16 UIKitCore -[_UISceneLifecycleMultiplexer _evalTransitionToSettings:fromSettings:forceExit:withTransitionStore:] + 608 [0x18ae57000] 100% 15 UIKitCore -[_UISceneLifecycleMultiplexer _performBlock:withApplicationOfDeactivationReasons:fromReasons:] + 212 [0x18ae57000] 100% 14 UIKitCore __101-[_UISceneLifecycleMultiplexer _evalTransitionToSettings:fromSettings:forceExit:withTransitionStore:]_block_invoke + 252 [0x18ae57000] 100% 13 UIKitCore _UIScenePerformActionsWithLifecycleActionMask + 112 [0x18ae57000] 100% 12 UIKitCore __101-[_UISceneLifecycleMultiplexer _evalTransitionToSettings:fromSettings:forceExit:withTransitionStore:]_block_invoke_2 + 512 [0x18ae57000] 100% 11 UIKitCore -[UIApplication _applicationDidEnterBackground] + 136 [0x18ae57000] 100% 10 UIKitCore +[UIViewController _performWithoutDeferringTransitionsAllowingAnimation:actions:] + 140 [0x18ae57000] 100% 9 UIKitCore __47-[UIApplication _applicationDidEnterBackground]_block_invoke + 256 [0x18ae57000] 100% 8 Foundation -[NSNotificationCenter postNotificationName:object:userInfo:] + 92 [0x182c3d000] 100% 7 CoreFoundation _CFXNotificationPost + 736 [0x185569000] 100% 6 CoreFoundation _CFXRegistrationPost + 436 [0x185569000] 100% 5 CoreFoundation ___CFXRegistrationPost_block_invoke + 92 [0x185569000] 100% 4 CoreFoundation __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 148 [0x185569000] 100% 3 CoreBluetooth -[CBXpcConnection _sendBarrier] + 188 [0x1c2254000] 100% 2 libdispatch.dylib _dispatch_semaphore_wait_slow + 132 [0x1bcf40000] 100% 1 libdispatch.dylib _dispatch_sema4_wait + 28 [0x1bcf40000] 100% 0 libsystem_kernel.dylib semaphore_wait_trap + 8 [0x22d5b6000]
0
0
51
2d
NSCollectionLayoutBoundarySupplementaryItem background blur covering the entire layout section
My app has the following UI layout: NSSplitViewController as the windows contentViewController NSPageController in the content (right) split item NSTabViewController as the root items of the NSPageController NSViewController with a collection view in the first tab of that NSTabViewController The collection view is using a NSCollectionViewCompositionalLayout in which the sections are set up to have a header using NSCollectionLayoutBoundarySupplementaryItem with pinToVisibleBounds=true and alignment=top With macOS 26, the pinned supplementary item automatically gets a blurred/semi-transparent background that seamlessly integrates with the toolbar. When the window's title bar has a NSTitlebarAccessoryViewController added, the said semi-transparent background gets a bottom hard edge and a hairline to provide more visual separation from the main content. During runtime, my NSPageController transitions from the NSTabViewController to another view controller. When transitioning back, the semi-transparent blur bleeds into the entire section. This happens no matter if there's a NSTitlebarAccessoryViewController added or not. It doesn't happen 100% of the cases, it seems to depend on section size, header visibility and/or scroll position. But it happens more often than not. Most of the time, a second or so after the back transition - shortly after pageControllerDidEndLiveTransition: of the NSPageControllerDelegate is called - the view updates and the supplementary views are back to normal. Sometimes, the issue also appears not when transitioning using NSPageController, but simply by scrolling through the collection view. Anyone has an idea what is happening here? Below are two screenshots of both the "ok" and "not ok" state I'm on macOS 26.0.1 and I'm using XCode 26.0.1
Topic: UI Frameworks SubTopic: AppKit Tags:
7
0
200
3d
Incorrect menu consistency warnings logged in Tahoe for NSStatusItem, performance issues related?
Is anyone else getting new warning about menu items with submenus when running on Tahoe? I'm getting big performance problems using my menu as well as seeing these messages and I'm wondering if there's a connection. My app is faceless with a NSStatusItem with an NSMenu. Specifically it's my own subclass of NSMenu where I have a lot of code to manage the menu's dynamic behavior. This code is directly in the menu subclass instead of in a controller because the app I forked had it this way, a little wacky but I don't see it being a problem. A nib defines the contents of the menu, and it's instantiated manually with code like: var nibObjects: NSArray? = [] guard let nib = NSNib(nibNamed: "AppMenu", bundle: nil) else { ... } guard nib.instantiate(withOwner: owner, topLevelObjects: &nibObjects) else { ... } guard let menu = nibObjects?.compactMap({ $0 as? Self }).first else { ... } Within that nib.instantiate call I see a warning logged that seems new to Tahoe, before the menu's awakeFromNib is called, that says (edited): Internal inconsistency in menus - menu <NSMenu: 0x6000034e5340> believes it has <My_StatusItem_App.AppMenu: 0x7f9570c1a440> as a supermenu, but the supermenu does not seem to have any item with that submenu My_StatusItem_App.AppMenu: 0x7f9570c1a440 is my menu belonging to the NSStatusItem, NSMenu: 0x6000034e5340 is the submenu of one of its menu items. At a breakpoint in the NSMenu subclass's awakeFromNib I print self and see clear evidence of the warning's incorrectness. Below is a snippet of the console including the full warning, only edited for clarity and brevity. It shows on line 32 menu item with placeholder title "prototype batch item" that indeed has that submenu. Internal inconsistency in menus - menu <NSMenu: 0x6000034e5340> Title: Supermenu: 0x7f9570c1a440 (My StatusItem App), autoenable: YES Previous menu: 0x0 (None) Next menu: 0x0 (None) Items: ( "<NSMenuItem: 0x6000010e4fa0 Do The Thing Again, ke mask='<none>'>", "<NSMenuItem: 0x6000010e5040 Customize\U2026, ke mask='<none>'>", "<NSMenuItem: 0x6000010e50e0, ke mask='<none>'>" ) believes it has <My_StatusItem_App.AppMenu: 0x7f9570c1a440> Title: My StatusItem App Supermenu: 0x0 (None), autoenable: YES Previous menu: 0x0 (None) Next menu: 0x0 (None) Items: ( ) as a supermenu, but the supermenu does not seem to have any item with that submenu (lldb) po self <My_StatusItem_App.AppMenu: 0x7f9570c1a440> Title: My StatusItem App Supermenu: 0x0 (None), autoenable: YES Previous menu: 0x0 (None) Next menu: 0x0 (None) Items: ( "<NSMenuItem: 0x6000010fd7c0 About My StatusItem App\U2026, ke mask='<none>', action: showAbout:, action image: info.circle>", "<NSMenuItem: 0x6000010fd860 Show Onboarding Window\U2026, ke mask='Shift', action: showIntro:>", "<NSMenuItem: 0x6000010fd900 Update Available\U2026, ke mask='<none>', action: installUpdate:, standard image: icloud.and.arrow.down, hidden>", "<NSMenuItem: 0x6000010e46e0, ke mask='<none>'>", "<NSMenuItem: 0x6000010e4780 Start The Thing, ke mask='<none>', action: startTheThing:>", "<NSMenuItem: 0x6000010e4dc0 \U2318-\U232b key detector item, ke mask='<none>', view: <My_StatusItem_App.KeyDetectorView: 0x7f9570c1a010>>", "<NSMenuItem: 0x6000010e4e60, ke mask='<none>'>", "<NSMenuItem: 0x6000010e4f00 saved batches heading item, ke mask='<none>', view: <NSView: 0x7f9570b4be10>, hidden>", "<My_StatusItem_App.BatchMenuItem: 0x6000016e02c0 prototype batch item, ke mask='<none>', action: replaySavedBatch:, submenu: 0x6000034e5340 ()>", "<NSMenuItem: 0x6000010f7d40, ke mask='<none>'>", "<My_StatusItem_App.ClipMenuItem: 0x7f956ef14fd0 prototype copy clip item, ke mask='<none>', action: copyClip:>", "<NSMenuItem: 0x6000010fa620 Settings\U2026, ke='Command-,', action: showSettings:>", "<NSMenuItem: 0x6000010fa6c0, ke mask='<none>'>", "<NSMenuItem: 0x6000010fa760 Quit My StatusItem App, ke='Command-Q', action: quit:>" ) Is this seemingly incorrect inconsistency message harmless? Am I only grasping at straws to think it has some connection to the performance issues with this menu?
3
2
321
3d
Extremely slow NSButton initialization
In my AppKit app I have a an outline view where each cell has a title (NSTextField), image view (NSImageView), and 4 NSButtons that are essentially static badges (their .bezelStyle is set to .badge). I’ve seeing very low performance when doing quick reloads in successions, for example when filtering data. My app is built on macOS Tahoe. Profiling the app in instruments I can see that each initialization takes more than 70ms. Does this make sense? Thanks!
Topic: UI Frameworks SubTopic: AppKit
0
0
39
4d
Layout recursion error message
Hi all, when I launch my macOS app from Xcode 16 on ARM64, appKit logs me this error on the debug console: It's not legal to call -layoutSubtreeIfNeeded on a view which is already being laid out. If you are implementing the view's -layout method, you can call -[super layout] instead. Break on _NSDetectedLayoutRecursion(void) to debug. This will be logged only once. This may break in the future. _NSDetectedLayoutRecursion doesn't help a lot, giving me these assembly codes from a call to a subclassed window method that looks like this: -(void) setFrame:(NSRect)frameRect display:(BOOL)flag { if (!_frameLocked) [super setFrame:frameRect display:flag]; } I have no direct call to -layoutSubtreeIfNeeded from a -layout implementation in my codes. I have a few calls to this method from update methods, however even if I comment all of them, the error is still logged... Finally, apart from that log, I cannot observe any layout error when running the program. So I wonder if this error can be safely ignored? Thanks!
4
0
97
5d
Resizing text to fit available space
My app displays some text that should appear the same regardless of the container view or window size, i.e. it should grow and shrink with the container view or window. On iOS there is UILabel.adjustsFontSizeToFitWidth but I couldn't find any equivalent API on macOS. On the internet some people suggest to iteratively set a smaller font size until the text fits the available space, but I thought there must be a more efficient solution. How does UILabel.adjustsFontSizeToFitWidth do it? My expectation was that setting a font's size to a fraction of the window width or height would do the trick, but when resizing the window I can see a slightly different portion of it. class ViewController: NSViewController { override func loadView() { view = MyView(frame: CGRect(x: 0, y: 0, width: 400, height: 400)) NSLayoutConstraint.activate([view.widthAnchor.constraint(equalTo: view.heightAnchor, multiplier: 3), view.heightAnchor.constraint(greaterThanOrEqualToConstant: 100)]) } } class MyView: NSView { let textField = NSTextField(labelWithString: String(repeating: "a b c d e f g h i j k l m n o p q r s t u v w x y z ", count: 2)) override init(frame frameRect: NSRect) { super.init(frame: frameRect) textField.translatesAutoresizingMaskIntoConstraints = false textField.setContentCompressionResistancePriority(.defaultLow, for: .horizontal) addSubview(textField) NSLayoutConstraint.activate([textField.topAnchor.constraint(equalTo: topAnchor), textField.leadingAnchor.constraint(equalTo: leadingAnchor), textField.trailingAnchor.constraint(equalTo: trailingAnchor)]) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func resize(withOldSuperviewSize oldSize: NSSize) { // textField.font = .systemFont(ofSize: frame.width * 0.05) textField.font = .systemFont(ofSize: frame.height * 0.1) } }
Topic: UI Frameworks SubTopic: AppKit Tags:
13
0
318
1w
How do I have the NSToolbar "floating" on top of content scrollview on macOS Tahoe?
I have this MWE right here -- it has a toolbar with a random action on it, in addition to a scroll view as the content of the window, with random labels attached inside. Since the redeisgn of the NSToolbar stuff in Tahoe, I expect the share button be able to "float" on top of the scrolled out content as shown as the first image at https://developer.apple.com/documentation/TechnologyOverviews/adopting-liquid-glass. #import <Cocoa/Cocoa.h> @interface AppDelegate : NSObject <NSApplicationDelegate, NSToolbarDelegate> @property (strong) NSWindow *window; @end @implementation AppDelegate - (void)applicationDidFinishLaunching:(NSNotification *)notification { NSRect frame = NSMakeRect(100, 100, 600, 400); self.window = [[NSWindow alloc] initWithContentRect:frame styleMask:(NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskResizable | NSWindowStyleMaskMiniaturizable) backing:NSBackingStoreBuffered defer:NO]; [self.window setTitle:@"Scroll View + Toolbar Demo"]; NSToolbar *toolbar = [[NSToolbar alloc] initWithIdentifier:@"MainToolbar"]; toolbar.displayMode = NSToolbarDisplayModeIconAndLabel; toolbar.delegate = self; [self.window setToolbar:toolbar]; NSScrollView *scrollView = [[NSScrollView alloc] initWithFrame:self.window.contentView.bounds]; [scrollView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)]; [scrollView setHasVerticalScroller:YES]; [scrollView setHasHorizontalScroller:YES]; NSView *documentView = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 1000, 1000)]; for (int i = 0; i < 10; i++) { NSTextField *label = [[NSTextField alloc] initWithFrame:NSMakeRect(50, 950 - i*80, 400, 40)]; [label setStringValue:[NSString stringWithFormat:@"Sample Label #%d", i + 1]]; [label setBezeled:NO]; [label setDrawsBackground:NO]; [label setEditable:NO]; [label setSelectable:NO]; [documentView addSubview:label]; } [scrollView setDocumentView:documentView]; [self.window setContentView:scrollView]; [self.window makeKeyAndOrderFront:nil]; } - (NSArray<NSToolbarItemIdentifier> *)toolbarAllowedItemIdentifiers:(NSToolbar *)toolbar { return @[NSToolbarFlexibleSpaceItemIdentifier, @"ShareItem"]; } - (NSArray<NSToolbarItemIdentifier> *)toolbarDefaultItemIdentifiers:(NSToolbar *)toolbar { return @[@"ShareItem"]; } - (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSToolbarItemIdentifier)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag { if ([itemIdentifier isEqualToString:@"ShareItem"]) { NSToolbarItem *shareItem = [[NSToolbarItem alloc] initWithItemIdentifier:itemIdentifier]; shareItem.toolTip = @"Share this content"; shareItem.image = [NSImage imageNamed:NSImageNameShareTemplate]; shareItem.target = self; shareItem.action = @selector(shareAction:); return shareItem; } return nil; } - (void)shareAction:(id)sender { NSLog(@"Share button clicked!"); // Here you could present a sharing service picker NSSharingServicePicker *picker = [[NSSharingServicePicker alloc] initWithItems:@[@"Hello, world!"]]; [picker showRelativeToRect:[sender view].bounds ofView:[sender view] preferredEdge:NSRectEdgeMinY]; } @end int main(int argc, const char * argv[]) { @autoreleasepool { NSApplication *app = [NSApplication sharedApplication]; AppDelegate *delegate = [[AppDelegate alloc] init]; [app setDelegate:delegate]; [app run]; } return EXIT_SUCCESS; } But it doesn't and produces this image: https://imgur.com/a/kA7MzIe I've tried to set various settings to make the top bar transparent, but all it does is that it makes it completely opaque instead. How can I make the share button float on top of the content? P.S. the app is a single-file app, compile it with clang -fobjc-arc -framework Cocoa -o ScrollApp toolbar.m
Topic: UI Frameworks SubTopic: AppKit
1
0
74
3w
NSScrollView only scrolls vertically for NSTableView after window resize
Hi everyone, I’m looking for help with an issue where using insertRows to add a row to an NSTableView requires resizing the window before I can scroll to the newly added rows that extend beyond the visible area of the NSScrollView. import Cocoa class ViewController: NSViewController { var data = Constants.movies // Table components var titleField = NSTextField() var directorField = NSTextField() var releaseYearField = NSTextField() var addMovieButton = NSButton(title: "Add Movie", image: NSImage(systemSymbolName: "plus", accessibilityDescription: "")!, target: nil, action: #selector(addMovie)) var table = NSTableView() var titleColumn = NSTableColumn(identifier: NSUserInterfaceItemIdentifier(Constants.titleColumnId)) var directorColumn = NSTableColumn(identifier: NSUserInterfaceItemIdentifier(Constants.directorColumnId)) var releaseYearColumn = NSTableColumn(identifier: NSUserInterfaceItemIdentifier(Constants.releaseColumnId)) // Scroll view let scrollView = NSScrollView() override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. view.wantsLayer = true view.layer?.backgroundColor = NSColor.black.cgColor configure() } private func configure() { titleField.translatesAutoresizingMaskIntoConstraints = false directorField.translatesAutoresizingMaskIntoConstraints = false releaseYearField.translatesAutoresizingMaskIntoConstraints = false addMovieButton.translatesAutoresizingMaskIntoConstraints = false scrollView.translatesAutoresizingMaskIntoConstraints = false table.translatesAutoresizingMaskIntoConstraints = false titleField.placeholderString = "Movie Title" directorField.placeholderString = "Name of Director" releaseYearField.placeholderString = "Year Released" // Configure table table.addTableColumn(titleColumn) table.addTableColumn(directorColumn) table.addTableColumn(releaseYearColumn) titleColumn.title = "Movie Title" directorColumn.title = "Director" releaseYearColumn.title = "Year Released" table.delegate = self table.dataSource = self table.focusRingType = .none // Configure scroll view scrollView.documentView = table scrollView.hasVerticalScroller = true scrollView.hasHorizontalScroller = false scrollView.autohidesScrollers = true // Add views to the hierarchy view.addSubview(titleField) view.addSubview(directorField) view.addSubview(releaseYearField) view.addSubview(addMovieButton) view.addSubview(scrollView) // view.addSubview(table) NSLayoutConstraint.activate([ titleField.widthAnchor.constraint(equalToConstant: 150), directorField.widthAnchor.constraint(equalToConstant: 150), releaseYearField.widthAnchor.constraint(equalToConstant: 150), addMovieButton.widthAnchor.constraint(equalToConstant: 100), titleField.topAnchor.constraint(equalTo: view.topAnchor, constant: 20), directorField.topAnchor.constraint(equalTo: view.topAnchor, constant: 20), releaseYearField.topAnchor.constraint(equalTo: view.topAnchor, constant: 20), addMovieButton.topAnchor.constraint(equalTo: view.topAnchor, constant: 20), directorField.trailingAnchor.constraint(equalTo: view.centerXAnchor, constant: -10), releaseYearField.leadingAnchor.constraint(equalTo: view.centerXAnchor, constant: 10), titleField.trailingAnchor.constraint(equalTo: directorField.leadingAnchor, constant: -20), addMovieButton.leadingAnchor.constraint(equalTo: releaseYearField.trailingAnchor, constant: 20), scrollView.topAnchor.constraint(equalTo: titleField.bottomAnchor, constant: 20), scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20), scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20), scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -20), // table.widthAnchor.constraint(equalTo: scrollView.contentView.widthAnchor), // table.heightAnchor.constraint(equalTo: scrollView.contentView.heightAnchor) ]) } @objc private func addMovie() { let title = titleField.stringValue let director = directorField.stringValue guard let year = Int(releaseYearField.stringValue) else { return } let movie = Movie(title: title, director: director, releaseYear: year) data.append(movie) // Approach 1 // table.reloadData() // Approach 2 let newRow = data.count - 1 table.insertRows(at: IndexSet(integer: newRow), withAnimation: .slideDown) } Using table.reloadData works fine and I can scroll to the new rows as I add them, but it doesn't have the smooth animation I want to achieve. What is the best practice and correct way for using table.insertRows to avoid this issue? Note: I am using programmatic constraints only.
1
0
63
3w
What is the standard process of subclassing NSTextLocation?
Cannot find any guidance in the forums and Developer Doc, the WWDC session Meet TextKit2 says this protocol is served for any location type espacially useful when the underlying doc model is not linear. But when I try to subclass the NSTextLocation with my own type to define a more structured location rather than a linear one, also with my own NSTextContentManager subclass implementation, I keep receiving the system internal Location model like NSCountableTextLocation compare to my location which cause the app to crash. -[NSCountableTextLocation compare:] receiving unmatching type <MarkdownTK2.ChildIndexPathLocation: 0x9b2402aa0> In my own NSTextContentManager subclass: public override func offset( from: any NSTextLocation, to: any NSTextLocation ) -> Int { this method will also both receive my own location and some times receiving the system defined location that I can not calculate the offset then just return zero. The doc only says If you provide your own implementation of the NSTextLocation protocol to manage locations in your content, subclass NSTextContentManager and implement your own storage object to support those locations. OS Development environment: Xcode 26.0, macOS 26.0 Run-time configuration: macOS 26.0
3
0
200
3w
CMD+V is not working on Tahoe OS with runForModalWindow screen
After upgrading my OS to Tahoe OS , in my application observed that Cmd+V is not working only on runForModalWindow. But menu Edit->Paste and Right click Paste is working on the same screen. Other screens in the application have no issues with Cmd+V. Could you please help with this issue why Cmd+V is not working only in this screen. Thanks, Sowmya
Topic: UI Frameworks SubTopic: AppKit
1
2
76
Oct ’25
How to bind AppKit window to Observable viewmodel using SwiftUI app life cycle
Hey everyone. I have a macOS app written in SwiftUI. I have multiple SwiftUI Scenes and Views, but needed to write one specific window in AppKit (an NSPanel, to be specific). The problem I'm facing is- I'm not sure how to incorporate this NSPanel with the rest of my SwiftUI/Observable code. I'm relying on the SwiftUI app cycle. For example, I have a boolean in my view model (observation tracked). I'd like to use this boolean to hide/unhide my NSPanel. Any way to cleanly hook into the viewmodel, or onto some specific observable variables would be very very helpful. Thank you everyone.
1
0
161
Oct ’25
[NSEvent charactersByApplyingModifiers:] not matching NSEvent.characters/charactersIgnoringModifiers
To my surprise [NSEvent charactersByApplyingModifiers:] does not always produce the same NSString result as the originating NSEvent reflects through characters/charactersIgnoringModifiers, even if passing on the event's own modifierFlags. For example, when pressing the 'end' key, both characters and charactersIgnoringModifiers return 0x000000000000f72b, which matches the value of NSEndFunctionKey. But calling [NSEvent charactersByApplyingModifiers:] passing in NSEvent.modifierFlags produces 0x0000000000000004, which matches the value of kEndCharCode. (lldb) po [[((NSApplication*)NSApp).currentEvent characters] characterAtIndex:0] 0x000000000000f72b (lldb) po [[((NSApplication*)NSApp).currentEvent charactersIgnoringModifiers] characterAtIndex:0] 0x000000000000f72b (lldb) po [[((NSApplication*)NSApp).currentEvent charactersByApplyingModifiers:[(NSEvent*)((NSApplication*)NSApp).currentEvent modifierFlags]] characterAtIndex:0] 0x0000000000000004 (The same can be observed with UCKeyTranslate directly, which charactersByApplyingModifiers seems to use internally). I would expect [NSApp.currentEvent charactersByApplyingModifiers:NSApp.currentEvent.modifierFlags] to match either NSApp.currentEvent.characters or NSApp.currentEvent.charactersIgnoringModifiers. Is there a logic behind this perceived discrepancy that I'm missing? Should I always prefer the content of NSEvent.characters/charactersIgnoringModifiers in this case if the modifier flags I'm applying match those of the event itself? Thanks for any insights! (Also reported as FB20591338)
Topic: UI Frameworks SubTopic: AppKit Tags:
3
0
90
Oct ’25