Slide 1

Slide 1 text

4XJGU#POEͱ.77.Ͱ ঢ়ଶ؅ཧΛγϯϓϧʹ͠Α͏ yohei SUGIGAMI 2016 04/13 Reactive Swift Meetup

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

ΞϓϦͷίʔυ͕ ෳࡶʹͳ͍ͬͯ·ͤΜ͔ ̎̌̍̑೥݄̑
 4ZODͷ։ൃ࣌ʹ
 ௅ઓͨ͠՝୊

Slide 5

Slide 5 text

എܠ Ϣʔβͷମݧʹ͓͚Δظ଴஋ͷߴ౓Խͱଟ༷Խ ϞόΠϧ୺຤ͷεϖοΫ޲্
 ௨৴؀ڥͷ޲্ ΞϓϦͷଟػೳԽ ௨৴΍ύϑΥʔϚϯενϡʔχϯάͰඇಉظଟൃ ίʔυͷෳࡶԽ

Slide 6

Slide 6 text

4ZODΞϓϦͷ։ൃͷલʹ ࣾ಺։ൃͰ"OHVMBS+4΍ͬͯ·ͨ͠ .77.ͱ7JFX%BUB#JOEʹ ٔΕΔ

Slide 7

Slide 7 text

IUUQTUBSUVQTUPDLQIPUPTDPN ͜Εͩʂ

Slide 8

Slide 8 text

MVVM IUUQTNTEONJDSPTPGUDPNFOVTMJCSBSZHH W1BOE1 BTQYTFD 6*7JFX$POUSPMMFS 6*#VUUPO 6*-BCFM 6*5BCMF7JFX FUD "1*$MJFOU %BUB.PEFM 1FSTJTUFODF 6*-PHJD #VTJOFTT-PHJD 1SFTFOUBUJPO-PHJD ෳࡶʹͳΓ͕ͪͳ6*7JFX$POUSPMMFSʹهड़͍ͯͨ͠ ϩδοΫ͕7JFX.PEFMʹू໿͞ΕΔ 7JFX.PEFM͸ػೳ͝ͱʹ Ϋϥε෼ׂ΍ڞ௨Խ͠΍͍͢ ςετ͕͠΍͍͢ ˰ݟ௨͕͠Α͘ͳΔ

Slide 9

Slide 9 text

੹຿ͱؔ৺ࣄͷ෼཭ 4UBUF 7JFX $POUSPMMFS 7JFX.PEFM %BUB ؔ஌͍ͯ͠ΔੈքΛখ͘͢͞Δ ੹຿Λ໌֬ʹ͢Δ ίʔυ͸Θ͔Γ΍͘͢ͳΔ -PHJD 7JFX 7JFX.PEFM͸ 7JFXʹ͍ͭͯ͸ؔ஌͠ͳ͍ σʔλͷมߋ͕੹຿ PS #JOE 7JFX͸σʔλ͕ͲͷΑ͏ʹ ࡞ΒΕΔ͔͸ؔ஌͠ͳ͍ 7JFX #JOEJOH $PNNBOET

Slide 10

Slide 10 text

4XJGUͰ 7JFX%BUB#JOEJOH Ͳ͏΍Δͷʁ

Slide 11

Slide 11 text

No content

Slide 12

Slide 12 text

όΠϯσΟϯάϑϨʔϜϫʔΫЋ 3FBDUJWFͳมԽͷৼΔ෣͍Λؔ਺Ͱ
 هड़Ͱ͖Δ 4XJGU#POEͱ͸ ࢖͏͜ͱ͕γϯϓϧͰ͋Δ͜ͱ ཧղ͢Δ͜ͱ͕γϯϓϧͰ͋Δ͜ͱ ໨ࢦ̎ͭ͢ͷΰʔϧ

Slide 13

Slide 13 text

Ͱ͖Δ͜ͱͷͬ͘͟ΓΠϝʔδਤ

Slide 14

Slide 14 text

IUUQTUBSUVQTUPDLQIPUPTDPN ΋͏̍ͭͷෳࡶϙΠϯτ ը໘ͷঢ়ଶ؅ཧ

Slide 15

Slide 15 text

6*4UBDL ͭͷը໘ʹ͸ଟ༷ͳঢ়ଶ͕͋Δʣ )PXUPpYBCBEVTFSJOUFSGBDF ೔ຊޠ༁όου6*Λվળ͢Δํ๏ʕ6*ͷʮͭͷঢ়ଶʯΛߟ͑Δ w ϒϥϯΫঢ়ଶ w ௨৴ঢ়ଶ w ్தঢ়ଶ w Τϥʔঢ়ଶ w ཧ૝ঢ়ଶ ը໘ͷঢ়ଶΛઃܭɾ؅ཧ͠Α͏ ΋͏গ͠ଟ͍4UBDL਺ͷ؅ཧΛ ޙ΄Ͳ঺հ͠·͢

Slide 16

Slide 16 text

γϯϓϧʹ σʔλ͚ͩͰ͸ͳ͘ɺঢ়ଶ͕มԽ͢Δͱ
 ಈతʹը໘ද͕ࣔ
 ੾ΓସΘΔΑ͏ʹ͍ͨ͠ ଟ༷ͳঢ়ଶͷදࣔΛ੾Γସ͑Δ
 ϩδοΫ͸ෳࡶʹͳΓ͕ͪ 7JFX4UBUF#JOEJOH

Slide 17

Slide 17 text

۩ମྫͰݟͯΈΑ͏ w .77. w 7JFX%BUB#JOEJOH w 7JFX4UBUF#JOEJOH w 4XJGU#POE

Slide 18

Slide 18 text

Α͋͘Δ௨৴ʹΑΔҰཡදࣔ JUFNT<JUFN JUFN JUFN ʜ> SFRVFTU4UBUF/POFPS3FRVFTUJOHPS&SSPS ഑ྻͱ௨৴ͷͭͷঢ়ଶʹண؟͢Δ

Slide 19

Slide 19 text

4UBUF3FRVFTUJOH 4UBUF&SSPS JUFNT<> 4UBUF/POF *OEJDBUPS7JFX 3FUSZ7JFX /P%BUB7JFX ഑ྻͷΞΠςϜ͕ͳ͍৔߹ͷঢ়ଶ̏ͭ

Slide 20

Slide 20 text

4UBUF3FRVFTUJOH 4UBUF&SSPS JUFNT<JUFN JUFN JUFN ʜ> 4UBUF/POF *OEJDBUPS7JFX 3FUSZ7JFX /P%BUB7JFX ഑ྻͷΞΠςϜ͕͋Δ৔߹ͷঢ়ଶ̏ͭ ΩϟογϡΛදࣔͯ͠Δ৔߹ͳͲ

Slide 21

Slide 21 text

഑ྻͷঢ়ଶ ௨৴ͷঢ়ଶ ᶃͭͷঢ়ଶͷมԽ͔Βಈతʹը໘දࣔΛ͍ͨ͠ ௨৴ͱ഑ྻͷঢ়ଶͷ3FBDUJWFͳมԽΛ ؔ਺ͰએݴతʹৼΔ෣͍ʹམͱ͜͠Ή ը໘͕ಈతʹܾ·Δ

Slide 22

Slide 22 text

ᶄ഑ྻͷཁૉ͕มԽ͢Δͱಈతʹද͍ࣔͨ͠ &.15: ഑ྻͷঢ়ଶ ഑ྻͷཁૉ͕มԽ͢Δͱ 6*5BCMF7JFXͷද͕ࣔ ಈతʹมΘΔ

Slide 23

Slide 23 text

7JFX.PEFM

Slide 24

Slide 24 text

enum RequestState { case None case Requesting case Error } protocol RequestListStateType { associatedtype Item var items: ObservableArray { get }
 var requestState: Observable { get } var hasVisibleItems: Observable { get } var noDataViewHidden: Observable { get } var indicatorViewHidden: Observable { get } var retryViewHidden: Observable { get } } Protocol 0CTFSBCMF 0CTFSBCMF"SSBZܕ͸
 4XJGU#POE͕ఏڙ͢Δػೳ

Slide 25

Slide 25 text

extension RequestListStateType { func binding() { items .map { $0.sequence.count > 0 } .bindTo(hasVisibleItems) requestState .combineLatestWith(hasVisibleItems) .map { !($0 == RequestState.Requesting && $1 == false) } .bindTo(indicatorViewHidden) requestState .combineLatestWith(hasVisibleItems) .map { !($0 == RequestState.Error && $1 == false) } .bindTo(retryViewHidden) requestState .combineLatestWith(hasVisibleItems) .map { !($0 == RequestState.None && $1 == false) } .bindTo(noDataViewHidden) } } Protocol Extension JUFNTͱSFRVFTU4UBUFͷมԽΛ ଞͷ0CTFSBCMFʹ#JOEJOH

Slide 26

Slide 26 text

