MacKuba

Kuba Suder's blog on Mac & iOS development

Modernizing Your UI for iOS 13

Categories: UIKit, WWDC 19 0 comments Watch the video

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() and presentationControllerDidDismiss() are called before/after dismiss animation

Share extension views are also presented as sheets by default

Search

UISearchController:

  • automaticallyShowsCancelButton – toggling cancel button
  • automaticallyShowsScopeBar – toggling the segmented control below
  • searchBar.textField – for customizing the search text field
  • showsSearchResultsController = 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 in
  • tableView(_: 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 menu
  • UIMenu – groups a list of UIActions and possibly nested UIMenus into a menu
  • there's also UICommand – like UIAction, 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 menu
  • previewProvider
  • actionProvider – a closure that returns a UIMenu 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



Leave a comment

*

*
This will only be used to display your Gravatar image.

*

What property can you use on iOS to get a unique device ID that the user can reset in Settings?

*