WWDC Quick Look 💓 By SwiftGGTeam
What's new in AppKit

What's new in AppKit

Watch original video

Highlight

macOS Monterey brings five major updates to AppKit: custom coloring of controls, SF Symbols 3 layered rendering, TextKit 2 non-linear typesetting engine, deep integration of Swift 5.5 concurrency features, and Shortcuts automation support.

Core Content

Control coloring and button design updates

macOS Monterey allows setting custom coloring for individual buttons, segmented controls, and sliders viabezelColorselectedSegmentColorandtrackFillColoraccomplish.This was already available on the Touch Bar and now extends to in-window controls.

One key design change: Push Buttons no longer have an accent color highlight when clicked, but instead are consistent with other clickable elements.Needed for custom drawinginteriorBackgroundStyleDetermine the underlying style.

Layered rendering for SF Symbols 3

SF Symbols 3 introduces two new rendering modes:

  • Hierarchical: single color, differentiated by opacity
  • Palette: Specify colors individually for each layer

Symbol variant mapping is also supported, such as automatically getting filled versions from hollow hearts.

Non-linear layout for TextKit 2

TextKit 2 uses a non-linear layout system. For large documents, only paragraphs near the visible area are typed, avoiding linear calculations from beginning to end.TextEdit’s plain text documents and AppKit text fields have been quietly made available in Big Sur using TextKit 2.

Swift Concurrency Integration

AppKit willNSResponderNSViewNSViewControllerand other core classes marked as@MainActor, the compiler level ensures that UI operations are executed on the main thread.NSColorSamplerWait for the asynchronous API to provide an async/await version.

Detailed Content

Control coloring and background style judgment (04:18)

