View in English

  • Apple 开发者
    • 入门汇总

    探索“入门汇总”

    • 概览
    • 学习
    • Apple Developer Program

    及时了解最新动态

    • 最新动态
    • 开发者你好
    • 平台

    探索“平台”

    • Apple 平台
    • iOS
    • iPadOS
    • macOS
    • Apple tvOS
    • visionOS
    • watchOS
    • App Store

    精选

    • 设计
    • 分发
    • 游戏
    • 配件
    • 网页
    • Home
    • CarPlay 车载
    • 技术

    探索“技术”

    • 概览
    • Xcode
    • Swift
    • SwiftUI

    精选

    • 辅助功能
    • App Intents
    • Apple 智能
    • 游戏
    • 机器学习与 AI
    • 安全性
    • Xcode Cloud
    • 社区

    探索“社区”

    • 概览
    • “与 Apple 会面交流”活动
    • 社区主导的活动
    • 开发者论坛
    • 开源

    精选

    • WWDC
    • Swift Student Challenge
    • 开发者故事
    • App Store 大奖
    • Apple 设计大奖
    • Apple Developer Centers
    • 文档

    探索“文档”

    • 文档库
    • 技术概述
    • 示例代码
    • 《人机界面指南》
    • 视频

    发布说明

    • 精选更新
    • iOS
    • iPadOS
    • macOS
    • watchOS
    • visionOS
    • Apple tvOS
    • Xcode
    • 下载

    探索“下载”

    • 所有下载
    • 操作系统
    • 应用程序
    • 设计资源

    精选

    • Xcode
    • TestFlight
    • 字体
    • SF Symbols
    • Icon Composer
    • 支持

    探索“支持”

    • 概览
    • 帮助指南
    • 开发者论坛
    • “反馈助理”
    • 联系我们

    精选

    • 《开发者账户帮助》
    • 《App 审核指南》
    • 《App Store Connect 帮助》
    • 即将实行的要求
    • 协议和准则
    • 系统状态
  • 快速链接

    • 活动
    • 新闻
    • 论坛
    • 示例代码
    • 视频
 

视频

打开菜单 关闭菜单
  • 专题
  • 所有视频
  • 关于

