AppDelegate.swift

1.9 KB · raw

1import AppKit23class AppDelegate: NSObject, NSApplicationDelegate {4  // Optional backing storage rather than implicitly-unwrapped optionals:5  // before `applicationDidFinishLaunching` runs (or after `invalidate`),6  // there is genuinely no status item or menu controller to hand out, and7  // reading them through a normal optional forces the lifecycle through8  // a single funnel instead of letting any caller trap on a half-built9  // delegate.10  private var statusItem: NSStatusItem?11  private var menuController: MenuController?1213  func applicationDidFinishLaunching(_ notification: Notification) {14    // Create the status item in the menu bar15    let item = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)1617    if let button = item.button {18      // Use a system symbol for the icon19      button.image = NSImage(20        systemSymbolName: "photo.on.rectangle.angled", accessibilityDescription: "Haven")21    }2223    // Initialize the menu controller24    menuController = MenuController(statusItem: item)25    statusItem = item26  }2728  /// Read-only access to the status item created during launch. Returns29  /// `nil` when the delegate has not finished launching yet (or after30  /// `invalidate()` has been called). Callers that need the item to be31  /// present must consult this guard and fail gracefully otherwise.32  var currentStatusItem: NSStatusItem? { statusItem }3334  /// Read-only access to the menu controller created during launch.35  /// Returns `nil` before launch finishes so callers do not accidentally36  /// observe a half-built controller.37  var currentMenuController: MenuController? { menuController }3839  /// Tear down status-item and menu-controller state. Useful for tests40  /// that want to recreate the delegate cleanly and for any future code41  /// path that needs to dispose of the menu bar item explicitly.42  func invalidate() {43    statusItem = nil44    menuController = nil45  }46}