View in English

  • Apple Developer
    • Get Started

    Explore Get Started

    • Overview
    • Learn
    • Apple Developer Program

    Stay Updated

    • Latest News
    • Hello Developer
    • Platforms

    Explore Platforms

    • Apple Platforms
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    • App Store

    Featured

    • Design
    • Distribution
    • Games
    • Accessories
    • Web
    • Home
    • CarPlay
    • Technologies

    Explore Technologies

    • Overview
    • Xcode
    • Swift
    • SwiftUI

    Featured

    • Accessibility
    • App Intents
    • Apple Intelligence
    • Games
    • Machine Learning & AI
    • Security
    • Xcode Cloud
    • Community

    Explore Community

    • Overview
    • Meet with Apple events
    • Community-driven events
    • Developer Forums
    • Open Source

    Featured

    • WWDC
    • Swift Student Challenge
    • Developer Stories
    • App Store Awards
    • Apple Design Awards
    • Apple Developer Centers
    • Documentation

    Explore Documentation

    • Documentation Library
    • Technology Overviews
    • Sample Code
    • Human Interface Guidelines
    • Videos

    Release Notes

    • Featured Updates
    • iOS
    • iPadOS
    • macOS
    • watchOS
    • visionOS
    • tvOS
    • Xcode
    • Downloads

    Explore Downloads

    • All Downloads
    • Operating Systems
    • Applications
    • Design Resources

    Featured

    • Xcode
    • TestFlight
    • Fonts
    • SF Symbols
    • Icon Composer
    • Support

    Explore Support

    • Overview
    • Help Guides
    • Developer Forums
    • Feedback Assistant
    • Contact Us

    Featured

    • Account Help
    • App Review Guidelines
    • App Store Connect Help
    • Upcoming Requirements
    • Agreements and Guidelines
    • System Status
  • Quick Links

    • Events
    • News
    • Forums
    • Sample Code
    • Videos
 

Vídeos

Abrir menu Fechar menu
  • Coleções
  • Todos os vídeos
  • Sobre

