Slide 1

Slide 1 text

݈߁తͳ.77. ॻ͍ͯ·͔͢ʁ d.77.Ξϯνύλʔϯूd )FBMUI4XJGU.FFUVQ CZ XJUI'J/$

Slide 2

Slide 2 text

!UBLBTFL w GSFFMBODFJ04&OHJOFFS w 'J/$͞ΜͰ͓࢓ࣄ͍͍ͤͯͨͩͯ͞·͢ w ɹ!UBLBTFL w ɹUBLBTFL w ɹUBLBTFL

Slide 3

Slide 3 text

!UBLBTFL w /PUJGXJGU
 IUUQTHJUIVCDPNUBLBTFL/PUJGXJGU
 /4/PUJpDBUJPOͷVTFS*OGPΛ
 4XJGUZʹѻ͏ϚΠΫϩϥΠϒϥϦ w "DUJPO$MPTVSBCMF
 IUUQTHJUIVCDPNUBLBTFL"DUJPO$MPTVSBCMF
 UBSHFUBDUJPOΛ౉͢ॲཧΛ
 4XJGUZͳΫϩʔδϟͰॻ͚Δ
 ϚΠΫϩϥΠϒϥϦ (JU)VCͰ
 044ϥΠϒϥϦ΋࡞ͬͯ·͢

Slide 4

Slide 4 text

͓͞Β͍ .77.ͱ͸

Slide 5

Slide 5 text

.PEFM 7JFX.PEFM 7JFX %BUB #JOEJOH $PNNBOET ɹ%BUB#JOEJOHͷ࣮ݱͷͨΊʹ͸ɺJ04ͷ৔߹ ɹɹ'31ϥΠϒϥϦ 3Y4XJGU 3FBDUJWF$PDPB ΍ ɹɹσʔλόΠϯσΟϯάϥΠϒϥϦ 4XJGU#POE ͷ ɹɹαϙʔτ͕ඞཁ ɹ ˞'J/$Ͱ͸ݱࡏ4XJGU#POEΛར༻

Slide 6

Slide 6 text

ຊ୊

Slide 7

Slide 7 text

͜Ε͔Β
 ෆ݈߁ͳ7JFX.PEFMΛ
 ਍࡯͠·͢

Slide 8

Slide 8 text

Ͱ͠Ό͹Γ7JFX.PEFM Χϧςᶃ


Slide 9

Slide 9 text

class MyViewModel { weak var view: MyView? func doSomething(fuga: Fuga) { guard let view = view else { return } if view.isHoge { view.doSomething(fuga) } } } class MyView { func awakeFromNib() { viewModel.view = self } } Ͱ͠Ό͹Γ7JFX.PEFM ঱ঢ় 7JFX.PEFM͕7JFX΁ͷࢀরΛ࣋ͬͯɺ௚઀ૢ࡞͢Δ

Slide 10

Slide 10 text

Ͱ͠Ό͹Γ7JFX.PEFM පࠜ 
 ࠜຊతʹઃܭ͕͓͔͍͠ w 7JFXʹमਖ਼͕ೖͬͨΒ7JFX.PEFM΋मਖ਼͠ͳ͖Όʜ w ͔ͤͬ͘ͷ.77.ύλʔϯ͕୆ແͩ͠ʂ w ʜͱ͍͏͔ɺ͜Ε.77.ʹͳͬͯͳ͍

Slide 11

Slide 11 text

ґଘͷํ޲͸ 7JFXɹɹ7JFX.PEFM 7JFX.PEFMɹɹ.PEFM Ҿ༻"SDIJUFDUJOH"OESPJEʜ5IFDMFBOXBZ 
 IUUQGFSOBOEPDFKBTDPNBSDIJUFDUJOHBOESPJEUIFDMFBOXBZ 7JFX.PEFM 7JFX σʔλόΠϯσΟϯά

Slide 12

Slide 12 text

Ͱ͠Ό͹Γ7JFX.PEFM ॲํᝦ w 7JFX.PEFM͸ࣗ෼ࣗ਎ͷঢ়ଶΛมߋ͢Δ͚ͩ w Ͳ͏࢖ΘΕΔ͔͸Ұ੾ؔ஌͠ͳ͍͠ɺ
 ୭ 7JFX ʹόΠϯυ͞Ε͍ͯΔ͔΋஌Βͳ͍
 ʹ7JFXʹґଘ͠ͳ͍
 ʹมߋʹڧ͍ 7JFX.PEFMˠ7JFX͸ ඞͣόΠϯσΟϯάͰܨ͙

