data flow through swiftui - devstreaming-cdn.apple.com · redistribution or public display not...

122
#WWDC19 © 2019 Apple Inc. All rights reserved. Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj Ramamurthy, SwiftUI Engineer Data Flow Through SwiftUI

Upload: others

Post on 27-Jul-2020

4 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

#WWDC19

© 2019 Apple Inc. All rights reserved. Redistribution or public display not permitted without written permission from Apple.

Luca Bernardi, SwiftUI Engineer Raj Ramamurthy, SwiftUI Engineer

•Data Flow Through SwiftUI

Page 2: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

•Principles of Data Flow •Anatomy of an Update •Understanding Your Data

Page 3: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

•Principles of Data Flow •Anatomy of an Update •Understanding Your Data

Page 4: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

•Principles of Data Flow •Anatomy of an Update •Understanding Your Data

Page 5: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

What is data?

Page 6: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

Tools for Data Flow

Property

@Binding

BindableObject

@Environment

@State

Page 7: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

Data Access as a Dependency

PlayerView isPlaying: Bool

Page 8: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

Data Access as a Dependency

PlayerView isPlaying: Bool

Page 9: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

Data Access as a Dependency

PlayerView false

Page 10: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

Data Access as a Dependency

falsePlayerViewPlayerView

Page 11: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

Data Access as a Dependency

truePlayerView

Page 12: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

Source of Truth

Page 13: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

Source of Truth

accentColor: Color

isPlaying: Bool

store: MessageStore

post: PhotoPost

Page 14: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

Duplicated Source of Truth

View

ViewView

isPlaying: Bool isPlaying: Bool

Page 15: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

Duplicated Source of Truth

View

ViewView

isPlaying: Bool isPlaying: Bool

Page 16: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

Duplicated Source of Truth

View

ViewView

isPlaying: BoolisPlaying: Bool

Page 17: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

Single Source of Truth

View

ViewView

isPlaying: Bool

Page 18: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

Single Source of Truth

View

ViewView

isPlaying: Bool

Page 19: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

Single Source of Truth

View

ViewView

isPlaying: Bool

Page 20: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj
Page 21: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

struct PlayerView : View { let episode: Episode

var body: some View { VStack { Text(episode.title) Text(episode.showTitle).font(.caption).foregroundColor(.gray) } } }

Page 22: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

struct PlayerView : View { let episode: Episode

var body: some View { VStack { Text(episode.title) Text(episode.showTitle).font(.caption).foregroundColor(.gray) } } }

Page 23: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

struct PlayerView : View { let episode: Episode

var body: some View { VStack { Text(episode.title) Text(episode.showTitle).font(.caption).foregroundColor(.gray) } } }

Page 24: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

struct PlayerView : View { let episode: Episode

var body: some View { VStack { Text(episode.title) Text(episode.showTitle).font(.caption).foregroundColor(.gray) } } }

Page 25: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

struct PlayerView : View { let episode: Episode var isPlaying: Bool

var body: some View { VStack { Text(episode.title) Text(episode.showTitle).font(.caption).foregroundColor(.gray)

Image(systemName: isPlaying ? "pause.circle" : "play.circle") } } }

Page 26: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

struct PlayerView : View { let episode: Episode var isPlaying: Bool

var body: some View { VStack { Text(episode.title) Text(episode.showTitle).font(.caption).foregroundColor(.gray)

Image(systemName: isPlaying ? "pause.circle" : "play.circle") } } }

Page 27: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

struct PlayerView : View { let episode: Episode var isPlaying: Bool var body: some View { VStack { Text(episode.title) Text(episode.showTitle).font(.caption).foregroundColor(.gray)

Button(action: { self.isPlaying.toggle() }) { Image(systemName: isPlaying ? "pause.circle" : "play.circle") } } } }

Page 28: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

struct PlayerView : View { let episode: Episode var isPlaying: Bool var body: some View { VStack { Text(episode.title) Text(episode.showTitle).font(.caption).foregroundColor(.gray)

Button(action: { self.isPlaying.toggle() }) { Image(systemName: isPlaying ? "pause.circle" : "play.circle") } } } }

Page 29: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

struct PlayerView : View { let episode: Episode var isPlaying: Bool var body: some View { VStack { Text(episode.title) Text(episode.showTitle).font(.caption).foregroundColor(.gray)

Button(action: { self.isPlaying.toggle() }) { Image(systemName: isPlaying ? "pause.circle" : "play.circle") } } } }

