Adding Delight to Your iOS App

WWDC 2018

Posted by Den on September 19, 2018 · 18 mins read
Adding Delight to Your iOS App

Adding Delight to Your iOS App

WWDC 2018

Adding Delight to Your iOS App

WWDC 2018

External Display Support

  • Add a custom UI for external displays
  • Consider the different display contexts
  • Handle connection changes gracefully

Designing for Multiple Displays

How to support External Display

Handling Connectivity

  • Is there an external display connected ?
  • What happens when the display is connected or disconnected ?
  • How to set up ?
  • When you receive didDisconnectNotification

Change Your App’s Behavior

Handle connection changes with graceful transitions

3 Cores in iOS App

Recipe for Layout-Driven UI

  • Find and track state that affects UI
  • Dirty layout when state changes with setNeedsLayout()
  • Update UI with state in layoutSubViews()

Animations with Layout-Driven Updates

  • .beginFromCurrentState 👍👍👍

Animation API

  • UIViewPropertyAnimator
  • UIView closure API

UIGestureRecognizer

Discrete Gesture

  • Start in the Possible state
  • If they don’t pass go, they move immediately into the Recognized state
  • These are useful for fire and forget interactions in your app
  • But won’t tell you at every phase during the interaction ⚠️

Continuous Gestures

  • Start in the Possible state
  • They begin to be recognized, they move to the Begin state
  • Receiving a continuous stream of events as the gesture moves around
  • When the gesture is complete, it moves to the Ended state

UIPanGestureRecognizer

  • Use translationInView( ) for dragging
  • Use velocityInView( ) for animation handoffs

Get your app responsive quickly

Anatomy of a Launch

  • Process Forking
  • Dynamic Linking
  • UI Construction
  • First Frame
  • Extended Launch Actions

Process Forking

  • Man pages for fork and exec with POSIX ?? 😱
  • iOS will take care of process forking for you 😆

Dynamic Linking

  • 40~50 % of typical app launch time
    1. Allocating memory for execution
    2. Linking libraries and frameworks
    3. Initialization of Swift, Objective-C, Foundations, etc
    4. Static object initialization
  • Best Practice ⭐️
    - Avoid code duplication
    - Limit use of 3rd-party libraries
    - Avoid static initializers

UI Construction

  • Return quickly from 
    application(_:willFinishLaunchingWithOptions:)
    application(_:didFinishLaunchingWithOptions:)
    applicationDidBecomeActive(_:)
  • Because UIKit waits for you to return from these functions 
    before we can mark your app as active 😱
  • Avoid writing to disk & Avoid loading very large data sets
    Blocking, require a sys call
  • Check database hygiene
    Clean data (core data), when you update your app 🛁

First Frame

  • Core Animation renders your first frame
  • Text drawing
  • Image loading and decompression
  • Only prepare the UI you need ⚠️
  • Avoid hiding views and layer ⚠️
    Even when views and layers are hidden, they still have a cost.

Extended Launch Actions

  • Prioritize loading content that should be visible at launch
  • Design for poor network conditions

ABM (Always Be Measuring )

  • Use Time Profiler to measure your launch
  • Measure regularly
  • Use statistical averages

Laser-Fast Launches

  • Get responsive fast
  • Use only what you need
  • Measure, measure, measure

Why Is My App Slow ?

  • 2 Solutions ( Computation, Graphics )

Solution 1: Computation

  • UICollectionView and UITableview prefetching
  • Push more work to background queues
    - Network and file system access
    - Image drawing
    - Text sizing

Solution 2: Graphics

  • Complex Graphics
    - Visual effects (blur, vibrancy are expensive)
    - Masking

Smooth Scrolling

  • Run Time Profiler and Core Animation instruments on your app
  • Keep work off the main thread
  • Use visual effects and masking sparingly

Continuing with Continuity

  • Implement Handoff
  • Delight your users
  • Integrate with Spotlight search, Siri Shortcuts, and more

A Magical Experience

  • Seamlessly transition activities between devices
  • Work between iOS, macOS, and watchOS
  • Doesn’t require an Internet connection
  • It’s easy to set up !

How could you use Handoff ?

NSUserActivity

  • Originating Device
  • Continuing device
    - App must declare support for activity type
    - Implement these UIApplicationDelegate functions

Continuation Streams

  • Set supportsContinuationStreams = true
  • Call on the continuing device
  • Call back on the originating device

Document-Based Apps

  • Get this for free !
  • UIDocument / NSDocument automatically create NSUserActivity objects
  • Supports documents in iCloud
  • Configure your Info.plist

Native App-to-Web Browser Handoff

  • Set webpageURL property on the user activity
  • Configure list of approved app IDs on web server
  • Continuing app must opt in with an associated-domains entitlement

Web Browser-to-Native App Handoff

  • Configure list of approved app IDs on web server
  • Continuing app must opt in with an associated-domains entitlement

Debugging like a Pro

  • The Detective Mindset
  • Misplaced Views and view Controllers
  • State issues
  • Memory issues
  • Xcode View Debugger and Memory Debugger
  • LLDB expr and dump

Think like a Detective

  • Verify your assumptions
  • Look for clues
  • Test your hunches
  • Example

Loading a View or View Controller


Debugging State Issues

  • LLDB’s expr command
  • Run arbitrary code in the debugger !
  • expo myStruct.doSomething( )

dump

-[NSObject _ivarDescription]

Breakpoints

  • Pause the program
  • Commands

Debugging Memory Issues