更多视频

  • 简介
  • 概要
  • 代码
  • 升级改造你的 AppKit App

    根据最新的 macOS 设计惯例升级改造你的 AppKit App。深入探索如何利用控制事件和手势识别器来处理输入,告别传统的追踪循环。增强 App 中的键盘导航功能,在重启后顺畅实现状态恢复;并利用新的边角同心性 API,让你的界面与 macOS 的美学设计无缝融合。

    章节

    • 0:00 - Introduction
    • 1:06 - Modern input
    • 1:27 - Modern event handling with gesture recognizers
    • 2:25 - Selection, context menus, and drag and drop
    • 3:52 - Text selection in custom views
    • 4:26 - Control events and gesture recognizers
    • 5:51 - Keyboard navigation and status items
    • 8:57 - Continuity across launches
    • 9:08 - Graceful app termination
    • 9:55 - State restoration
    • 14:09 - Design updates
    • 14:24 - Liquid Glass updates in macOS 27
    • 15:41 - Concentricity
    • 16:59 - Next steps

    资源

    • Use SwiftUI with AppKit
    • Restoring your app’s state with AppKit
    • Gestures
    • TN3212: Adopting gesture recognizers for Sidecar touch support
    • NSControl.Events
      • 高清视频
      • 标清视频

    相关视频

    WWDC26

    • 将 SwiftUI 与 AppKit 和 UIKit 搭配使用
  • 搜索此视频…
    • 3:35 - Modern dragging delegate

      // Modern dragging delegate methods
      func tableView(_ tableView: NSTableView,
              pasteboardWriterForRow row: Int) -> (any NSPasteboardWriting)? {
          let pasteboardItem = NSPasteboardItem()
          pasteboardItem.setString(..., forType: .string)
          return pasteboardItem
      }
    • 4:55 - Control events

      // Use control events
      let button = NSButton()
      button.addTarget(
          self,
          action: #selector(trackingEndedOutsideHandler),
          for: .trackingEndedOutside
      )
    • 5:44 - hitTest override

      override func hitTest(_ point: NSPoint) -> NSView? {
          return nil
      }
    • 6:24 - autorecalculatesKeyViewLoop

      window.autorecalculatesKeyViewLoop = true
    • 7:37 - Expanded interface delegate — setup

      // Set the expanded interface delegate
      @main class LightAppDelegate: NSObject, NSApplicationDelegate {
          lazy var lightStatusItem: NSStatusItem = { ... }()
      
          func applicationDidFinishLaunching(_ notification: Notification) {
              // ...
              lightStatusItem.expandedInterfaceDelegate = self
          }
      }
    • 7:52 - Expanded interface delegate — methods

      // Implement the delegate methods
      extension LightAppDelegate: NSStatusItemExpandedInterfaceDelegate {
          // ...
          func statusItem(_ statusItem: NSStatusItem, didBegin session:
                          NSStatusItemExpandedInterfaceSession) {
              // Show window
          }
          func statusItemDidEndExpandedInterfaceSession(
              _ statusItem: NSStatusItem, animated: Bool) {
              // Hide window
          }
          func selectedAction() {
              // Take the action
              // Cancel session to request window dismissal
              lightStatusItem.expandedInterfaceSession?.cancel()
          }
      }
    • 8:16 - Expanded interface delegate — cancel

      // Cancel the session when dismissing
      extension LightAppDelegate: NSStatusItemExpandedInterfaceDelegate {
          // ...
          func statusItem(_ statusItem: NSStatusItem, didBegin session:
                          NSStatusItemExpandedInterfaceSession) {
              // Show window
          }
          func statusItemDidEndExpandedInterfaceSession(
              _ statusItem: NSStatusItem, animated: Bool) {
              // Hide window
          }
          func selectedAction() {
              // Take the action
              // Cancel session to request window dismissal
              lightStatusItem.expandedInterfaceSession?.cancel()
          }
      }
    • 9:45 - preventsApplicationTerminationWhenModal

      window.preventsApplicationTerminationWhenModal = false
    • 10:18 - Set window identifiers for state restoration

      // Set window identifiers for state restoration
      @MainActor class MainWindowController: NSWindowController, NSWindowDelegate {
          // ...
          convenience init() {
              let window = NSWindow( ... )
              // ...
              window.identifier = NSUserInterfaceItemIdentifier(WindowIdentifiers.mainWindow)
              window.setFrameAutosaveName(WindowIdentifiers.mainWindow)
              window.isRestorable = true
              window.restorationClass = WindowRestorationHandler.self
              // ...
          }
      }
    • 11:04 - encodeRestorableState

      // Preserve state to recreate the UI
      @MainActor class MainWindowController: NSWindowController, NSWindowDelegate {
          // ...
          override func encodeRestorableState(with coder: NSCoder) {
              super.encodeRestorableState(with: coder)
              // ...
              coder.encode(selectedProduct?.identifier.uuid,
                          forKey: RestorationKeys.productIdentifier)
              // ...
          }
          // ...
      }
    • 11:50 - invalidateRestorableState

      // Invalidate restorable state when the view hierarchy changes
      @MainActor class MainWindowController: NSWindowController, NSWindowDelegate {
          // ...
          convenience init() {
              // ...
              splitViewController.onProductSelected = { [weak self] product in
                  self?.invalidateRestorableState()
              }
          }
      }
    • 12:26 - restoreWindow(withIdentifier:)

      // Restore windows
      class WindowRestorationHandler: NSObject, NSWindowRestoration {
          static func restoreWindow(
              withIdentifier identifier: NSUserInterfaceItemIdentifier,
              state: NSCoder,
              completionHandler: @escaping (NSWindow?, Error?) -> Void
          ) {
              //...
              if identifier == .mainWindow, let window = appDelegate.mainWindowController?.window {
                  completionHandler(window, nil)
              } else if identifier == .imageWindow {
                  let controller = ImageWindowController()
                  appDelegate.imageWindowControllers.append(controller)
                  completionHandler(controller.window, nil)
              } else {
                  completionHandler(nil, error)
              }
          }
      }
    • 13:29 - restoreState

      // Restore window UI
      @MainActor class MainWindowController: NSWindowController, NSWindowDelegate {
          //...
          override func restoreState(with coder: NSCoder) {
              super.restoreState(with: coder)
              if let productId = coder.decodeObject(
                  of: [NSString.self],
                  forKey: RestorationKeys.productIdentifier) as? String {
                  splitViewController?.selectedProductId = productId
              }
              //...
          }
      }
    • 16:11 - cornerConfiguration

      // Subclass NSView to override cornerConfiguration
      class LocalWeatherView: NSView {
          // ...
          override var cornerConfiguration: NSViewCornerConfiguration? {
              let radius: NSViewCornerRadius = .containerConcentric(minimumCornerRadius)
              return .uniformCorners(radius: radius)
          }
          // ...
      }
    • 0:00 - Introduction
    • A modern app takes advantage of how AppKit interfaces with Mac so that its form and function feel in harmony with the rest of the system. That harmony shows up in precision input, continuity across launches, and look and feel.

    • 1:06 - Modern input
    • Precision input devices have been at the heart of the Mac since the very beginning. Learn modern APIs for handling mouse events, keyboard navigation, and status items.

    • 1:27 - Modern event handling with gesture recognizers
    • Gesture recognizers are the modern way to handle mouse events in AppKit. mouseDown: overrides and tracking loops must be replaced with modern APIs.

    • 2:25 - Selection, context menus, and drag and drop
    • AppKit has dedicated view-based APIs for the most common mouseDown: use cases: observe selected on collection and table types for selection, use menuForEvent: or .menu for context menus, and use modern pasteboard delegate methods for drag and drop.

    • 3:52 - Text selection in custom views
    • NSTextSelectionManager brings classic macOS text selection behaviors to any view outside of NSTextView. Attach it to a view to get bidirectional selection, drag and drop, and toggling.

    • 4:26 - Control events and gesture recognizers
    • Control events let you react to user-driven tracking state changes on standard controls. For custom interactions, use NSGestureRecognizer.

    • 5:51 - Keyboard navigation and status items
    • Enable autorecalculatesKeyViewLoop on your window to keep Tab navigation correct as views change. For status items with custom UI, use the expanded interface session API so AppKit can manage keyboard focus correctly.

    • 8:57 - Continuity across launches
    • A great Mac app seamlessly quits and quickly restores. Learn how to handle graceful app termination and state restoration using NSWindowRestoration.

    • 9:08 - Graceful app termination
    • Apps should quit without blocking, especially during system reboots. Set preventsApplicationTerminationWhenModal to false on any sheet or modal that does not strictly require user intervention.

    • 9:55 - State restoration
    • Use NSWindowRestoration to save and recover your app's UI across launches, so it picks up exactly where people left off.

    • 14:09 - Design updates
    • There's one more area where your app and the Mac meet: the UI. Learn about Liquid Glass updates in macOS 27 and the new concentricity API.

    • 14:24 - Liquid Glass updates in macOS 27
    • Liquid Glass continues to evolve in macOS 27, and many updates apply automatically. Sidebars, scroll edge effects, and toolbar items all receive refinements, and a new interactive glass effect gives controls a physical sense of response when clicked.

    • 15:41 - Concentricity
    • The NSViewCornerConfiguration API lets views near a container's corners automatically match the container's corner radius using .containerConcentric, so views adapt to the shape of their container instead of feeling at odds with the rest of the window.

    • 16:59 - Next steps
    • Prioritize gesture recognizers and view-based APIs over mouseDown:, ensure your app is fully keyboard-navigable, make quit and relaunch feel seamless, and adopt concentricity in your view hierarchies.

Developer Footer

  • 视频
  • WWDC26
  • 升级改造你的 AppKit App
  • 打开菜单 关闭菜单
    • iOS
    • iPadOS
    • macOS
    • Apple tvOS
    • visionOS
    • watchOS
    打开菜单 关闭菜单
    • Swift
    • SwiftUI
    • Swift Playground
    • TestFlight
    • Xcode
    • Xcode Cloud
    • SF Symbols
    打开菜单 关闭菜单
    • 辅助功能
    • 配件
    • Apple 智能
    • App 扩展
    • App Store
    • 音频与视频 (英文)
    • 增强现实
    • 设计
    • 分发
    • 教育
    • 字体 (英文)
    • 游戏
    • 健康与健身
    • App 内购买项目
    • 本地化
    • 地图与位置
    • 机器学习与 AI
    • 开源资源 (英文)
    • 安全性
    • Safari 浏览器与网页 (英文)
    打开菜单 关闭菜单
    • 完整文档 (英文)
    • 部分主题文档 (简体中文)
    • 教程
    • 下载
    • 论坛 (英文)
    • 视频
    打开菜单 关闭菜单
    • 支持文档
    • 联系我们
    • 错误报告
    • 系统状态 (英文)
    打开菜单 关闭菜单
    • Apple 开发者
    • App Store Connect
    • 证书、标识符和描述文件 (英文)
    • 反馈助理
    打开菜单 关闭菜单
    • Apple Developer Program
    • Apple Developer Enterprise Program
    • App Store Small Business Program
    • MFi Program (英文)
    • Mini Apps Partner Program
    • News Partner Program (英文)
    • Video Partner Program (英文)
    • 安全赏金计划 (英文)
    • Security Research Device Program (英文)
    打开菜单 关闭菜单
    • 与 Apple 会面交流
    • Apple Developer Center
    • App Store 大奖 (英文)
    • Apple 设计大奖
    • Apple Developer Academies (英文)
    • WWDC
    阅读最近新闻。
    获取 Apple Developer App。
    版权所有 © 2026 Apple Inc. 保留所有权利。
    使用条款 隐私政策 协议和准则