Cannot use mutating member on immutable value: 'self' is immutable

Page 30: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

struct PlayerView : View { let episode: Episode @State private var isPlaying: Bool = false var body: some View { VStack { Text(episode.title) Text(episode.showTitle).font(.caption).foregroundColor(.gray)

Button(action: { self.isPlaying.toggle() }) { Image(systemName: isPlaying ? "pause.circle" : "play.circle") } } } }

Page 31: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

struct PlayerView : View { let episode: Episode @State private var isPlaying: Bool = false var body: some View { VStack { Text(episode.title) Text(episode.showTitle).font(.caption).foregroundColor(.gray)

Button(action: { self.isPlaying.toggle() }) { Image(systemName: isPlaying ? "pause.circle" : "play.circle") } } } }

false

Page 32: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

struct PlayerView : View { let episode: Episode @State private var isPlaying: Bool = false var body: some View { VStack { Text(episode.title) Text(episode.showTitle).font(.caption).foregroundColor(.gray)

Button(action: { self.isPlaying.toggle() }) { Image(systemName: isPlaying ? "pause.circle" : "play.circle") } } } }

false

Page 33: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

struct PlayerView : View { let episode: Episode @State private var isPlaying: Bool = false var body: some View { VStack { Text(episode.title) Text(episode.showTitle).font(.caption).foregroundColor(.gray)

Button(action: { self.isPlaying.toggle() }) { Image(systemName: isPlaying ? "pause.circle" : "play.circle") } } } }

true

Page 34: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

Wraps property access with additional behavior

What’s New in Swift WWDC 2019

Modern Swift API Design Thursday, 2:00

Property Wrapper

Page 35: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

@State Property Wrapper

@State private var isPlaying: Bool = false

PlayerView

SwiftUI

Page 36: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

@State Property Wrapper

@State private var isPlaying: Bool = false

PlayerView isPlaying = false

SwiftUI

Page 37: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

Anatomy of a View Update

PlayerView

ButtonTextText

SwiftUI isPlaying = false

Page 38: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

PlayerView

TextText

SwiftUI isPlaying = false

Anatomy of a View Update

Button

Page 39: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

PlayerView

TextText

SwiftUI isPlaying = false

Anatomy of a View Update

isPlaying = true

Button

Page 40: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

Anatomy of a View Update

PlayerView

SwiftUI

ButtonTextText

isPlaying = true

Page 41: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

Anatomy of a View Update

PlayerView

ButtonTextText

SwiftUI isPlaying = true

PlayerView

ButtonTextText

Page 42: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

Anatomy of a View Update

PlayerView

ButtonTextText

SwiftUI isPlaying = true

Page 43: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

Every @State is a source of truth.

Page 44: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

Views are a function of state, not of a sequence of events.

Page 45: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

!

Page 46: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

!

SwiftUI

Page 47: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

!User Interaction

SwiftUI

Action

Page 48: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

!User Interaction

SwiftUI

Action

Page 49: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

!User Interaction

SwiftUI

Action

State

Mutation

Page 50: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

!User Interaction

SwiftUI

Action

State

Mutation

Page 51: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

!User Interaction

SwiftUI

Action

State

Mutation

View

Updates

Page 52: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

!User Interaction

SwiftUI

Action

State

Mutation

View

Updates

Page 53: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

!User Interaction

SwiftUI

Action

State

Mutation

View

Updates

Render

Page 54: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

struct PlayerView : View { let episode: Episode @State private var isPlaying: Bool = false var body: some View { VStack { Text(episode.title).foregroundColor(isPlaying ? .white : .gray) Text(episode.showTitle).font(.caption).foregroundColor(.gray)

Button(action: { self.isPlaying.toggle() }) { Image(systemName: isPlaying ? "pause.circle" : "play.circle") } } } }

Page 55: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

struct PlayerView : View { let episode: Episode @State private var isPlaying: Bool = false var body: some View { VStack { Text(episode.title).foregroundColor(isPlaying ? .white : .gray) Text(episode.showTitle).font(.caption).foregroundColor(.gray)

Button(action: { self.isPlaying.toggle() }) { Image(systemName: isPlaying ? "pause.circle" : "play.circle") } } } }

