Vincent Tourraine

Notes WWDC 2019 : Modernizing Your UI for iOS 13

#dev #iOS

Référence : Session 224 - Modernizing Your UI for iOS 13

Flexible UI


let appearance = UINavigationBarAppearance()

appearance.titleTextAttributes = [.foregroundColor: myAppLabelColor]
appearance.largeTitleTextAttributes = [.foregroundColor: myAppLabelColor]

navigationBar.standardAppearance = appearance

Different layout appearances:

Same for toolbars and tab bars:

Can be customized with view controller navigation item


Pull down to dismiss automatically. Can be customized (for instance, when the user has entered text in the modal, offer to discard or save new content):

class EmailController: UIViewController, UIAdaptivePresentationControllerDelegate {
  func draftDidChange() {
    isModalInPresentation = draft.hasChanges

  func presentationControllerDidAttemptToDismiss(_: UIPresentationController) {
    // Present action sheet

Appearance callbacks: for page and form sheets with iOS 13 SDK, the presenting view controller is not removed from the view hierarchy, therefore the viewWill/Did/Appear/Disappear methods are not called. Use the new “attempt to dismiss” and other UIPresentationController methods instead. Note that these methods are only called if the controller is dismissed with the gestures. If the controller is dismissed programmatically, you need to handle the corresponding event yourself (with a custom delegate, for instance).

UISearchController: can now hide elements of the search bar (scope, cancel button), search text field exposed

let searchController = UISearchController(searchResultsController: /*...*/)

// Don’t automatically show the cancel button or scope bar
searchController.automaticallyShowsCancelButton = false
searchController.automaticallyShowsScopeBar = false

// Customize appearance of the search text field
let searchField = searchController.searchBar.textField
searchField.textColor = UIColor(named: "MyPinkColor")
searchField.font = UIFont(name: "American Typewriter", size: 18)

The search results controller can now be displayed as soon as the search bar becomes active (for instance, to display a list of filters, like system Mail app)

// Show the search results controller as soon as search is activated
searchController.showsSearchResultsController = true

New UISearchTextField API for tokens (copy, paste, drag and drop)

Creating tokens:

let selectedText = field.textIn(field.selectedTextRange)
let token = UISearchToken(icon: nil, text: selectedText)
field.replaceTextualPortion(of: field.selectedTextRange, with: token, at: field.tokens.count)


Selection gestures in custom text views

UITextInteraction: implement system text-related gestures in custom text view

// Create selection interaction with type .editable or nonEditable
let selectionInteraction = UITextInteraction(for: .editable)
// Assign `textInput` property to your view that implements the UITextInput protocol
selectionInteraction.textInput = textView
// Add the interaction to the view

Multiple selection gestures in tables and collections

optional func tableView(_ tableView: UITableView, shouldBeginMultipleSelectionInteractionAtIndexPath indexPath: IndexPath) -> Bool
optional func tableView(_ tableView: UITableView, didBeginMultipleSelectionInteractionAtIndexPath indexPath: IndexPath)

Editing gestures (undo/redo)

Can opt-out:

public protocol UIResponder {
  public var editingInteractionConfiguration: UIEditingInteractionConfiguration

public enum UIEditingInteractionConfiguration {
  case `default` // System behavior, default
  case none // Disable


Consistent gestures, based on device capabilities:

UIMenu and UIAction

// Create a UIContextMenuInteraction with Some Delegate
let interaction = UIContextMenuInteraction(delegate: self)

// Attach It to Our View


func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configurationForMenuAtLocation location: CGPoint) -> UIContextMenuConfiguration?
let actionProvider = (suggestedActions: [UIMenuElement]) -> UIMenu? {
  let editMenu = UIMenu(title: "Edit...", children: [
    UIAction(title: "Copy") { ... },
    UIAction(title: "Duplicate") { ... }

  return UIMenu(children: [
    UIAction(title: "Share") { ... },
    UIAction(title: "Delete", style: .destructive) { ... }

return UIContextMenuConfiguration(identifier: "unique-ID" as NSCopying, previewProvider: nil, actionProvider: actionProvider)

UITableView and UICollectionView

// UITableViewDelegate
optional func tableView(_ tableView: UITableView, contextMenuConfigurationForRowAtIndexPath indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration?