View in English

  • Apple Developer
    • 시작하기

    시작하기 탐색

    • 개요
    • 알아보기
    • Apple Developer Program

    알림 받기

    • 최신 뉴스
    • Hello Developer
    • 플랫폼

    플랫폼 탐색

    • Apple 플랫폼
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    • App Store

    피처링

    • 디자인
    • 배포
    • 게임
    • 액세서리
    • 웹
    • 홈
    • CarPlay
    • 기술

    기술 탐색

    • 개요
    • Xcode
    • Swift
    • SwiftUI

    피처링

    • 손쉬운 사용
    • 앱 인텐트
    • Apple Intelligence
    • 게임
    • 머신 러닝 및 AI
    • 보안
    • Xcode Cloud
    • 커뮤니티

    커뮤니티 탐색

    • 개요
    • Apple과의 만남 이벤트
    • 커뮤니티 주도 이벤트
    • 개발자 포럼
    • 오픈 소스

    피처링

    • WWDC
    • Swift Student Challenge
    • 개발자 이야기
    • App Store 어워드
    • Apple 디자인 어워드
    • 문서

    문서 탐색

    • 문서 라이브러리
    • 기술 개요
    • 샘플 코드
    • 휴먼 인터페이스 가이드라인
    • 비디오

    릴리즈 노트

    • 피처링 업데이트
    • iOS
    • iPadOS
    • macOS
    • watchOS
    • visionOS
    • tvOS
    • Xcode
    • 다운로드

    다운로드 탐색

    • 모든 다운로드
    • 운영 체제
    • 애플리케이션
    • 디자인 리소스

    피처링

    • Xcode
    • TestFlight
    • 서체
    • SF Symbols
    • Icon Composer
    • 지원

    지원 탐색

    • 개요
    • 도움말
    • 개발자 포럼
    • 피드백 지원
    • 문의하기

    피처링

    • 계정 도움말
    • 앱 심사 지침
    • App Store Connect 도움말
    • 새로 추가될 요구 사항
    • 계약 및 지침
    • 시스템 상태
  • 빠른 링크

    • 이벤트
    • 뉴스
    • 포럼
    • 샘플 코드
    • 비디오
 

비디오

메뉴 열기 메뉴 닫기
  • 컬렉션
  • 전체 비디오
  • 소개

더 많은 비디오

  • 소개
  • 요약
  • 코드
  • AppKit 앱 현대화하기

    AppKit 앱을 최신 macOS 규칙에 맞게 최신 상태로 업데이트하세요. 제어 이벤트와 제스처 인식기를 사용한 입력 처리에 대해 자세히 살펴보고, 기존의 추적 방식을 향상해 보세요. 앱에서 키보드 탐색을 개선하고, 재시동 후 원활한 상태 복원을 구현하며, 인터페이스가 macOS 미감과 매끄럽게 어우러지도록 해 주는 새로운 모서리 동심성 API를 활용하세요.

    챕터

    • 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
      • HD 비디오
      • SD 비디오

    관련 비디오

    WWDC26

    • AppKit 및 UIKit과 함께 SwiftUI 사용하기
  • 비디오 검색…
    • 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 앱 현대화하기
  • 메뉴 열기 메뉴 닫기
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    메뉴 열기 메뉴 닫기
    • Swift
    • SwiftUI
    • Swift Playground
    • TestFlight
    • Xcode
    • Xcode Cloud
    • SF Symbols
    메뉴 열기 메뉴 닫기
    • 손쉬운 사용
    • 액세서리
    • Apple Intelligence
    • 앱 확장 프로그램
    • App Store
    • 오디오 및 비디오(영문)
    • 증강 현실
    • 디자인
    • 배포
    • 교육
    • 서체(영문)
    • 게임
    • 건강 및 피트니스
    • 앱 내 구입
    • 현지화
    • 지도 및 위치
    • 머신 러닝 및 AI
    • 오픈 소스(영문)
    • 보안
    • Safari 및 웹(영문)
    메뉴 열기 메뉴 닫기
    • 문서(영문)
    • 튜토리얼
    • 다운로드
    • 포럼(영문)
    • 비디오
    메뉴 열기 메뉴 닫기
    • 지원 문서
    • 문의하기
    • 버그 보고
    • 시스템 상태(영문)
    메뉴 열기 메뉴 닫기
    • Apple Developer
    • 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 Bounty Program(영문)
    • Security Research Device Program(영문)
    메뉴 열기 메뉴 닫기
    • Apple과의 만남
    • Apple Developer Center
    • App Store 어워드(영문)
    • Apple 디자인 어워드
    • Apple Developer Academy(영문)
    • WWDC
    최신 뉴스 읽기.
    Apple Developer 앱 받기.
    Copyright © 2026 Apple Inc. 모든 권리 보유.
    약관 개인정보 처리방침 계약 및 지침