protocol RequestListType: RequestListStateType {} extension RequestListType { func request(task: Task>) {
 requestState.value = .Requesting task.success { (collection: Collection) in self.requestState.value = .None self.items.array = collection.items }.failure { _ in self.requestState.value = .Error } } } Protocol Extension 3FRVFTUͷ1SPNJTF͕׬ྃͨ͠Β
 JUFNTͱSFRVFTU4UBUFʹ஋Λ୅ೖ˰ը໘͕ಈతʹมԽ 4XJGU#POE͸1SPNJTFΛఏڙ͍ͯ͠ͳ͍ͷͰखಈͰ݁߹

Slide 27

Slide 27 text

struct RequestListViewModel: RequestListType { typealias Item = T let requestState = Observable(.None) let items = ObservableArray([])
 let hasVisibleItems = Observable(false) let indicatorViewHidden = Observable(true) let retryViewHidden = Observable(true) let noDataViewHidden = Observable(true) init() { binding() } } Protocol Implement (FOFSJDTͰ*UFNͷܕΛղܾ 7JFX.PEFMͷ࣮૷͸༻్ʹΑͬͯ࢖͍෼͚͍ͨͱ͖͕͋ΔͷͰ 1SPUPDPM&YUFOTJPOΛ׆༻ͯ͠ڞ௨Խ

Slide 28

Slide 28 text

7JFX$POUSPMMFS

Slide 29

Slide 29 text

let viewModel = RequestListViewModel() override func viewDidLoad() { super.viewDidLoad( viewModel.indicatorViewHidden.bindTo(indicatorView.bnd_hidden) viewModel.retryViewHidden.bindTo(retryView.bnd_hidden) viewModel.noDataFirstViewHidden.bindTo(noDataView.bnd_hidden) viewModel.requestState.observeNew { UIApplication.sharedApplication() .networkActivityIndicatorVisible = ($0 == .Requesting) if $0 == .Error {
 StatusBarNotification.showWithStatus("Connection failed") } } viewModel.items.lift().bindTo(tableView, proxyDataSource: self) { 
 (indexPath, dataSource, tableView) -> UITableViewCell in let vm = dataSource[indexPath.section][indexPath.row] let cell = tableView.dequeueReusableCellWithIdentifier(
 ContactCell.identifier, forIndexPath: indexPath) as! ContactCell
 cell.configure(vm) return cell } final class ContactsViewController: UITableViewController {

Slide 30

Slide 30 text

viewModel.indicatorViewHidden.bindTo(indicatorView.bnd_hidden) viewModel.retryViewHidden.bindTo(retryView.bnd_hidden) viewModel.noDataFirstViewHidden.bindTo(noDataView.bnd_hidden) viewModel.requestState.observeNew { UIApplication.sharedApplication() .networkActivityIndicatorVisible = ($0 == .Requesting)
 if $0 == .Error {
 StatusBarNotification.showWithStatus("Connection failed") } } COE@IJEEFO͸4XJGU#POE͕6*7JFXΛ FYUFOTJPOͨ͠GVODUJPO YYYY7JFX)JEEFOͷ஋͕มԽ͢Δͱ#JOE5Pͨ͠ 7JFXͷIJEEFO͕ಈతʹมΘΔ

Slide 31

Slide 31 text

viewModel.items.lift().bindTo(tableView, proxyDataSource: self) { 
 (indexPath, dataSource, tableView) -> UITableViewCell in let vm = dataSource[indexPath.section][indexPath.row] let cell = tableView.dequeueReusableCellWithIdentifier(
 ContactCell.identifier, forIndexPath: indexPath) as! ContactCell
 cell.configure(vm) return cell } JUFNTͷมԽΛ6*5BCMF7JFXʹ#JOEJOH ಺෦తʹ4XJGU#POE͕6*5BCMF7JFX%BUBTPVSDFͷ ࣮૷ʹͳΔͷͰɺ%BUBTPVSDFͷهड़͕ෆཁʹ Ҏ্͕Α͋͘Δ௨৴ͷྫͷ࣮૷ʹͳΓ·͢

Slide 32

Slide 32 text

·ͱΊ ᶃ ෳࡶʹͳΓ͕ͪͳίʔυΛ୺తͰએݴతʹ
 ৼΔ෣͍Λهड़Ͱ͖Δ
 ˰࢓༷Λཧղ͠΍͍͢ ᶄ ৼΔ෣͍Λ'31Ͱهड़͍ͯ͠ΔͷͰ෭࡞༻
 Λߟྀ͢Δඞཁ͕ແ͍
 ˰ڍಈΛ೺Ѳ͠΍͍͢ ᶅ 3FBDUJWF͸೉ͦ͠͏͚ͩͲ4XJGU#POE
 ͸γϯϓϧʹهड़Ͱ͖Δ


Slide 33

Slide 33 text

&/%