Vincent Tourraine
Blog

Notes WWDC 2019 : Modernizing Your UI for iOS 13

#dev #iOS

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

Flexible UI

Bars

let appearance = UINavigationBarAppearance()
appearance.configureWithOpaqueBackground()

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

Presentations

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)

Gestures

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
textView.addInteraction(selectionInteraction)

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
}

UIContextMenuInteraction

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
menuSourceView.addInteraction(interaction)

UIContextMenuInteractionDelegate

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") { ... },
    editMenu,
    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?