{"id":52315,"date":"2026-06-18T14:56:11","date_gmt":"2026-06-18T18:56:11","guid":{"rendered":"https:\/\/mjtsai.com\/blog\/?p=52315"},"modified":"2026-06-18T14:56:41","modified_gmt":"2026-06-18T18:56:41","slug":"appkit-in-macos-27","status":"publish","type":"post","link":"https:\/\/mjtsai.com\/blog\/2026\/06\/18\/appkit-in-macos-27\/","title":{"rendered":"AppKit in macOS 27"},"content":{"rendered":"<p><a href=\"https:\/\/developer.apple.com\/documentation\/macos-release-notes\/macos-27-release-notes\">macOS Golden Gate 27 Beta Release Notes<\/a>:<\/p>\n<blockquote cite=\"https:\/\/developer.apple.com\/documentation\/macos-release-notes\/macos-27-release-notes\">\n<p>AppKit adds <code>NSRefreshController<\/code>, providing pull-to-refresh functionality for <code>NSScrollView<\/code>.<\/p>\n<p>[&#8230;]<\/p>\n<p><code>NSToolbarItemGroup<\/code> adds the <code>role<\/code> property and the <code>NSToolbarItemGroupRole<\/code> enum, allowing toolbar item groups to be tagged with a semantic role. <code>NSSegmentedControl<\/code> similarly adds a <code>role<\/code> property and the <code>NSSegmentedControlRole<\/code> enum, including a <code>tabs<\/code> role for controls that represent tab-based navigation and content selection.<\/p>\n<p>[&#8230;]<\/p>\n<p><code>NSTextSelectionManager<\/code> provides common text selection interactions (click, drag, shift-click, double\/triple-click word\/line\/paragraph selection) to a <code>NSView<\/code> with a set of <code>NSGestureRecognizers<\/code> rather than overriding <code>NSEvent<\/code> mouse methods. <code>NSTextView<\/code> now uses <code>NSTextSelectionManager<\/code> and provides its own set of <code>NSGestureRecognizers<\/code> to provide additional features in addition to text selection.<\/p>\n<p>[&#8230;]<\/p>\n<p>By default, <code>NSMenu<\/code> hides all menu item symbol images &mdash; non-symbol images remain visible. [&#8230;] Use the new <code>preferredImageVisibility<\/code> property on <code>NSMenuItem<\/code> to customize the image visibility for your menu items. As in macOS 26.0, <code>NSMenu<\/code> automatically provides default visible menu item images for certain common system-wide menu items, such as Settings, Share, and Print.<\/p>\n<\/blockquote>\n\n<p><a href=\"https:\/\/developer.apple.com\/documentation\/updates\/appkit\">AppKit updates<\/a>:<\/p>\n<blockquote cite=\"https:\/\/developer.apple.com\/documentation\/updates\/appkit\">\n<p>Create events similar to <code>UIControl<\/code> events on <a href=\"https:\/\/developer.apple.com\/documentation\/AppKit\/NSControl\"><code>NSControl<\/code><\/a> with the new <a href=\"https:\/\/developer.apple.com\/documentation\/AppKit\/NSControl\/Events\"><code>NSControl.Events<\/code><\/a> type.<\/p>\n<p>[&#8230;]<\/p>\n<p>Initiate a drag operation from a gesture recognizer using the new <a href=\"https:\/\/developer.apple.com\/documentation\/AppKit\/NSView\/beginDraggingSession(items:gesture:source:)\"><code>beginDraggingSession(items:gesture:source:)<\/code><\/a> method on <a href=\"https:\/\/developer.apple.com\/documentation\/AppKit\/NSView\"><code>NSView<\/code><\/a>.<\/p>\n<p>[&#8230;]<\/p>\n<p>Update views automatically in response to <a href=\"https:\/\/developer.apple.com\/documentation\/Observation\/Observable\"><code>Observable<\/code><\/a> model changes using the guidance in <a href=\"https:\/\/developer.apple.com\/documentation\/AppKit\/updating-views-automatically-with-observation-tracking\">Updating views automatically with observation tracking<\/a>.<\/p>\n<\/blockquote>\n\n<p>How is this different from what was announced <a href=\"https:\/\/mjtsai.com\/blog\/2025\/06\/18\/automatic-observation-tracking-in-uikit-and-appkit\/\">last year<\/a>?<\/p>\n\n<p><a href=\"https:\/\/developer.apple.com\/videos\/play\/wwdc2026\/289\/\">Modernize your AppKit app<\/a>:<\/p>\n<blockquote cite=\"https:\/\/developer.apple.com\/videos\/play\/wwdc2026\/289\/\">\n<p>Bring your AppKit app up to date with modern macOS conventions. Dive into handling input with control events and gesture recognizers, moving beyond traditional tracking loops. Enhance keyboard navigation in your app, implement graceful state restoration after restarts, and take advantage of new corner concentricity APIs that let your interface blend seamlessly with the macOS aesthetic.<\/p>\n<\/blockquote>\n\n<p><a href=\"https:\/\/mastodon.social\/@stroughtonsmith\/116720914974503987\">Steve Troughton-Smith<\/a>:<\/p>\n<blockquote cite=\"https:\/\/mastodon.social\/@stroughtonsmith\/116720914974503987\">\n<p>To summarize the singular AppKit session this year: hey remember all these APIs and design patterns from UIKit? Well they&rsquo;re now in AppKit and you should use them! Also make your glass use interactive bounce effects.<\/p>\n<p>Why? No reason!&#x1F609;<\/p>\n<\/blockquote>\n\n<p><a href=\"https:\/\/developer.apple.com\/documentation\/Technotes\/tn3212-adopting-gesture-recognizers-for-sidecar-touch-support\">TN3212<\/a>:<\/p>\n<blockquote cite=\"https:\/\/developer.apple.com\/documentation\/Technotes\/tn3212-adopting-gesture-recognizers-for-sidecar-touch-support\">\n<p>In macOS 27, AppKit continues to standardize on gesture recognizers as the primary mechanism for input handling. This change directly affects Sidecar because gesture recognizers are the only way to respond to touch input from a Sidecar-connected iPad running iPadOS 27. If your app relies on tracking loops for mouse event handling, migrate to gesture recognizers to support Sidecar touch input.<\/p>\n<p>This article explains how the gesture recognizer model works, how to implement gesture recognizers correctly for Sidecar touch input, how to update your existing event-handling code, and which APIs macOS 27 adds. Codebases that implement <a href=\"https:\/\/developer.apple.com\/documentation\/AppKit\/NSWindow\/nextEvent(matching:)\"><code>nextEvent(matching:)<\/code><\/a> or <a href=\"https:\/\/developer.apple.com\/documentation\/AppKit\/NSResponder\/mouseDown(with:)\"><code>mouseDown(with:)<\/code><\/a>, <a href=\"https:\/\/developer.apple.com\/documentation\/AppKit\/NSResponder\/mouseDragged(with:)\"><code>mouseDragged(with:)<\/code><\/a>, and <a href=\"https:\/\/developer.apple.com\/documentation\/AppKit\/NSResponder\/mouseUp(with:)\"><code>mouseUp(with:)<\/code><\/a> events are most affected by the updates discussed.<\/p>\n<\/blockquote>\n\n<p><a href=\"https:\/\/mastodon.social\/@agiletortoise\/116721189165623106\">Greg Pierce<\/a>:<\/p>\n<blockquote cite=\"https:\/\/mastodon.social\/@agiletortoise\/116721189165623106\">\n<p>After the AppKit session blindsided me a bit after telling me not to override <code>mouseDown<\/code>, and then telling me I should override <code>hitTest<\/code><\/p>\n<\/blockquote>\n\n<p><a href=\"https:\/\/mastodon.social\/@marioguzman\/116739060412201202\">Mario Guzm&aacute;n<\/a>:<\/p>\n<blockquote cite=\"https:\/\/mastodon.social\/@marioguzman\/116739060412201202\">\n<p>A few years ago, Apple introduced:<\/p>\n<pre>func tableView(_ tableView: NSTableView, userCanChangeVisibilityOf column: NSTableColumn) -&gt; Bool<\/pre>\n<p>for <code>NSTableView<\/code>, which Is a native way users could control-click on a TableView column to show\/hide columns.<\/p>\n<p>This year, in #macOS27, they updated it to have a new &ldquo;Reset to Defaults&rdquo; option.<\/p>\n<p>This is awesome bc I have done my own implementation of this feature JUST to have the option to &ldquo;reset all columns&rdquo; and now Apple just includes it!<\/p>\n<\/blockquote>\n\n<p><a href=\"https:\/\/developer.apple.com\/videos\/play\/wwdc2026\/370\/\">Elevate your app&rsquo;s text experience with TextKit<\/a>:<\/p>\n<blockquote cite=\"https:\/\/developer.apple.com\/videos\/play\/wwdc2026\/370\/\">\n<p>Discover how to combine the convenience of built-in text views with the control of TextKit. We&rsquo;ll show you how new APIs make it easy to extend <code>UITextView<\/code> and <code>NSTextView<\/code> with custom behaviors like line numbers and collapsible sections. We&rsquo;ll also explore the TextKit architecture and walk through new caching and reuse policies for text attachments.<\/p>\n<\/blockquote>\n\n<p>Previously:<\/p>\n<ul>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2026\/06\/18\/macos-touch\/\">macOS Touch<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2026\/06\/17\/wwdc-2026-links\/\">WWDC 2026 Links<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2026\/06\/09\/golden-gate-menu-icons\/\">Golden Gate Menu Icons<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2026\/06\/09\/golden-gate-sidebars-and-toolbars\/\">Golden Gate Sidebars and Toolbars<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2025\/08\/15\/textkit-2-the-promised-land\/\">TextKit 2: The Promised Land<\/a><\/li>\n<\/ul>","protected":false},"excerpt":{"rendered":"<p>macOS Golden Gate 27 Beta Release Notes: AppKit adds NSRefreshController, providing pull-to-refresh functionality for NSScrollView. [&#8230;] NSToolbarItemGroup adds the role property and the NSToolbarItemGroupRole enum, allowing toolbar item groups to be tagged with a semantic role. NSSegmentedControl similarly adds a role property and the NSSegmentedControlRole enum, including a tabs role for controls that represent tab-based [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"apple_news_api_created_at":"2026-06-18T18:56:17Z","apple_news_api_id":"cc74f7ca-1342-4db3-8dcf-6d891be84db4","apple_news_api_modified_at":"2026-06-18T18:56:45Z","apple_news_api_revision":"AAAAAAAAAAAAAAAAAAAAAA==","apple_news_api_share_url":"https:\/\/apple.news\/AzHT3yhNCTbONz22JG-hNtA","apple_news_coverimage":0,"apple_news_coverimage_caption":"","apple_news_is_hidden":false,"apple_news_is_paid":false,"apple_news_is_preview":false,"apple_news_is_sponsored":false,"apple_news_maturity_rating":"","apple_news_metadata":"\"\"","apple_news_pullquote":"","apple_news_pullquote_position":"","apple_news_slug":"","apple_news_sections":"\"\"","apple_news_suppress_video_url":false,"apple_news_use_image_component":false,"footnotes":""},"categories":[4],"tags":[69,30,2784,71,1818,591],"class_list":["post-52315","post","type-post","status-publish","format-standard","hentry","category-programming-category","tag-cocoa","tag-mac","tag-macos-27","tag-programming","tag-sidecar","tag-text-kit"],"apple_news_notices":[],"_links":{"self":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/52315","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/comments?post=52315"}],"version-history":[{"count":2,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/52315\/revisions"}],"predecessor-version":[{"id":52319,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/52315\/revisions\/52319"}],"wp:attachment":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/media?parent=52315"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/categories?post=52315"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/tags?post=52315"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}