Page 56: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

struct PlayerView : View { let episode: Episode @State private var isPlaying: Bool = false var body: some View { VStack { Text(episode.title).foregroundColor(isPlaying ? .white : .gray) Text(episode.showTitle).font(.caption).foregroundColor(.gray)

Button(action: { self.isPlaying.toggle() }) { Image(systemName: isPlaying ? "pause.circle" : "play.circle") } } } }

Page 57: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

struct PlayerView : View { let episode: Episode @State private var isPlaying: Bool = false var body: some View { VStack { Text(episode.title).foregroundColor(isPlaying ? .white : .gray) Text(episode.showTitle).font(.caption).foregroundColor(.gray)

Button(action: { self.isPlaying.toggle() }) { Image(systemName: isPlaying ? "pause.circle" : "play.circle") } } } }

Page 58: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

struct PlayerView : View { let episode: Episode @State private var isPlaying: Bool = false var body: some View { VStack { Text(episode.title).foregroundColor(isPlaying ? .white : .gray) Text(episode.showTitle).font(.caption).foregroundColor(.gray)

PlayButton() } } }

Page 59: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

struct PlayerView : View { let episode: Episode @State private var isPlaying: Bool = false var body: some View { VStack { Text(episode.title).foregroundColor(isPlaying ? .white : .gray) Text(episode.showTitle).font(.caption).foregroundColor(.gray)

PlayButton() } } }

Page 60: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

struct PlayButton : View { @State private var isPlaying: Bool = false

var body: some View { Button(action: { self.isPlaying.toggle() }) { Image(systemName: isPlaying ? "pause.circle" : "play.circle") } } }

Page 61: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

struct PlayButton : View { @State private var isPlaying: Bool = false

var body: some View { Button(action: { self.isPlaying.toggle() }) { Image(systemName: isPlaying ? "pause.circle" : "play.circle") } } }

Page 62: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

struct PlayButton : View { @State private var isPlaying: Bool = false

var body: some View { Button(action: { self.isPlaying.toggle() }) { Image(systemName: isPlaying ? "pause.circle" : "play.circle") } } }

Page 63: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

@Binding Property Wrapper

Read and write without ownership

Derivable from @State

@Binding var isPlaying: Bool

Page 64: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

struct PlayButton : View { @Binding var isPlaying: Bool var body: some View { Button(action: { self.isPlaying.toggle() }) { Image(systemName: isPlaying ? "pause.circle" : "play.circle") } } }

Page 65: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

struct PlayButton : View { @Binding var isPlaying: Bool var body: some View { Button(action: { self.isPlaying.toggle() }) { Image(systemName: isPlaying ? "pause.circle" : "play.circle") } } }

Page 66: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

struct PlayerView : View { let episode: Episode @State private var isPlaying: Bool = false var body: some View { VStack { Text(episode.title).foregroundColor(isPlaying ? .white : .gray) Text(episode.showTitle).font(.caption).foregroundColor(.gray)

PlayButton(isPlaying: $isPlaying) } } }

Page 67: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

struct PlayerView : View { let episode: Episode @State private var isPlaying: Bool = false var body: some View { VStack { Text(episode.title).foregroundColor(isPlaying ? .white : .gray) Text(episode.showTitle).font(.caption).foregroundColor(.gray)

PlayButton(isPlaying: $isPlaying) } } }

Page 68: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

struct PlayerView : View { let episode: Episode @State private var isPlaying: Bool = false var body: some View { VStack { Text(episode.title).foregroundColor(isPlaying ? .white : .gray) Text(episode.showTitle).font(.caption).foregroundColor(.gray)

PlayButton(isPlaying: $isPlaying) } } }

Page 69: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

PlayerViewController

Page 70: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

PlayerView

PlayerViewController isPlaying

PlayButton

isPlaying

Page 71: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

PlayerView

PlayerViewController isPlaying

PlayButton

isPlaying

Page 72: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

PlayerView

PlayerViewController

isPlayingisPlaying

Page 73: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

PlayerView

PlayerViewController

isPlaying

PlayButton

isPlaying

Page 74: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

PlayerView

isPlaying

PlayButton

isPlaying

Page 75: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

API

Page 76: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

public struct Toggle<Label> : View { public init( isOn: Binding<Bool>, label: () -> Label ) }