Slide 13

Slide 13 text

class MyViewModel { let fuga = Observable(nil) func didReceiveFuga(fuga: Fuga) { self.fuga.value = fuga } } class MyView { func awakeFromNib() { viewModel.fuga.ignoreNil().observe { [weak self] in self?.doSomething($0) } } } Ͱ͠Ό͹Γ7JFX.PEFM վળྫ

Slide 14

Slide 14 text

ࠞઢ͍ͯ͠Δ 7JFX.PEFM Χϧςᶄ


Slide 15

Slide 15 text

ࠞઢ͍ͯ͠Δ7JFX.PEFM ঱ঢ় 7JFX.PEFM΁ͷίϚϯυ͕
 ɹॲཧͷ׬ྃ࣌ʹ࣮ߦ͢ΔΫϩʔδϟΛड͚ͨΓ class MyView { func awakeFromNib() { viewModel.alertMessage.observe { [weak self] in self?.showAlert($0) // ↓Ͳ͕ͬͪຊے!? } } func didTapButton() { viewModel.doSomething(completion: { [weak self] alertMessage in self?.showAlert(alertMessage) // ↑Ͳ͕ͬͪຊے!? }) } } ˠॲཧͷྲྀΕ͕ΧΦεʹʂ BMFSU.FTTBHF 0CTFSWBCMF4USJOH͕ มߋ͞ΕͨΒൃಈ ͳΜ͔΍ͬͨ݁Ռ BMFSU.FTTBHFΛ ड͚औΔ

Slide 16

Slide 16 text

ࠞઢ͍ͯ͠Δ7JFX.PEFM පࠜ
 ॲཧͷྲྀΕ͕ ੔ཧͰ͖͍ͯͳ͍

Slide 17

Slide 17 text

ࠞઢ͍ͯ͠Δ7JFX.PEFM ॲํᝦ جຊɺ
 7JFXˠ7JFX.PEFM͸ίϚϯυΛୟ͚ͩ͘ 7JFX.PEFMˠ7JFX͸όΠϯυ͢Δ͚ͩ 7JFX.PEFM 7JFX %BUB #JOEJOH $PNNBOET ᶃίϚϯυ ᶄঢ়ଶมߋ ᶅঢ়ଶ൓ө †એݴతʹهड़

Slide 18

Slide 18 text

Ψϥεͷ7JFX.PEFM Χϧςᶅ


Slide 19

Slide 19 text

class MyViewModel { let text = Observable("") let textLength = Observable(0) } vm.text.value = "ͳΜ͔௕͍ςΩετ" vm.text // "ͳΜ͔௕͍ςΩετ" vm.textLength // 0 ←!!?!!? Ψϥεͷ7JFX.PEFM ঱ঢ় յΕͦ͏ͳ0CTFSWBCMF͹͔ΓूΊͯ͠·͏

Slide 20

Slide 20 text

Ψϥεͷ7JFX.PEFM පࠜ
 ঢ়ଶͷओैؔ܎Λ
 એݴతʹදݱͰ͖͍ͯͳ͍ w UFYUΛมߋͨ͠Βɺ
 ͦͷϝιουͰUFYU-FOHUI΋
 มߋ͢ΔΑ͏ʹؾΛ͚ͭΔʁ
 ͍΍͍΍ɺͦΜͳͷਓ͕ؒ
 έΞ͢΂͖͜ͱ͡Όͳ͍͔Βʂ ຖճҪށ͔Β ਫΛ἞·͞ΕͯΔΑ͏ͳ ॏ࿑ಇײ

Slide 21

Slide 21 text

Ψϥεͷ7JFX.PEFM ॲํᝦ $PMEͳ0CTFSWBCMFΛ࢖͏ )PU
 0CTFSWBCMF $PME
 &WFOU1SPEVDFS

Slide 22

Slide 22 text

class MyViewModel { let text = Observable("") let textLength: EventProducer init() { textLength = text.map { $0.characters.count } } } vm.text // "ͳΜ͔௕͍ςΩετ" vm.textLength // 9 Ψϥεͷ7JFX.PEFM վળྫ ɹUFYU-FOHUI͸NBQ USBOTGPSNJOHPQFSBUPS Λ௨͚ͩ͢ͷ ɹ$PMEͳଘࡏʹ͠ɺ੔߹ੑΛอূ એݴతʹهड़Ͱ͖ͨʂ

Slide 23

Slide 23 text

ઉ଍Βͣͳ
 7JFX.PEFM Χϧςᶆ


Slide 24

Slide 24 text

class MyViewModel { let name = Observable("") let address = Observable("") } let vm = MyViewModel() vm.name.observe { func setUserData() } vm.address.observe { func setUserData() } func setUserData(userId: Int) { userNameLabel.text = vm.name userAddressLabel.text = vm.address } ઉ଍Βͣͳ7JFX.PEFM ঱ঢ় ɹ7JFX.PEFMͷมԽΛड͚औͬͨ7JFX͕ɺ
 ɹվΊͯ7JFX.PEFMͷϓϩύςΟΛࢀর͍ͯ͠Δ OBNFͱBEESFTT ͲͪΒ͕มߋ͞Εͯ΋ ྆ํΛ࢖ͬͯߋ৽ॲཧΛ ߦ͍͍ͨʂ

Slide 25

Slide 25 text

ઉ଍Βͣͳ7JFX.PEFM පࠜ σʔλΛద੾ͳཻ౓ɾ૊Ͱ ౉͍ͯ͠ͳ͍

Slide 26

Slide 26 text

ઉ଍Βͣͳ7JFX.PEFM ॲํᝦ ֤छΦϖϨʔλΛ࢖͍͜ͳ͢ class MyViewModel { let name = Observable("") let address = Observable("") lazy var nameAndAddress: EventProducer<(String, String)> = { return combineLatest(self.name, self.address) }() } let vm = MyViewModel() vm.nameAndAddress.observe { name, address in userNameLabel.text = name userAddressLabel.text = address } IUUQSYNBSCMFTDPNͱ͔ࢀߟʹͳΔΑ OBNFͱBEESFTT͕ λϓϧͰ౉ͬͯ͘Δ

Slide 27

Slide 27 text

؂ಜෆߦಧͳ
 7JFX.PEFM Χϧςᶇ


Slide 28

Slide 28 text

class MyView { var viewType: ViewType func setup(viewType: ViewType) { self.viewType = viewType switch viewType { case .Title: viewModel.title.observe { ... } case .Image: viewModel.image.observe { ... } case .Detail: viewModel.detail.observe { ... } } } } ؂ಜෆߦಧͳ7JFX.PEFM ঱ঢ় 7JFXଆʹঢ়ଶ΍৚݅෼ذ͕͋Δ

Slide 29

Slide 29 text

؂ಜෆߦಧͳ7JFX.PEFM පࠜ
 ঢ়ଶ΍৚݅൑அͷίʔυΛ
 7JFX.PEFMʹҠ͍ͯ͠ͳ͍

Slide 30

Slide 30 text

ͦ΋ͦ΋7JFX.PEFM͸.PEFMͷӨͳͷͰ͢ɻ
 ͦͯ͠·ͨ7JFX͸7JFX.PEFMͷӨͰ΋͋Γ·͢ɻ Ҿ༻.77.ͷ.PEFMʹ·ͭΘΔޡղUIFTFBPGGFSUJMJUZ IUUQVHBZBIBUFCMPKQFOUSZNPEFMNJTUBLF

Slide 31

Slide 31 text

؂ಜෆߦಧͳ7JFX.PEFM ॲํᝦ ʮ7JFX͸7JFX.PEFMͷӨʯΛ పఈͤ͞Δ class MyView { func awakeFromNib() { viewModel.title.observe { ... } viewModel.image.observe { ... } viewModel.detail.observe { ... } } } 7JFX͸Կ΋൑அΛߦΘͣɺ 7JFX.PEFMͷঢ়ଶΛ ໧ʑͱ6*ʹ൓өͤ͞Δ 7JFX.PEFM͸ɺ 7JFXΛ࠶ߏ੒Ͱ͖Δ͚ͩͷ ঢ়ଶ৘ใΛอ࣋͢Δ

Slide 32

Slide 32 text

ਆܦ࣭ͳ
 7JFX.PEFM Χϧςᶈ


Slide 33

Slide 33 text

ਆܦ࣭ͳ7JFX.PEFM ঱ঢ় 7JFX.PEFM͕ঢ়ଶΛࡉ͔࣋ͪ͗ͯ͘͢ΧΦε ɾμΠΞϩάͷදࣔඇදࣔঢ়ଶͱ͔ ɾը໘ભҠͷঢ়ଶͱ͔

Slide 34

Slide 34 text

ਆܦ࣭ͳ7JFX.PEFM පࠜ ʮঢ়ଶʯͱʮشൃੑͷݱ৅ʯΛ ۠ผͰ͖͍ͯͳ͍ ˞شൃੑͷݱ৅ඞͣফ͑Ώ͘΋ͷɻ

Slide 35

Slide 35 text

ਆܦ࣭ͳ7JFX.PEFM ॲํᝦ 0CTFSWBCMF7PJE class MyViewModel { let isUpdated = Observable() private func didSomething() { isUpdated.next() } } 81' 8JOEPXT1SFTFOUBUJPO'PVOEBUJPO ʹ͸ .FTTFOHFSͱ͍͏֓೦͕͋Δ
 7JFX.PEFM͕Πϕϯτͷൃߦͱ͍͏ܗͰ7JFXʹ௨஌͢Δ࢓૊Έ ղܾ͍ͨ͠໰୊͸ಉ͡ʜ ͩͱࢥ͏Μ͚ͩͲɺ 81'ͷ஌ݟ͕ͳ͍ͷͰ ؒҧͬͯͨΒ͢Έ·ͤΜʜ ͱΓ͋͑ͣ 0CTFSWBCMF7PJE͸ศརͰ͢

Slide 36

Slide 36 text

ϝλϘϦοΫγϯυϩʔϜ
 7JFX.PEFM Χϧςᶉ


Slide 37

Slide 37 text

ϝλϘͳ7JFX.PEFM ঱ঢ় 7JFX.PEFM͕
 ɹ ɹ௨৴ॲཧ
 ɹσʔλΩϟογϡ
 ɹ͞·͟·ͳۀ຿ͷϋϯυϦϯά 
 ɹʜΛߦ͍ͬͯΔ

Slide 38

Slide 38 text

ϝλϘͳ7JFX.PEFM පࠜ .PEFMʹ͍ͭͯ ޡղͯ͠·ͤΜ͔

Slide 39

Slide 39 text

ϝλϘͳ7JFX.PEFM ॲํᝦ .PEFM૚Λ͔ͬ͠Γ࡞Ζ͏ .PEFM%"0 %BUB"DDFTT0CKFDU Ͱ͸ͳ͍ .PEFMۀ຿ϩδοΫ ඇ6*,JUͷผϓϥοτϑΥʔϜʹҠ২ͯ͠΋มΘΒͳ͍෦෼ Α͘7JFX$POUSPMMFSʹߦ͘Β͍ॻ͔ΕͯΔ΍ͭ ͋Ε͸΄ͱΜͲ.PEFMʹॻ͘΂͖΋ͷ

Slide 40

Slide 40 text

;ͨͨͼҾ༻"SDIJUFDUJOH"OESPJEʜ5IFDMFBOXBZ 
 IUUQGFSOBOEPDFKBTDPNBSDIJUFDUJOHBOESPJEUIFDMFBOXBZ .77.͸ ΞʔΩςΫνϟશମΛΧόʔͰ͖Δ֓೦Ͱ͸ͳ͘ ද૚෦෼ͷ࣮૷ʹա͗ͳ͍

Slide 41

Slide 41 text

.PEFM 7JFX.PEFM 7JFX %BUB #JOEJOH $PNNBOET ͜ͷ࿈ܞʹ͍ͭͯ͸.77.͸Կ΋نఆͯ͠ͳ͍ ʢ.7˓શ෦ͦ͏͚ͩͲʣ

Slide 42

Slide 42 text

ͦ͏͍͏ͱ͜Λҙࣝͭͭ͠ɺ ΞϓϦશମʹ໨Λ഑ͬͯ ݈߁తͳઃܭΛ͠ɺ ݈߁తͳίʔυΛॻ͖ɺ ݈߁తͳΤϯδχΞϥΠϑΛૹΓ·͠ΐ͏ʂ

Slide 43

Slide 43 text

'J/$Ͱ͸ ݈߁తͳΤϯδχΞ஥ؒΛืू͍ͯ͠·͢