Advanced Dark Mode
Advanced Dark Mode
WWDC 2018
NSAppearance
- Cocoa’s UI theme system
- One view hierarchy for both light and dar
- Underlies Dark Mode, High Contrast mode, and Touch Bar


NSAppearanceCustomization
- Adopted by NSView and NSWindow
- In 10.14, NSApplication conforms too

Appearance Source ( new )
- Makes a window inherit appearance from another object

- Assign
nil
to reset default inheritance


Custom Views
- Do appearance-sensitive work in

- Appearance changes will cause
- Set
needsUpdateConstraints needsLayout, or needsDisplay
to trigger manually




Glow behind image


Customizing for High Contrast
- High-contrast appearance names




- Not available directly
- Only via System Preferences

- Pass to
bestMatch(from:)
to provide custom behavior

Managing Custom Sublayers
- Custom sublayers don’t inherit appearance automatically
- If possible, switch to using views
- Otherwise, manage layers manually with
-viewDidChangeEffectiveAppearance()
-NSAppearance.current
Detecting Appearance Change ( new )

- Good time to
- Perform custom invalidation
- Drop caches - No need to invalidate view itself !
Current Appearance

- Thread-local state
- LikeNSGraphicsContext.current
- Appearance used to resolve colors and images
- Current appearance is set up automatically for

- You can also set it yourself

NSImage as Layer Contents
- Don’t

- Do
- If possible, switch to NSImageView
- Automatically updates for appearance
- Create a CGImage inupdateLayer()

Materials
- Dynamic backgrounds
- Use effects like blur, tinting, and gradients
- Provide depth, context, and beauty to the interface
- Automatically used in
- Window titlebars and backgrounds
- Table views
- Sidebar split view items
- Popovers
- Menus

NSVisualEffectView
- A view that shows a material

- Controls whether material uses active window look
- By default, matches enclosing window

- Controls whether material “punches through” window

- Behind-window by default


- Encapsulates effect definition

Semantic Materials ( new )

Materials
Nonsemantic materials are deprecated ⚠️
- Light
- Dark
- Medium light
- Ultra dard



Desktop-Tinted Materials
- Automatic support
- NSWindow, NSScrollView, NSTableView, NSCollectionView - Custom NSBox support

- NSBox and NSVisualEffectView support

- Untinted color in light
- Desktop-tinted in dark
- Tint effect might be disabled






- Effect is provided by Quartz window server
- Updates asynchronously from your app
- But can’t draw with the color ( or get RGB values )
- Instead, use
maskImage
Mask Image
- Masks the material to a shape
- Drawing-handler images supported
- Works with any material
- Alpha channel used for mask
- Only material (not subviews) masked
- Provide a resizable image
capInsets
andresizingMode
Vibrancy
- Lightens or darkens the content behind it
- Similar to dodge and burn in a photo editor



- Provided by “vibrant” NSAppearance objects

- Override
allowsVibrancy
to returntrue
- Blending effect automatically applies to your view and its descendants
- Typically, draw with a label color depending on prominence
- Avoid non grayscale colors

Vibrant Blending Tips
- Vibrant blend mode applies to subtree
- Typically only leaf views should be vibrant
- Break non vibrant drawing out into a sibling view
- Avoid overlapping vibrant and non-vibrant views
- Don’t subclass Cocoa controls to override
allowsVibrancy
- Only override
allowsVibrancy
if you also override drawing


Background Styles ( new )
- NSTableView now sets background style recursively
- Label colors automatically adapt to emphasized style



Custom Selections

Selection Material
- Selection material follow the accent color
- Avoid drawing custom blue selections
- Use NSVisualEffectView instead


Backward Deployment
- System colors ( 10.10 + )

- Asset catalog colors


- Desktop-tinted materials
- Desktop-tinted NSVisualEffectView materials are new in 10.14
- Classes providing automatic materials

- Manually enable or disable Dar Mode
- Automatically opted in with 10.14 SDK
- Info.plist key:NSRequiresAquaSystemAppearance
Set to NO to enable Dark Mode with earlier SDKs
Set to YES to disable it temporarily
Find Hardcoded Colors
- Static named color

- Hardcoded components

Offscreen Drawing
- Prefer block-based NSImage over lockFocus

- Other offscreen drawing techniques, including



Appearances in Interface Builder
- Views set to Aqua won’t change dynamically
- Choose “Inherited” to match the superview

- NSVisualEffectView now automatically uses the correct vibrant appearance
- Avoid overriding the appearance
- Interface Builder: select “Inherited”
- In code: setappearance
tonil


Testing Appearances ( new )
- Switch appearances from the Debug Bar and Touch Bar

Using the View Debugger ( new )
Enhancements in Xcode 10
- System color names
- Asset Catalog color names
- NSAppearance configuration