public struct TextField : View { init( _ text: Binding<String> ) }

public struct Slider : View { public init<V : BinaryFloatingPoint>( value: Binding<V> ) }

API

Page 77: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

Views are for Data

Layout Visual Effects Navigation

Gestures Drawing Animations

Page 78: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

// Animated Changes

struct PlayButton : View { @Binding var isPlaying: Bool var body: some View { Button(action: { self.isPlaying.toggle() }) { Image(systemName: isPlaying ? "pause.circle" : "play.circle") } } }

Page 79: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

// Animated Changes

struct PlayButton : View { @Binding var isPlaying: Bool var body: some View { Button(action: { withAnimation { self.isPlaying.toggle() } }) { Image(systemName: isPlaying ? "pause.circle" : "play.circle") } } }

Page 80: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

// Animated Changes

struct PlayButton : View { @Binding var isPlaying: Bool var body: some View { Button(action: { withAnimation { self.isPlaying.toggle() } }) { Image(systemName: isPlaying ? "pause.circle" : "play.circle") } } }

Page 81: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

Raj Ramamurthy, SwiftUI Engineer

•Working With External Data

Page 82: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

Tools for Data Flow

@Binding

BindableObject

@Environment

@State

Property

Page 83: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

!

SwiftUI

Page 84: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

!User Interaction

SwiftUI

Action

State

Mutation

View

Updates

Render

Page 85: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

User Interaction

SwiftUI

Action

State

Mutation

View

Updates

Render

!🔔⏰

Page 86: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

User Interaction

SwiftUI

Action

State

Mutation

View

Updates

Render

!🔔⏰

Publisher

Page 87: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

Combine Publisher

Single abstraction

Main thread: use .receive(on:)

Introducing Combine and Advances in Foundation Thursday, 10:00

Combine in Practice Thursday, 2:00

Page 88: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

struct PlayerView : View { let episode: Episode @State private var isPlaying: Bool = true @State private var currentTime: TimeInterval = 0.0

var body: some View { VStack { Text(episode.title).foregroundColor(isPlaying ? .white : .gray) Text(episode.showTitle).font(.caption).foregroundColor(.gray)

PlayButton(isPlaying: $isPlaying)

Text("\(currentTime, formatter: currentTimeFormatter)") } } }

Page 89: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

struct PlayerView : View { let episode: Episode @State private var isPlaying: Bool = true @State private var currentTime: TimeInterval = 0.0

var body: some View { VStack { Text(episode.title).foregroundColor(isPlaying ? .white : .gray) Text(episode.showTitle).font(.caption).foregroundColor(.gray)

PlayButton(isPlaying: $isPlaying)

Text("\(currentTime, formatter: currentTimeFormatter)") } } }

Page 90: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