// Set a semantic color for the button
let preorderButton = NSButton(title: "Preorder", target: self, action: #selector(preorder))
preorderButton.bezelColor = NSColor.systemOrange

// Set the selected color for the segmented control
let segmentControl = NSSegmentedControl()
segmentControl.selectedSegmentColor = NSColor.systemGreen

// Set the track fill color for the slider
let slider = NSSlider()
slider.trackFillColor = NSColor.systemBlue

Determine the background style when customizing drawing:

class CustomButtonCell: NSButtonCell {
    override func drawInterior(withFrame cellFrame: NSRect, in controlView: NSView) {
        // interiorBackgroundStyle reflects the underlying style of the button bezel
        // .normal — colorless state (regular button)
        // .emphasized — colored/emphasized state (tinted button, default button, toggle on state)
        if interiorBackgroundStyle == .emphasized {
            // Draw white content on a colored background
            drawWhiteContent()
        } else {
            // Draw dark content on a colorless background
            drawDarkContent()
        }
    }
}

Key points:

  • Colored buttons appear colored in all active states, unlike normal buttons which are white/gray
  • Avoid confusion between colored buttons and Default Buttons, both have a colored appearance
  • Labels or icons must be used to assist in conveying the purpose of the control, not color alone
  • interiorBackgroundStylealternative checkhighlightstatus to determine the drawing strategy

Color Picker (14:40)

@IBAction func pickColor(_ sender: Any?) {
    Task {
        guard let color = await NSColorSampler().sample() else { return }
        textField.textColor = color
    }
}

Key points:

  • NSColorSampler().sample()Is an async method, the user selects a color from anywhere on the screen
  • After the call, the thread gives up and waits for the user to complete the selection before continuing the execution.
  • Can be used directly inguard let, the code is more natural than the completion handler

Automatic localization of menu shortcut keys

macOS Monterey automatically handles localization of menu shortcuts:

// Automatically map unavailable shortcuts
// Command-backslash has no backslash key on a Japanese keyboard
// The system automatically maps it to an equivalent, typeable shortcut

// Directional shortcuts are automatically mirrored in RTL languages
// Command-[ automatically becomes Command-] in RTL languages

// For absolute-direction actions, such as left alignment, disable mirroring
let alignLeftItem = NSMenuItem(title: "Align Left", action: #selector(alignLeft), keyEquivalent: "[")
alignLeftItem.allowsAutomaticKeyEquivalentMirroring = false

// Disable localization entirely for a menu item
let customItem = NSMenuItem(title: "Custom", action: #selector(custom), keyEquivalent: "k")
customItem.allowsAutomaticKeyEquivalentLocalization = false

// Disable automatic localization for the entire app
func applicationShouldAutomaticallyLocalizeKeyEquivalents(_ application: NSApplication) -> Bool {
    return false
}

Key points:

  • Most applications do not require manual intervention, the system handles it automatically
  • Disable mirroring only if the shortcut key has an absolute directional meaning (e.g. Align Left)
  • App-level disabling is a last resort, use menu item-level controls first

Swift property wrapper automatically refreshes the view

class ConfigurableView: NSView {
    // Automatically call setNeedsDisplay when the property changes
    @Invalidating(.display) var foregroundColor: NSColor = .label

    // Automatically call setNeedsLayout when the property changes
    @Invalidating(.layout) var spacing: CGFloat = 8

    // Automatically call setNeedsUpdateConstraints when the property changes
    @Invalidating(.constraints) var maxWidth: CGFloat = 200

    // Automatically call invalidateIntrinsicContentSize when the property changes
    @Invalidating(.intrinsicContentSize) var title: String = ""

    // Combine multiple invalidation operations
    @Invalidating(.display, .layout) var cornerRadius: CGFloat = 0
}

Key points:

  • @InvalidatingyesNSViewNested property wrapper for
  • Property types must followEquatable, the wrapper only performs invalidation when the value actually changes
  • Built-in support.display.layout.constraints.intrinsicContentSize.restorableState
  • PassableNSViewInvalidatingProtocol defines custom invalidation behavior

Shortcuts integration

AppKit apps support Shortcuts through Services:

// Implement the validRequestor method to declare acceptable/provided data types
extension MyView: NSServicesMenuRequestor {
    override func validRequestor(forSendType sendType: NSPasteboard.PasteboardType?,
                                 returnType: NSPasteboard.PasteboardType?) -> Any? {
        if returnType == .string {
            return self
        }
        return super.validRequestor(forSendType: sendType, returnType: returnType)
    }

    func readSelection(from pboard: NSPasteboard) -> Bool {
        // Read data from the pasteboard
        return true
    }

    func writeSelection(to pboard: NSPasteboard, types: [String]) -> Bool {
        // Write data to the pasteboard
        return true
    }
}

Key points:

  • If the app already supports Services, Shortcuts is automatically supported
  • Shortcuts appear everywhere in the Services menu
  • AppKit checks whether each responder can provide/accept data of the specified type through the responder chain

Core Takeaways

  1. What to do: Add screen color picking functionality to the Mac version of the design tool
  • Why it’s worth doing:NSColorSamplerThe async/await API enables professional color pickers with just one line of code
  • How ​​to start: Called in the action of the color picking buttonawait NSColorSampler().sample(), get the color and apply it to the selected element
  1. What to do: Create colorful label icons using SF Symbols 3’s Palette mode in File Manager for Mac
  • Why it’s worth doing: Palette mode can specify different colors for different layers of the symbol. The label icon can be gray in the background layer and colored in the foreground layer.
  • How ​​to get started: UseNSImage.SymbolConfiguration(paletteColors: [backgroundColor, foregroundColor])Configure symbol rendering
  1. What to do: Migrate to TextKit 2 for Mac text editor to support very large documents
  • Why it’s worth doing: TextKit 2’s non-linear layout significantly improves performance on large documents, only the visible area is typeset
  • How ​​to get started: CreateNSTextLayoutManagersubstituteNSLayoutManager,useNSTextContentStorageManage text content
  1. What: Used in AppKit applications@InvalidatingSimplify custom view properties
  • Why it’s worth doing: Eliminate a lot ofdidSetinsetNeedsDisplay/setNeedsLayoutBoilerplate code
  • How ​​to start: Add the configuration properties of the custom view@Invalidating(.display)or@Invalidating(.layout)annotation

Comments

GitHub Issues · utterances