WWDC 19
Modernizing Your UI for iOS 13
Launch images are deprecated – starting from April 2020 App Store will require apps to have a launch storyboard
When a new device with new screen size is launched, apps built on iOS 13 and above that aren’t rebuilt on latest SDK will always be displayed in native resolution, not in some kind of compatibility mode like before. This means your app needs to support being rendered in unexpected resolutions – for iPad apps this includes split screen modes.
Customizing navigation title appearance (large titles):
UINavigationBarAppearance()
.configureWithOpaqueBackground()
.titleTextAttributes
.largeTitleTextAttributes
navigationBar.standardAppearance
– settings to use as default
navigationBar.compactAppearance
– on smaller iPhones in landscape
navigationBar.scrollEdgeAppearance
– when scrolled to the top (default is now to have transparent background below the large title)
navigationBar.buttonAppearance
– appearance for normal navigation bar buttons
navigationBar.doneButtonAppearance
– appearance for “done” (bold) navigation bar buttons
You can customize e.g. title color per screen by overriding the appearance in VC’s navigationItem.***Appearance
.
Same for:
UIToolbar
⭢UIToolbarAppearance
UITabBar
⭢UITabBarAppearance
Additional options for tab bars:
tabBar.stackedLayoutAppearance
– default
tabBar.inlineLayoutAppearance
– on iPads
tabBar.compactLayoutAppearance
– on smaller phones
Sheets - new default presentation style for modals
UIModalPresentationStyle
.pageSheet
and .formSheet
no longer render as full screen in compact width + regular height layout (i.e. iphone portrait)
On iPads page sheets also have an updated design, the default width follows the “readable width” and depends on font size
If a page sheet opens another page sheet on ipad, they form a stack
Default style is now “automatic” and shows a page sheet for custom VCs, or chooses display mode depending on configuration for system modals
Set presentation style explicitly to .fullScreen
to opt out
Popovers also display as new-style sheets in compact width
The "view will/did appear/disappear" callbacks are not called on the presenting (parent) view if the modal appears as a sheet, since it doesn’t completely disappear
To prevent a sheet from being pulled down:
- set
isModalInPresentation = true
- delegate method
presentationControllerDidAttemptToDismiss()
is called if the user tries to pull the sheet down - you can also implement
presentationControllerShouldDismiss()
and make the decision there presentationControllerWillDismiss()
andpresentationControllerDidDismiss()
are called before/after dismiss animation
Share extension views are also presented as sheets by default
Search
UISearchController
:
automaticallyShowsCancelButton
– toggling cancel buttonautomaticallyShowsScopeBar
– toggling the segmented control belowsearchBar.textField
– for customizing the search text fieldshowsSearchResultsController = true
– show results immediately (to e.g. show suggestions or favorites)
UISearchTextField
– a UITextField
that supports tokens
let token = UISearchToken(icon: icon, text: "…") field.replaceTextualPortion(of: range, with: token, at: field.tokens.count)
field.textualRange
⭢ range of just the text after all tokens
Gestures
Using system text selecting/editing gestures in custom text views:
let interaction = UITextInteraction(for: .editable) interaction.textInput = textView textView.addInteraction(interaction)
Table/collection view multi-selection:
- tables & collection views now allow quick multi-selection by dragging two fingers across the list
- on iPads with external keyboards also works with shift+select
tableView(_: shouldBeginMultipleSelectionInteractionAtIndexPath:)
– return true to opt intableView(_: didBeginMultipleSelectionInteractionAtIndexPath:)
– update UI when the user turns on edit mode
New 3-finger editing gestures: copy, paste, undo & redo
Your app gets them automatically if it uses UndoManager
Set UIResponder.editingInteractionConfiguration = .none
to disable if this conflicts with existing gestures in your app
Context menus (replaces old 3D Touch peek & pop actions):
Lets you present a rich preview of content + menus with complex hierarchies
iOS adapts the exact layout depending on the context (portrait iPhone / landscape iPhone / iPad)
In Catalyst apps it renders as a Mac context menu
Menus are built with UIMenu
and UIAction
objects
UIMenus
are hierarchical, so they can contain other UIMenus
as submenus
UIAction
– a named action with a title and optionally an image, which takes a block to execute when it's selected in the menuUIMenu
– groups a list ofUIActions
and possibly nestedUIMenus
into a menu- there's also
UICommand
– likeUIAction
, but it takes a selector instead of a block and passes it through the responder chain
Adding to a view:
let interaction = UIContextMenuInteraction(delegate: self) image.addInteraction(interaction)
Delegate protocol requires one method:
func contextMenuInteraction(_ interaction: configurationForMenuAtLocation:) -> UIContextMenuConfiguration?
Return nil if context menu should not be displayed
UIContextMenuConfiguration
takes 3 parameters:
identifer
– an id for you to identify this specific context menupreviewProvider
actionProvider
– a closure that returns aUIMenu
with a list of actions
→ receives a list of system-provided “suggested actions” as a parameter that you can include
You can customize the context menu’s animation, the look and location of the preview (UITargetedPreview
), etc.
In table & collection views, context menus on table cells can be enabled easily using:
tableView(_: contextMenuConfigurationForForAtIndexPath: point:) -> UIContextMenuConfiguration?
Peek & pop (UIViewControllerPreviewing
) is deprecated