struct PlayerView : View { let episode: Episode @State private var isPlaying: Bool = true @State private var currentTime: TimeInterval = 0.0

var body: some View { VStack { // … Text("\(playhead, formatter: currentTimeFormatter)") } .onReceive(PodcastPlayer.currentTimePublisher) { newCurrentTime in self.currentTime = newCurrentTime } } }

Page 91: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

struct PlayerView : View { let episode: Episode @State private var isPlaying: Bool = true @State private var currentTime: TimeInterval = 0.0

var body: some View { VStack { // … Text("\(playhead, formatter: currentTimeFormatter)") } .onReceive(PodcastPlayer.currentTimePublisher) { newCurrentTime in self.currentTime = newCurrentTime } } }

Page 92: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

BindableObject Protocol

External

Reference type

Great for the model you already have

Page 93: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

class PodcastPlayerStore { var currentTime: TimeInterval var isPlaying: Bool var currentEpisode: Episode

func advance() { ... } func skipForward() { ... } func skipBackward() { ... } }

Page 94: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

class PodcastPlayerStore : BindableObject {

var didChange = PassthroughSubject<Void, Never>() // …

func advance() { currentEpisode = nextEpisode currentTime = 0.0 // Notify subscribers that the player changed didChange.send() } }

Page 95: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

class PodcastPlayerStore : BindableObject {

var didChange = PassthroughSubject<Void, Never>() // …

func advance() { currentEpisode = nextEpisode currentTime = 0.0 // Notify subscribers that the player changed didChange.send() } }

Page 96: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

Creating Dependencies on BindableObject

ViewModel

Page 97: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

Creating Dependencies on BindableObject

ViewModel

@ObjectBinding

Page 98: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

Creating Dependencies on BindableObject

ViewModel

@ObjectBinding

struct MyView :aView {a @ObjectBinding var model: MyModelObject ... }a

MyView(model: modelInstance)

Page 99: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

Creating Dependencies on BindableObject

ViewModel

@ObjectBinding

struct MyView :aView {a @ObjectBinding var model: MyModelObject ... }a

MyView(model: modelInstance)

Page 100: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

Creating Dependencies on BindableObject

View

@ObjectBinding

Model

struct MyView :aView {a @ObjectBinding var model: MyModelObject ... }a

MyView(model: modelInstance)

Page 101: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

Creating Dependencies on BindableObject

View

@ObjectBinding

Model

struct MyView :aView {a @ObjectBinding var model: MyModelObject ... }a

MyView(model: modelInstance)

Page 102: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

Creating Dependencies on BindableObject

View

@ObjectBinding

Model

Pass directly with @ObjectBinding

Automatic dependency tracking

struct MyView :aView {a @ObjectBinding var model: MyModelObject ... }a

MyView(model: modelInstance)

Page 103: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

Creating Dependencies Indirectly

View

View

View

Model

Page 104: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

Creating Dependencies Indirectly

View

View

View

Environment

Environment

Environment

Model

Page 105: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

Creating Dependencies Indirectly

Environment

Environment

Environment

.environmentObject()

Model

View

View

View

Page 106: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

Creating Dependencies Indirectly

Environment

Environment

Environment

@EnvironmentObject

.environmentObject()

Model

View

View

View

Page 107: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

Creating Dependencies Indirectly

Environment

Environment

Environment

.environmentObject()

Model

@EnvironmentObject

View

View

View@EnvironmentObject

Page 108: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

Creating Dependencies Indirectly

Environment

Environment

Environment

.environmentObject()

Model

@EnvironmentObject

View

View

View@EnvironmentObject

Page 109: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

struct PlayerView : View { @EnvironmentObject var player: PodcastPlayerStore var body: some View { VStack { Text(player.currentEpisode.title) .foregroundColor(isPlaying ? .white : .gray) Text(player.currentEpisode.showTitle) .font(.caption).foregroundColor(.gray) PlayButton(isPlaying: $player.isPlaying) Text("\(player.currentTime, formatter: playheadTimeFormatter)") } } }

Page 110: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

struct PlayerView : View { @EnvironmentObject var player: PodcastPlayerStore var body: some View { VStack { Text(player.currentEpisode.title) .foregroundColor(isPlaying ? .white : .gray) Text(player.currentEpisode.showTitle) .font(.caption).foregroundColor(.gray) PlayButton(isPlaying: $player.isPlaying) Text("\(player.currentTime, formatter: playheadTimeFormatter)") } } }

Page 111: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

@ObjectBinding

View View View View View View

Model

Page 112: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

@ObjectBinding

View View View View View View

Model

Page 113: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

@EnvironmentObject

View View View View View View

Model Environment

Page 114: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

@EnvironmentObject

View View View View View View

Model Environment

Page 115: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

Environment

•Data applicable to an entire hierarchy •Convenience for indirection •Accent color, right-to-left, and more

Page 116: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

Sources of Truth

@State BindableObject

View-local Value

Framework Managed

External Reference

Developer Managed

Page 117: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

Building Reusable Components

Read-only: Swift property, Environment

Read-write: @Binding

Prefer immutable access

Page 118: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

@Binding

First class reference to data

Great for reusability

Use $ to derive from source

@State @ObjectBinding

@Binding

@Binding

Page 119: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

Using State Effectively

Limit use if possible

Use derived Binding or value

Prefer BindableObject for persistence

Example: Button highlighting

Page 120: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

Next Steps

Minimize sources of truth

Understand your data

Build a great app!

Page 121: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj

More Informationdeveloper.apple.com/wwdc19/226

SwiftUI Essentials WWDC 2019

Integrating SwiftUI Thursday, 3:00

Building Custom Views with SwiftUI Friday, 9:00

Page 122: Data Flow Through SwiftUI - devstreaming-cdn.apple.com · Redistribution or public display not permitted without written permission from Apple. Luca Bernardi, SwiftUI Engineer Raj