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” methods instead.

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?