2021 EssentialsSwiftUI & UI Frameworks
WWDC21 · 27 min · Essentials / SwiftUI & UI Frameworks
What’s new in Mac Catalyst
Discover the latest updates to Mac Catalyst and find out how you can make your app feel even more at home on macOS. Learn about a variety of new and enhanced UIKit APIs that let you customize your Mac Catalyst app to take advantage of behaviors unique to macOS. To get the most out of this session, we recommend a basic familiarity with Mac Catalyst. Check out “Introducing iPad Apps for Mac” from WWDC19 to acquaint yourself. For more on refining your Mac Catalyst app, watch “Optimize the interface of your Mac Catalyst app” from WWDC20.
Watch at developer.apple.com ↗Code shown on screen · 22 snippets
Push Button
let button = UIButton(type: .system) Toggle Button
let button = UIButton(type: .system)
button.changesSelectionAsPrimaryAction = true Pull-down Menu
let button = UIButton(type: .system)
button.menu = UIMenu()
button.showsMenuAsPrimaryAction = true Pop-up Button
let button = UIButton(type: .system)
button.menu = UIMenu()
button.showsMenuAsPrimaryAction = true
button.changesSelectionAsPrimaryAction = true UIToolTipInteraction
let toolTipInteraction = UIToolTipInteraction(defaultToolTip: string)
view.addInteraction(tooltipInteraction) UIControl ToopTip
control.toolTip = "Enable updates" ToolTips: UILabel
label.showsExpansionTextWhenTruncated = true Printing APIs
<key>UIApplicationSupportsPrintCommand</key>
</true> Print Support
func printContent(_ sender: Any?) {
let printInteractionController = UIPrintInteractionController.shared
...
} Window Subtitle
scene.subtitle = "My subtitle" Behavioral Style
let button = UIButton(configuration: config)
button.preferredBehavioralStyle = .pad Window Tab Opt-Out
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<true/>
<key>UIApplicationSupportsTabbedSceneCollection</key>
<false/>
</dict> UIPointerShape
UIPointerShape.beam(preferredLength:0 axis: .horizontal)
UIPointerShape.beam(preferredLength:0 axis: .vertical) Hidden Cursor
UIPointerStyle.hidden Scene subtitles
let subtitle: String = "..."
let scene: UIScene = ...
scene.subtitle = subtitle ToolTips
// ToolTip Interaction
let imageView: UIImageView = UIImageView(frame: .zero)
let interaction = UIToolTipInteraction(defaultToolTip: "...")
imageView.addInteraction(interaction)
// ToolTips - Label Expansion Text
let label: UILabel = UILabel()
label.text = "..."
label.showsExpansionTextWhenTruncated = true
// ToolTips — On UIControls
let switchControl = UISwitch()
switchControl.toolTip = "..." Primary button
let submitButton = UIButton(type: .system)
submitButton.role = .primary
submitButton.setTitle("Submit", for: .normal) Toggle button with menu
// Toggle button with menu
let toggleButton = UIButton(configuration: .filled(), primaryAction: nil)
toggleButton.configuration?.title = "Points Multiplier"
toggleButton.changesSelectionAsPrimaryAction = true
toggleButton.menu = ...
// Elsewhere...
toggleButton.configuration?.baseBackgroundColor = .systemRed Plain, destructive button
let resetButton = UIButton(configuration: .plain(), primaryAction: nil)
resetButton.configuration?.title = "Reset"
resetButton.role = .destructive
resetButton.tintColor = .systemRed Pop-up button
let popup = UIButton(type: .system)
popup.changesSelectionAsPrimaryAction = true
popup.showsMenuAsPrimaryAction = true
popup.menu = ... iPad behavioral style toggle
let button = UIButton(configuration: .filled(), primaryAction: nil)
button.configuration?.image = UIImage(systemName: "leaf")
button.preferredBehavioralStyle = .pad
button.configuration?.preferredSymbolConfigurationForImage =
UIImage.SymbolConfiguration(pointSize: 60)
button.changesSelectionAsPrimaryAction = true
button.configurationUpdateHandler = colorUpdateHandler Printing
override func printContent(_: Any?) {
...
}
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
if action == #selector(self.printContent(_:)) {
...
} else {
return super.canPerformAction(action, withSender: sender)
}
}
override func target(forAction action: Selector, withSender sender: Any?) -> Any? {
switch action {
case #selector(UIResponder.printContent(_:)):
...
default:
return super.target(forAction: action, withSender: sender)
}
} Resources
Related sessions
-
24 min -
23 min -
27 min -
20 min -
27 min -
38 min -
41 min