Mais vídeos

  • Sobre
  • Resumo
  • Código
  • Como usar o SwiftUI com AppKit e UIKit

    Descubra como adotar o SwiftUI de forma incremental em seu app do AppKit ou UIKit. Vamos mostrar como usar o framework Observation para atualizar automaticamente suas visualizações, integrar componentes do SwiftUI na hierarquia de visualizações já existente e adicionar reconhecedores de movimentos ao SwiftUI. Também vamos explorar como adicionar cenas completas do SwiftUI a um app sem alterar sua arquitetura geral.

    Capítulos

    • 0:00 - Introduction
    • 2:33 - Observation in AppKit
    • 5:41 - Hosting SwiftUI in AppKit
    • 7:48 - AppKit gestures in SwiftUI
    • 9:16 - SwiftUI in the main menu
    • 11:30 - SwiftUI scenes in AppKit
    • 13:04 - Next steps

    Recursos

      • Vídeo HD
      • Vídeo SD

    Vídeos relacionados

    WWDC26

    • Crie efeitos gráficos avançados com SwiftUI

    WWDC25

    • Novidades do UIKit

    WWDC22

    • Bring multiple windows to your SwiftUI app
    • Use SwiftUI with AppKit
    • Use SwiftUI with UIKit

    WWDC21

    • Add rich graphics to your SwiftUI app
  • Buscar neste vídeo...
    • 3:39 - Observation in AppKit

      // Observation in AppKit
      
      import Observation
      
      @Observable @MainActor
      final class ColorModel {
          var hue: Double = 0.6
          var saturation: Double = 1.0
          var brightness: Double = 1.0
      }
    • 6:28 - Circular color picker

      // Circular color picker
      
      import SwiftUI
      import Observation
      
      @Observable @MainActor
      final class ColorModel {
          var hue: Double = 0.6
          var saturation: Double = 1.0
          var brightness: Double = 1.0
      }
      
      // MARK: - Picker View
      
      @Animatable
      struct HSBColorPicker: View {
          var hue: Double
          var saturation: Double
          var brightness: Double
          @AnimatableIgnored var model: ColorModel
      
          init(model: ColorModel) {
              self.model = model
              self.hue = model.hue
              self.saturation = model.saturation
              self.brightness = model.brightness
          }
      
          var body: some View {
              Canvas { context, size in
                  let metrics = PickerMetrics(size: size)
                  drawPicker(in: &context, metrics: metrics, hue: hue, saturation: saturation, brightness: brightness)
              }
              .contentShape(Circle())
              .modifier(ColorPickerDragGesture(model: model))
              .aspectRatio(1, contentMode: .fit)
          }
      }
      
      // MARK: - Drag Gesture
      
      private struct ColorPickerDragGesture: ViewModifier {
          var model: ColorModel
      
          private enum Ring { case hue, saturation, brightness }
          @State private var draggedRing: Ring?
      
          func body(content: Content) -> some View {
              GeometryReader { proxy in
                  content.gesture(
                      DragGesture(minimumDistance: 0, coordinateSpace: .local)
                          .onChanged { onDrag(to: $0.location, size: proxy.size) }
                          .onEnded { _ in draggedRing = nil }
                  )
              }
          }
      
          private func onDrag(to location: CGPoint, size: CGSize) {
              let metrics = PickerMetrics(size: size)
              let point = CGPoint(x: location.x - metrics.mid.x, y: location.y - metrics.mid.y)
              if draggedRing == nil {
                  let distance = hypot(point.x, point.y)
                  if distance >= metrics.radius - metrics.ringWidth - metrics.gap / 2 {
                      draggedRing = .hue
                  } else if distance >= metrics.radius - metrics.ringWidth * 2 - metrics.gap {
                      draggedRing = point.x > 0 ? .brightness : .saturation
                  }
              }
              switch draggedRing {
              case .hue: model.hue = (angle0To2Pi(point) / (2 * .pi) + 0.25).truncatingRemainder(dividingBy: 1)
              case .saturation: model.saturation = leftSemicircleValue(point)
              case .brightness: model.brightness = 1 - rightSemicircleValue(point)
              case nil: break
              }
          }
      }
      
      // MARK: - Metrics
      
      struct PickerMetrics {
          let mid: CGPoint
          let radius: CGFloat
          let ringWidth: CGFloat
          let gap: CGFloat = 8
      
          init(size: CGSize) {
              let border: CGFloat = 1 // reserve room so the outer ring's stroke isn't clipped
              mid = CGPoint(x: size.width / 2, y: size.height / 2)
              radius = (min(size.width, size.height) - 2 * border) / 2
              ringWidth = radius / 3
          }
      
          var diameter: CGFloat { radius * 2 }
          var innerRadius: CGFloat { (diameter - 2 * ringWidth - gap) / 2 }
          var centerRadius: CGFloat { radius - 2 * ringWidth - gap }
      }
      
      // MARK: - Geometry Helpers
      
      func angle0To2Pi(_ point: CGPoint) -> CGFloat {
          let a = atan2(point.y, point.x)
          return a >= 0 ? a : a + 2 * .pi
      }
      
      func rightSemicircleValue(_ point: CGPoint) -> CGFloat {
          let angle = atan2(point.y, point.x)
          return point.x >= 0 ? (angle + .pi / 2) / .pi : (point.y >= 0 ? 1 : 0)
      }
      
      func leftSemicircleValue(_ point: CGPoint) -> CGFloat {
          guard point.x <= 0 else { return point.y >= 0 ? 1 : 0 }
          return (atan2(point.y, -point.x) + .pi / 2) / .pi
      }
      
      private extension Path {
          /// A circle whose stroke of `lineWidth` lands inside `radius`.
          init(ring radius: CGFloat, center: CGPoint, lineWidth: CGFloat) {
              let inset = radius - lineWidth / 2
              self.init(ellipseIn: CGRect(x: center.x - inset, y: center.y - inset, width: inset * 2, height: inset * 2))
          }
      }
      
      // MARK: - Drawing
      
      private func drawPicker(in context: inout GraphicsContext, metrics: PickerMetrics, hue: Double, saturation: Double, brightness: Double) {
          drawHueRing(in: &context, metrics: metrics, hue: hue, saturation: saturation, brightness: brightness)
          drawValueRings(in: &context, metrics: metrics, hue: hue, saturation: saturation, brightness: brightness)
          drawCenter(in: &context, metrics: metrics, hue: hue, saturation: saturation, brightness: brightness)
      }
      
      private func drawHueRing(in context: inout GraphicsContext, metrics: PickerMetrics, hue: Double, saturation: Double, brightness: Double) {
          let ring = Path(ring: metrics.radius, center: metrics.mid, lineWidth: metrics.ringWidth)
          // A custom metal shader would be work great here as well
          let colors = stride(from: 0.0, through: 1, by: 1.0 / 64).map { Color(hue: $0, saturation: saturation, brightness: brightness) }
          context.stroke(ring, with: .conicGradient(Gradient(colors: colors), center: metrics.mid, angle: .degrees(-90)), lineWidth: metrics.ringWidth)
          context.stroke(ring.strokedPath(StrokeStyle(lineWidth: metrics.ringWidth)), with: .color(.black), lineWidth: 1)
          // Tick marks are left as a fun exercise for the reader.
          drawKnob(in: &context, metrics: metrics, radius: metrics.radius, rotation: 2 * .pi * hue + .pi)
      }
      
      private func drawValueRings(in context: inout GraphicsContext, metrics: PickerMetrics, hue: Double, saturation: Double, brightness: Double) {
          drawSemicircle(in: &context, metrics: metrics, start: .degrees(90), conicAngle: .degrees(0), stops: (0...1).map {
              Gradient.Stop(color: Color(hue: hue, saturation: 1 - Double($0), brightness: brightness), location: 0.25 + Double($0) * 0.5)
          })
          drawSemicircle(in: &context, metrics: metrics, start: .degrees(270), conicAngle: .degrees(180), stops: (0...1).map {
              Gradient.Stop(color: Color(hue: hue, saturation: saturation, brightness: 1 - Double($0)), location: 0.25 + Double($0) * 0.5)
          })
          drawKnob(in: &context, metrics: metrics, radius: metrics.innerRadius, rotation: .pi * (1 - saturation))
          drawKnob(in: &context, metrics: metrics, radius: metrics.innerRadius, rotation: .pi * (1 - brightness) + .pi)
      }
      
      private func drawSemicircle(in context: inout GraphicsContext, metrics: PickerMetrics, start: Angle, conicAngle: Angle, stops: [Gradient.Stop]) {
          var path = Path()
          path.addArc(center: metrics.mid, radius: metrics.innerRadius - metrics.ringWidth / 2, startAngle: start, endAngle: start + .degrees(180), clockwise: false)
          let band = path.strokedPath(StrokeStyle(lineWidth: metrics.ringWidth))
          context.fill(band, with: .conicGradient(Gradient(stops: stops), center: metrics.mid, angle: conicAngle))
          context.stroke(band, with: .color(.black), lineWidth: 1)
          // Tick marks are left as a fun exercise for the reader.
      }
      
      private func drawCenter(in context: inout GraphicsContext, metrics: PickerMetrics, hue: Double, saturation: Double, brightness: Double) {
          let r = metrics.centerRadius
          let disc = Path(ellipseIn: CGRect(x: metrics.mid.x - r, y: metrics.mid.y - r, width: r * 2, height: r * 2))
          context.fill(disc, with: .color(Color(hue: hue, saturation: saturation, brightness: brightness)))
          context.stroke(disc, with: .color(.black))
      }
      
      private func drawKnob(in context: inout GraphicsContext, metrics: PickerMetrics, radius: CGFloat, rotation: CGFloat) {
          let lineWidth: CGFloat = 5
          let inset: CGFloat = 3 + lineWidth / 2
          var path = Path()
          path.move(to: CGPoint(x: 0, y: radius - metrics.ringWidth + inset))
          path.addLine(to: CGPoint(x: 0, y: radius - inset))
          path = path.applying(CGAffineTransform(rotationAngle: rotation))
          path = path.applying(CGAffineTransform(translationX: metrics.mid.x, y: metrics.mid.y))
          context.stroke(path, with: .color(.black.opacity(0.8)), style: StrokeStyle(lineWidth: lineWidth + 1, lineCap: .round))
          context.stroke(path, with: .color(.white), style: StrokeStyle(lineWidth: lineWidth, lineCap: .round))
      }
      
      #Preview {
          @Previewable @State var model = ColorModel()
          HSBColorPicker(model: model)
              .frame(width: 320, height: 320)
              .padding()
      }
    • 7:21 - Hosting SwiftUI in AppKit

      // Hosting SwiftUI in AppKit
      
      NSHostingView(
          rootView: HSBColorPicker(model: model)
      )
    • 8:14 - Mix NSGestureRecognizer with SwiftUI

      // Mix NSGestureRecognizer with SwiftUI
      
      import SwiftUI
      import AppKit
      
      @Observable @MainActor
      final class ColorModel {
          var hue: Double = 0.6
          var saturation: Double = 1.0
          var brightness: Double = 1.0
      }
      
      struct ForceClickReset: NSGestureRecognizerRepresentable {
          var model: ColorModel
      
          func makeNSGestureRecognizer(context: Context) -> ForceClickGestureRecognizer {
              ForceClickGestureRecognizer()
          }
      
          func handleNSGestureRecognizerAction(_ recognizer: ForceClickGestureRecognizer, context: Context) {
              withAnimation {
                  model.saturation = 1
                  model.brightness = 1
              }
          }
      }
      
      final class ForceClickGestureRecognizer: NSGestureRecognizer {
          private var didActivate = false
      
          override func pressureChange(with event: NSEvent) {
              if event.stage >= 2 && !didActivate {
                  didActivate = true
                  state = .ended
              }
          }
      
          override func mouseDown(with event: NSEvent) {
              didActivate = false
              state = .possible
          }
      
          override func mouseUp(with event: NSEvent) {
              didActivate = false
              state = .possible
          }
      }
    • 9:42 - Adding ColorMenu to the Main Menu

      // Adding ColorMenu to the Main Menu
      
      import AppKit
      import SwiftUI
      import Observation
      
      @Observable @MainActor
      final class ColorModel {
          var hue: Double = 0.6
          var saturation: Double = 1.0
          var brightness: Double = 1.0
      }
      
      // Menu definition in SwiftUI.
      struct ColorMenu: View {
          var model: ColorModel
      
          private static let hues: [(name: String, hue: Double)] = [
              ("Red", 0), ("Yellow", 0.17), ("Green", 0.33), ("Cyan", 0.5), ("Blue", 0.67), ("Purple", 0.83),
          ]
      
          var body: some View {
              Button("Full Intensity") {
                  withAnimation {
                      model.saturation = 1
                      model.brightness = 1
                  }
              }
              .keyboardShortcut(.upArrow, modifiers: [.command, .shift])
      
              Button("Blackout") {
                  withAnimation {
                      model.brightness = 0
                  }
              }
              .keyboardShortcut(.downArrow, modifiers: [.command, .shift])
      
              Divider()
      
              Button("Brighten") {
                  withAnimation {
                      model.brightness = min(1, model.brightness + 0.1)
                  }
              }
              .keyboardShortcut(.upArrow, modifiers: .command)
      
              Button("Dim") {
                  withAnimation {
                      model.brightness = max(0, model.brightness - 0.1)
                  }
              }
              .keyboardShortcut(.downArrow, modifiers: .command)
      
              Divider()
      
              Picker("Color", selection: Bindable(model).hue) {
                  ForEach(Self.hues, id: \.hue) { entry in
                      Label(entry.name, systemImage: "circle.fill")
                          .tint(Color(hue: entry.hue, saturation: 1, brightness: 1))
                          .tag(entry.hue)
                  }
              }
              .pickerStyle(.palette)
          }
      }
      
      @MainActor
      class AppDelegate: NSObject, NSApplicationDelegate {
          let colorModel = ColorModel()
      
          func setupMainMenu() {
              let mainMenu = NSMenu()
      
              let colorMenu = NSHostingMenu(rootView: ColorMenu(model: colorModel))
              colorMenu.title = "Color"
      
              let colorMenuItem = NSMenuItem()
              colorMenuItem.submenu = colorMenu
              mainMenu.addItem(colorMenuItem)
          }
      }
      
      #Preview {
          Menu("Color") {
              ColorMenu(model: ColorModel())
      
          }.padding()
      }
    • 11:36 - Adding SwiftUI scenes dynamically

      // Adding SwiftUI scenes dynamically
      
      import AppKit
      import SwiftUI
      import Observation
      
      @MainActor
      class AppDelegate: NSObject, NSApplicationDelegate {
          let model = AppModel()
          var openSettingsAction: (() -> Void)?
      
          func applicationWillFinishLaunching(_ notification: Notification) {
              let scenes = NSHostingSceneRepresentation {
                  LightMenuBarExtra(appModel: model)
                  LightSettings(appModel: model)
              }
              NSApplication.shared.addSceneRepresentation(scenes)
              openSettingsAction = {
                  scenes.environment.openSettings()
              }
          }
      
          @IBAction func openSettings(_ sender: Any?) {
              openSettingsAction?()
          }
      }
      
      @Observable @MainActor
      final class ColorModel {
          var hue: Double = 0.6
          var saturation: Double = 1.0
          var brightness: Double = 1.0
      
          var color: Color {
              Color(hue: hue, saturation: saturation, brightness: brightness)
          }
      }
      
      @Observable @MainActor
      final class AppModel {
          var showMenuBarExtra: Bool = true
      
          var colorModel = ColorModel()
      
          var startUniverse: Int = 1
          var numberOfPixels: Int = 50
      
          var maxBrightness: Double = 1.0
          var isConnected: Bool = false
      }
      
      struct LightMenuBarExtra: Scene {
          var appModel: AppModel
      
          var body: some Scene {
              MenuBarExtra("Light Mix", systemImage: "lightbulb.fill", isInserted: Bindable(appModel).showMenuBarExtra) {
                  MenuBarContent(appModel: appModel)
              }
              .menuBarExtraStyle(.window)
          }
      }
      
      
      struct MenuBarContent: View {
          @Bindable var appModel: AppModel
      
          var body: some View {
              // TODO: Use HSBColorPicker
              VStack {
                  RoundedRectangle(cornerRadius: 10)
                      .fill(appModel.colorModel.color)
                      .frame(height: 80)
                      .overlay(RoundedRectangle(cornerRadius: 10).stroke(.black.opacity(0.1)))
      
                  LabeledContent("Brightness") {
                      Slider(value: $appModel.colorModel.brightness)
                          .frame(width: 140)
                  }
              }
              .padding()
              .frame(width: 280)
          }
      }
      
      struct LightSettings: Scene {
          var appModel: AppModel
      
          var body: some Scene {
              Settings {
                  SettingsView(appModel: appModel)
              }
          }
      }
      
      struct SettingsView: View {
          var appModel: AppModel
      
          var body: some View {
              TabView {
                  Tab("General", systemImage: "gearshape") {
                      GeneralTab(appModel: appModel)
                  }
                  Tab("Output", systemImage: "antenna.radiowaves.left.and.right") {
                      OutputTab(appModel: appModel)
                  }
                  Tab("About", systemImage: "info.circle") {
                      AboutTab()
                  }
              }
              .formStyle(.grouped)
              .scrollDisabled(true)
              .frame(width: 460)
              .fixedSize(horizontal: false, vertical: true)
          }
      }
      
      struct GeneralTab: View {
          @Bindable var appModel: AppModel
      
          var body: some View {
              Form {
                  Section("Appearance") {
                      Toggle("Show in Menu Bar", isOn: $appModel.showMenuBarExtra)
                  }
                  Section("DMX Configuration") {
                      LabeledContent("Start Universe") {
                          TextField("", value: $appModel.startUniverse, format: .number)
                              .textFieldStyle(.roundedBorder)
                              .frame(width: 80)
                      }
                      LabeledContent("Number of Pixels") {
                          TextField("", value: $appModel.numberOfPixels, format: .number)
                              .textFieldStyle(.roundedBorder)
                              .frame(width: 80)
                      }
                  }
              }
          }
      }
      
      struct OutputTab: View {
          @Bindable var appModel: AppModel
      
          var body: some View {
              Form {
                  Section("Output") {
                      LabeledContent("Max Brightness") {
                          HStack {
                              Slider(value: $appModel.maxBrightness, in: 0...1)
                              Text("\(Int((appModel.maxBrightness * 100).rounded()))%")
                                  .monospacedDigit()
                                  .foregroundStyle(.secondary)
                                  .frame(width: 40, alignment: .trailing)
                          }
                      }
                  }
              }
          }
      }
      
      struct AboutTab: View {
          var body: some View {
              VStack(spacing: 16) {
                  Image(systemName: "lightbulb.fill")
                      .font(.system(size: 48))
                      .foregroundStyle(.yellow.gradient)
      
                  Text("Light Mix")
                      .font(.title2.bold())
      
                  Text("WWDC26 — Bring SwiftUI to your AppKit and UIKit App")
                      .multilineTextAlignment(.center)
                      .foregroundStyle(.secondary)
              }
          }
      }
      
      #Preview("Menu Bar") {
          MenuBarContent(appModel: AppModel())
      }
      
      #Preview("Settings") {
          SettingsView(appModel: AppModel())
      }
    • 0:00 - Introduction
    • How SwiftUI is designed to work alongside existing AppKit and UIKit apps — already used in Logic Pro plugins, Xcode's Coding Assistant, and even AppKit controls like NSSlider, NSSwitch, and NSSegmentedControl. Previews the agenda using a sample lighting-control app: Observation in AppKit, hosting SwiftUI in AppKit, AppKit gestures in SwiftUI, SwiftUI in the main menu, and SwiftUI scenes in AppKit.

    • 2:33 - Observation in AppKit
    • Replace manual needsDisplay invalidation with automatic updates by adopting @Observable on your model. AppKit (and UIKit) automatically track property reads in draw, updateConstraints, layout, updateLayer, and their NSViewController equivalents — so dependent views redraw when the model changes. Back-deployable to macOS 15 / iOS 18 via NSObservationTrackingEnabled / UIObservationTrackingEnabled, and on by default with the 2026 releases.

    • 5:41 - Hosting SwiftUI in AppKit
    • When a new feature would require very different drawing or interaction code, it's a good moment to move to SwiftUI. Reimplement the color picker as a SwiftUI Canvas — an immediate-mode drawing API similar to drawRect, with withCGContext for reusing existing CoreGraphics code — then embed the SwiftUI view in the existing AppKit hierarchy with NSHostingView.

    • 7:48 - AppKit gestures in SwiftUI
    • Reuse an existing NSGestureRecognizer subclass directly in a SwiftUI view via the new NSGestureRecognizerRepresentable protocol. Implement makeNSGestureRecognizer and handleNSGestureRecognizerAction, then attach it with the standard .gesture modifier — shown adding a Force Click to reset brightness and saturation alongside an existing drag gesture.

    • 9:16 - SwiftUI in the main menu
    • Build a menu in SwiftUI as a regular View — Buttons with actions, keyboard shortcuts, and a palette-style Picker — then add it to the AppKit main menu using NSHostingMenu (an NSMenu subclass) wrapped in an NSMenuItem. Ensures features like the Force Click reset are also available to people on input devices that don't support force gestures.

    • 11:30 - SwiftUI scenes in AppKit
    • Use NSHostingSceneRepresentation to add complete SwiftUI scenes to an app with the AppKit lifecycle. Add a MenuBarExtra for quick light controls, and a Settings scene with a Toggle that inserts or removes the MenuBarExtra dynamically — all from your existing NSApplicationDelegate.

    • 13:04 - Next steps
    • Start using @Observable to keep models and NSViews in sync, consider SwiftUI for new views, reuse existing gestures via the representable protocol, and use SwiftUI for new scenes. There's no expectation that an app needs to be entirely SwiftUI to take advantage of it.

