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