Adding Delight to Your iOS App
Adding Delight to Your iOS App
Adding Delight to Your iOS App
External Display Support
- Add a custom UI for external displays
- Consider the different display contexts
- Handle connection changes gracefully
- Is there an external display connected ?
- What happens when the display is connected or disconnected ?
- When you receive
didDisconnectNotification
- Find and track state that affects UI
- Dirty layout when state changes with
setNeedsLayout()
- Update UI with state in
layoutSubViews()
.beginFromCurrentState
👍👍👍
- UIViewPropertyAnimator
- UIView closure API
UIGestureRecognizer
- 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 ⚠️
- 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
- Use
translationInView( )
for dragging - Use
velocityInView( )
for animation handoffs
- 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 )
UICollectionView
and UITableview
prefetching- Push more work to background queues
- Network and file system access
- Image drawing
- Text sizing
- Complex Graphics
- Visual effects (blur, vibrancy are expensive)
- Masking
- 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
- 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 ?
- Continuing device
- App must declare support for activity type
- Implement these UIApplicationDelegate
functions
- Set
supportsContinuationStreams = true
- Call on the continuing device
- Call back on the originating device
- 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
- Configure list of approved app IDs on web server
- Continuing app must opt in with an associated-domains entitlement
- 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
- LLDB’s
expr
command - Run arbitrary code in the debugger !
expo myStruct.doSomething( )
dump
- Pause the program
- Commands