Developer Footer

  • Vídeos
  • WWDC26
  • Como usar o SwiftUI com AppKit e UIKit
  • Open Menu Close Menu
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    • App Store
    Open Menu Close Menu
    • Swift
    • SwiftUI
    • Swift Playground
    • TestFlight
    • Xcode
    • Xcode Cloud
    • Icon Composer
    • SF Symbols
    Open Menu Close Menu
    • Accessibility
    • Accessories
    • Apple Intelligence
    • Audio & Video
    • Augmented Reality
    • Business
    • Design
    • Distribution
    • Education
    • Games
    • Health & Fitness
    • In-App Purchase
    • Localization
    • Maps & Location
    • Machine Learning & AI
    • Security
    • Safari & Web
    Open Menu Close Menu
    • Documentation
    • Downloads
    • Sample Code
    • Videos
    Open Menu Close Menu
    • Help Guides & Articles
    • Contact Us
    • Forums
    • Feedback & Bug Reporting
    • System Status
    Open Menu Close Menu
    • Apple Developer
    • App Store Connect
    • Certificates, IDs, & Profiles
    • Feedback Assistant
    Open Menu Close Menu
    • 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
    Open Menu Close Menu
    • Meet with Apple
    • Apple Developer Centers
    • App Store Awards
    • Apple Design Awards
    • Apple Developer Academies
    • WWDC
    Read the latest news.
    Get the Apple Developer app.
    Copyright © 2026 Apple Inc. All rights reserved.
    Terms of Use Privacy Policy Agreements and Guidelines