Upgrade to Pro — share decks privately, control downloads, hide ads and more …

iOSDC2018.pdf

Yuki Yasoshima
August 31, 2018
2k

 iOSDC2018.pdf

Yuki Yasoshima

August 31, 2018
Tweet

Transcript

  1. digraph { graph [label = "Door", labelloc = "t", labeljust

    = "l", fontcolor = "#333333", rankdir = "TB", fontname = "Osaka-Mono", fontsize = "12", charset = "UTF-8"] node [fontcolor = "#333333", fillcolor = "#F9F9F9", fontname = "Osaka-Mono", style = "solid,filled", fontsize = "10", color = "#CCCCCC"] edge [fontcolor = "#333333", fontname = "Osaka-Mono", fontsize = "9", color = "#AAAAAA"] opened [shape = "record", label = "{opened|։͍͍ͯΔ}", color = "#BBBBBB"] closing [shape = "record", label = "{closing|ด͡Δ}", color = "#40C5EE"] closed [shape = "record", label = "{closed|ด͍ͯ͡Δ}", color = "#00D54B"] opening [shape = "record", label = "{opening|։͘}", color = "#40C5EE"] "opened" -> "closing" [style = "solid", color = "#99DEF3"] "closing" -> "closed" [style = "dashed", color = "#AAAAAA"] "closed" -> "opening" [style = "solid", color = "#99DEF3"] // // Door.swift // import FlowGraph // υΞͷঢ়ଶ class Door: FlowGraphType { private(set) var isOpen: Bool = false { didSet { print("isOpen \(self.isOpen)") if let handler = self.isOpenHandler { handler(self.isOpen) } } } var isOpenHandler: ((Bool) -> Void)? enum WaitingState { case closed case opened } enum RunningState { case opening case closing } enum EventKind { case open case close } typealias Event = (kind: EventKind, object: Door) private let graph: FlowGraph<Door> init() { let builder = FlowGraphBuilder<Door>() // ด͍ͯ͡Δ builder.add(waiting: .closed) { event in if case .open = event.kind { return .run(.opening, event) } else { return .stay } } // ։͍͍ͯΔ builder.add(waiting: .opened) { event in if case .close = event.kind { return .run(.closing, event) } else { return .stay } } %PPSTXJGU %PPSEPU %PPSTWH
  2. $ swift build -c release $ swift run -c release

    FlowGraphDotConverter ೖྗ͢ΔϑΝΠϧʢෳ਺ʣ--output ग़ྗ͢ΔϑΥϧμ $ dot -T svg ೖྗ͢Δύε -o ग़ྗ͢Δύε Ϗϧυ͢Δʢ4XJGU1BDLBHF.BOBHFSʣ 4XJGUϑΝΠϧΛղੳͯ͠(SBQIWJ[ͷܗࣜʹग़ྗ (SBQIWJ[Ͱਤʹม׵͢Δ $POWFSUFSͷ࣮ߦ
  3. class Door: FlowGraphType { enum WaitingState { case closed case

    opened } enum RunningState { case opening case closing } typealias Event = (kind: EventKind, object: Door) ... } 'MPX(SBQI5ZQFʹద߹ͨ͠ܕΛఆٛ
  4. class Door: FlowGraphType { enum WaitingState { case closed case

    opened } enum RunningState { case opening case closing } typealias Event = (kind: EventKind, object: Door) ... } ଴ػ͢ΔεςʔτͷܕʢFOVNਪ঑ʣ 'MPX(SBQI5ZQFʹ४ڌͨ͠ܕΛఆٛ
  5. class Door: FlowGraphType { enum WaitingState { case closed case

    opened } enum RunningState { case opening case closing } typealias Event = (kind: EventKind, object: Door) ... } ࣮ߦ͢ΔεςʔτͷܕʢFOVNਪ঑ʣ 'MPX(SBQI5ZQFʹ४ڌͨ͠ܕΛఆٛ
  6. class Door: FlowGraphType { enum WaitingState { case closed case

    opened } enum RunningState { case opening case closing } typealias Event = (kind: EventKind, object: Door) ... } ड͚औΔΠϕϯτͷܕʢͳΜͰ΋ʣ 'MPX(SBQI5ZQFʹ४ڌͨ͠ܕΛఆٛ enum EventKind { case open case close }
  7. builder.add(waiting: .closed) { event in if case .open = event.kind

    { return .run(.opening, event) } else { return .stay } } 8BJUJOH4UBUFͷొ࿥
  8. builder.add(waiting: .closed) { event in if case .open = event.kind

    { return .run(.opening, event) } else { return .stay } } 8BJUJOH4UBUFͷొ࿥ ొ࿥͢Δεςʔτ໊
  9. builder.add(waiting: .closed) { event in if case .open = event.kind

    { return .run(.opening, event) } else { return .stay } } 8BJUJOH4UBUFͷొ࿥ ొ࿥͢ΔΫϩʔδϟ
  10. builder.add(waiting: .closed) { event in if case .open = event.kind

    { return .run(.opening, event) } else { return .stay } } ΠϕϯτΛड͚औΔ 8BJUJOH4UBUFͷొ࿥
  11. builder.add(waiting: .closed) { event in if case .open = event.kind

    { return .run(.opening, event) } else { return .stay } } 8BJUJOH4UBUFͷొ࿥ ผͷεςʔτʹભҠ͢Δ
  12. builder.add(waiting: .closed) { event in if case .open = event.kind

    { return .run(.opening, event) } else { return .stay } } 8BJUJOH4UBUFͷొ࿥ return .wait(.opened) ผͷεςʔτʹભҠ͢Δ
  13. builder.add(waiting: .closed) { event in if case .open = event.kind

    { return .run(.opening, event) } else { return .stay } } Կ΋͠ͳ͍ 8BJUJOH4UBUFͷొ࿥
  14. builder.add(running: .opening) { event in event.object.isOpen = true return .wait(.opened)

    } ผͷεςʔτʹભҠ͢Δ 3VOOJOH4UBUFͷొ࿥ ❇3VOOJOH4UBUFʹཹ·Δ͜ͱ͸Ͱ͖ͳ͍
  15. \ LFZEJBHOPTUJD@TUBHFTPVSDFEJBHOPTUJDTUBHFTXJGUQBSTF  LFZMFOHUI  LFZP⒎TFU  LFZTVCTUSVDUVSF< \ LFZBDDFTTJCJMJUZTPVSDFMBOHTXJGUBDDFTTJCJMJUZJOUFSOBM

     LFZCPEZMFOHUI  LFZCPEZP⒎TFU  LFZFMFNFOUT< \ LFZLJOETPVSDFMBOHTXJGUTUSVDUVSFFMFNUZQFSFG  LFZMFOHUI  LFZP⒎TFU ^ >  LFZJOIFSJUFEUZQFT< \ LFZOBNF'MPX(SBQI5ZQF ^ >  LFZLJOETPVSDFMBOHTXJGUEFDMDMBTT  LFZMFOHUI  LFZOBNF%PPS  LFZOBNFMFOHUI  4USVDUVSF
  16. \ LFZEJBHOPTUJD@TUBHFTPVSDFEJBHOPTUJDTUBHFT LFZMFOHUI  LFZP⒎TFU  LFZTVCTUSVDUVSF< \ LFZBDDFTTJCJMJUZTPVSDFMBOHTXJGUBDDFTTJCJ LFZCPEZMFOHUI

     LFZCPEZP⒎TFU  LFZFMFNFOUT< \ LFZLJOETPVSDFMBOHTXJGUTUSVDUVSFFMFN LFZMFOHUI  LFZP⒎TFU P⒎TFUͱMFOHUIͰ ཁૉͷจࣈྻͷҐஔ͕ औಘͰ͖Δ
  17. \ LFZEJBHOPTUJD@TUBHFTPVSDFEJBHOPTUJDTUBHFT LFZMFOHUI  LFZP⒎TFU  LFZTVCTUSVDUVSF< \ LFZBDDFTTJCJMJUZTPVSDFMBOHTXJGUBDDFTTJCJ LFZCPEZMFOHUI

     LFZCPEZP⒎TFU  LFZFMFNFOUT< \ LFZLJOETPVSDFMBOHTXJGUTUSVDUVSFFMFN LFZMFOHUI  LFZP⒎TFU TVCTUSVDUVSFʹࢠͷཁૉͷ഑ྻ
  18. LFZP⒎TFU  LFZTVCTUSVDUVSF< \ LFZBDDFTTJCJMJUZTPVSDFMBOHTXJGUBDDFTTJCJ LFZCPEZMFOHUI  LFZCPEZP⒎TFU  LFZFMFNFOUT<

    \ LFZLJOETPVSDFMBOHTXJGUTUSVDUVSFFMFN LFZMFOHUI  LFZP⒎TFU ^ >  LFZJOIFSJUFEUZQFT< LJOE͸ཁૉͷछྨ
  19. // Door.swift // import FlowGraph // υΞͷঢ়ଶ class Door: FlowGraphType

    { private(set) var isOpen: Bool = false didSet { print("isOpen \(self.isOpen)") if let handler = self.isOpenHa handler(self.isOpen) } } } var isOpenHandler: ((Bool) -> Void)?
  20. LFZJOIFSJUFEUZQFT< \ LFZOBNF'MPX(SBQI5ZQF ^ >  LFZLJOETPVSDFMBOHTXJGUEFDMDMBTT  LFZMFOHUI 

    LFZOBNF%PPS  LFZOBNFMFOHUI  LFZOBNFP⒎TFU  LFZP⒎TFU  LFZSVOUJNF@OBNF@5U$@@NBJO@@%PPS  LFZTVCTUSVDUVSF< \ LFZBDDFTTJCJMJUZTPVSDFMBOHTXJGUBDDFTTJCJM LJOE͕DMBTT
  21. LFZJOIFSJUFEUZQFT< \ LFZOBNF'MPX(SBQI5ZQF ^ >  LFZLJOETPVSDFMBOHTXJGUEFDMDMBTT  LFZMFOHUI 

    LFZOBNF%PPS  LFZOBNFMFOHUI  LFZOBNFP⒎TFU  LFZP⒎TFU  LFZSVOUJNF@OBNF@5U$@@NBJO@@%PPS  LFZTVCTUSVDUVSF< \ LFZBDDFTTJCJMJUZTPVSDFMBOHTXJGUBDDFTTJCJM P⒎TFUͱMFOHIͰ ΫϥεͷҐஔΛऔಘ
  22. LFZJOIFSJUFEUZQFT< \ LFZOBNF'MPX(SBQI5ZQF ^ >  LFZLJOETPVSDFMBOHTXJGUEFDMDMBTT  LFZMFOHUI 

    LFZOBNF%PPS  LFZOBNFMFOHUI  LFZOBNFP⒎TFU  LFZP⒎TFU  LFZSVOUJNF@OBNF@5U$@@NBJO@@%PPS  LFZTVCTUSVDUVSF< \ LFZBDDFTTJCJMJUZTPVSDFMBOHTXJGUBDDFTTJCJM OBNFʹDMBTTͷ໊લ
  23. init() { let builder = FlowGraphBuilder<Door>() // ด͍ͯ͡Δ builder.add(waiting: .closed)

    { event in if case .open = event.kind { return .run(.opening, event) } else { return .stay } } // ։͍͍ͯΔ builder.add(waiting: .opened) { event in if case .close = event.kind { return .run(.closing, event) } else { return .stay
  24. \ LFZCPEZMFOHUI  LFZCPEZP⒎TFU  LFZLJOETPVSDFMBOHTXJGUFYQSDBMM  LFZMFOHUI  LFZOBNFCVJMEFSBEE

     LFZOBNFMFOHUI  LFZOBNFP⒎TFU  LFZP⒎TFU  LFZTVCTUSVDUVSF< \ LFZCPEZMFOHUI  LFZCPEZP⒎TFU  LFZLJOETPVSDFMBOHTXJGUFYQSBSHVNFOU  LFZMFOHUI  LFZOBNFXBJUJOH  LFZOBNFMFOHUI  FYQSDBMM͕ؔ਺ݺͼग़͠
  25. \ LFZCPEZMFOHUI  LFZCPEZP⒎TFU  LFZLJOETPVSDFMBOHTXJGUFYQSDBMM  LFZMFOHUI  LFZOBNFCVJMEFSBEE

     LFZOBNFMFOHUI  LFZOBNFP⒎TFU  LFZP⒎TFU  LFZTVCTUSVDUVSF< \ LFZCPEZMFOHUI  LFZCPEZP⒎TFU  LFZLJOETPVSDFMBOHTXJGUFYQSBSHVNFOU  LFZMFOHUI  LFZOBNFXBJUJOH  LFZOBNFMFOHUI  FYQSDBMMͷOBNFʹ ؔ਺໊
  26. LFZOBNFMFOHUI  LFZOBNFP⒎TFU  LFZP⒎TFU  LFZTVCTUSVDUVSF< \ LFZCPEZMFOHUI 

    LFZCPEZP⒎TFU  LFZLJOETPVSDFMBOHTXJGUFYQSBSHVNFOU  LFZMFOHUI  LFZOBNFXBJUJOH  LFZOBNFMFOHUI  LFZOBNFP⒎TFU  LFZP⒎TFU ^  \ LFZCPEZMFOHUI  LFZCPEZP⒎TFU  BSHVNFOU͕ ؔ਺ͷҾ਺
  27. LFZOBNFMFOHUI  LFZOBNFP⒎TFU  LFZP⒎TFU  LFZTVCTUSVDUVSF< \ LFZCPEZMFOHUI 

    LFZCPEZP⒎TFU  LFZLJOETPVSDFMBOHTXJGUFYQSBSHVNFOU  LFZMFOHUI  LFZOBNFXBJUJOH  LFZOBNFMFOHUI  LFZOBNFP⒎TFU  LFZP⒎TFU ^  \ LFZCPEZMFOHUI  LFZCPEZP⒎TFU  BSHVNFOUͷOBNFʹ Ҿ਺ͷϥϕϧ
  28. LFZOBNFMFOHUI  LFZOBNFP⒎TFU  LFZP⒎TFU  LFZTVCTUSVDUVSF< \ LFZCPEZMFOHUI 

    LFZCPEZP⒎TFU  LFZLJOETPVSDFMBOHTXJGUFYQSBSHVNFOU  LFZMFOHUI  LFZOBNFXBJUJOH  LFZOBNFMFOHUI  LFZOBNFP⒎TFU  LFZP⒎TFU ^  \ LFZCPEZMFOHUI  LFZCPEZP⒎TFU  Ҿ਺ͷ஋ͷ෦෼͸Ґஔ͚ͩ
  29. init() { let builder = FlowGraphBuilder<Door>() // ด͍ͯ͡Δ builder.add(waiting: .closed)

    { event in if case .open = event.kind { return .run(.opening, event) } else { return .stay } } // ։͍͍ͯΔ builder.add(waiting: .opened) { event in if case .close = event.kind { return .run(.closing, event) } else { return .stay SFUVSOͷҐஔ͸Θ͔Βͳ͍
  30. {type:comment offset:0, length:3, content:'// '}, {type:comment offset:3, length:15, content:'// Door.swift

    '}, {type:comment offset:18, length:3, content:'// '}, {type:keyword offset:22, length:6, content:'import'}, {type:identifier offset:29, length:9, content:'FlowGraph'}, {type:comment offset:40, length:19, content:'// υΞͷঢ়ଶ '}, {type:keyword offset:59, length:5, content:'class'}, {type:identifier offset:65, length:4, content:'Door'}, {type:typeidentifier offset:71, length:13, content:'FlowGraphType'}, {type:attributeBuiltin offset:91, length:12, content:'private(set)'}, {type:keyword offset:104, length:3, content:'var'}, {type:identifier offset:108, length:6, content:'isOpen'}, {type:typeidentifier offset:116, length:4, content:'Bool'}, {type:keyword offset:123, length:5, content:'false'}, {type:keyword offset:139, length:6, content:'didSet'}, {type:identifier offset:160, length:5, content:'print'}, {type:string offset:166, length:8, content:'"isOpen '}, {type:stringInterpolationAnchor offset:175, length:1, content:'('}, {type:keyword offset:176, length:4, content:'self'}, {type:identifier offset:181, length:6, content:'isOpen'}, {type:stringInterpolationAnchor offset:187, length:1, content:')'},
  31. init() { let builder = FlowGraphBuilder<Door>() // ด͍ͯ͡Δ builder.add(waiting: .closed)

    { event in if case .open = event.kind { return .run(.opening, event) } else { return .stay } } // ։͍͍ͯΔ builder.add(waiting: .opened) { event in if case .close = event.kind { return .run(.closing, event) } else { return .stay ؔ਺ͷCPEZ෦෼
  32. '}, {type:identifier offset:800, length:7, content:'builder'}, {type:identifier offset:808, length:3, content:'add'}, {type:identifier

    offset:812, length:7, content:'waiting'}, {type:identifier offset:822, length:6, content:'closed'}, {type:identifier offset:832, length:5, content:'event'}, {type:keyword offset:838, length:2, content:'in'}, {type:keyword offset:853, length:2, content:'if'}, {type:keyword offset:856, length:4, content:'case'}, {type:identifier offset:862, length:4, content:'open'}, {type:identifier offset:869, length:5, content:'event'}, {type:identifier offset:875, length:4, content:'kind'}, {type:keyword offset:898, length:6, content:'return'}, {type:identifier offset:906, length:3, content:'run'}, {type:identifier offset:911, length:7, content:'opening'}, {type:identifier offset:920, length:5, content:'event'}, {type:keyword offset:941, length:4, content:'else'}, {type:keyword offset:964, length:6, content:'return'}, {type:identifier offset:972, length:4, content:'stay'}, {type:comment offset:1018, length:19, content:'// ։͍͍ͯΔ '}, {type:identifier offset:1045, length:7, content:'builder'}, {type:identifier offset:1053, length:3, content:'add'}, {type:identifier offset:1057, length:7, content:'waiting'}, {type:identifier offset:1067, length:6, content:'opened'},
  33. '}, {type:identifier offset:800, length:7, content:'builder'}, {type:identifier offset:808, length:3, content:'add'}, {type:identifier

    offset:812, length:7, content:'waiting'}, {type:identifier offset:822, length:6, content:'closed'}, {type:identifier offset:832, length:5, content:'event'}, {type:keyword offset:838, length:2, content:'in'}, {type:keyword offset:853, length:2, content:'if'}, {type:keyword offset:856, length:4, content:'case'}, {type:identifier offset:862, length:4, content:'open'}, {type:identifier offset:869, length:5, content:'event'}, {type:identifier offset:875, length:4, content:'kind'}, {type:keyword offset:898, length:6, content:'return'}, {type:identifier offset:906, length:3, content:'run'}, {type:identifier offset:911, length:7, content:'opening'}, {type:identifier offset:920, length:5, content:'event'}, {type:keyword offset:941, length:4, content:'else'}, {type:keyword offset:964, length:6, content:'return'}, {type:identifier offset:972, length:4, content:'stay'}, {type:comment offset:1018, length:19, content:'// ։͍͍ͯΔ '}, {type:identifier offset:1045, length:7, content:'builder'}, {type:identifier offset:1053, length:3, content:'add'}, {type:identifier offset:1057, length:7, content:'waiting'}, {type:identifier offset:1067, length:6, content:'opened'},
  34. waiting closed event in if case open event kind return

    run opening event else return stay ಄͔Βॱ൪ʹݟ͍ͯ͘
  35. waiting closed event in if case open event kind return

    run opening event else return stay XBJUJOH͔ SVOOJOH ͳΒʜ XBJUJOH
  36. waiting closed event in if case open event kind return

    run opening event else return stay ࣍͸ εςʔτ໊ XBJUJOH DMPTFE
  37. waiting closed event in if case open event kind return

    run opening event else return stay JOͷޙ͔Β Ϋϩʔδϟ XBJUJOH DMPTFE
  38. waiting closed event in if case open event kind return

    run opening event else return stay SFUVSOΛ୳͢ XBJUJOH DMPTFE
  39. waiting closed event in if case open event kind return

    run opening event else return stay SVO͔ XBJUͳΒʜ XBJUJOH DMPTFE
  40. waiting closed event in if case open event kind return

    run opening event else return stay ਐΉઌͷ εςʔτ໊ XBJUJOH DMPTFE PQFOJOH
  41. waiting closed event in if case open event kind return

    run opening event else return stay SFUVSOΛ୳͢ XBJUJOH DMPTFE PQFOJOH
  42. waiting closed event in if case open event kind return

    run opening event else return stay TUBZͳΒແࢹ XBJUJOH DMPTFE PQFOJOH
  43. %PU

  44. digraph { graph [label = "Door", labelloc = "t", labeljust

    = "l", fontcolor = "#333333", rankdir = "TB", fontname = "Osaka-Mono", fontsize = "12", charset = "UTF-8"] node [fontcolor = "#333333", fillcolor = "#F9F9F9", fontname = "Osaka-Mono", style = "solid,filled", fontsize = "10", color = "#CCCCCC"] edge [fontcolor = "#333333", fontname = "Osaka-Mono", fontsize = "9", color = "#AAAAAA"] opened [shape = "record", label = "{opened|։͍͍ͯΔ}", color = "#BBBBBB"] closing [shape = "record", label = "{closing|ด͡Δ}", color = "#40C5EE"] closed [shape = "record", label = "{closed|ด͍ͯ͡Δ}", color = "#00D54B"] opening [shape = "record", label = "{opening|։͘}", color = "#40C5EE"] "opened" -> "closing" [style = "solid", color = "#99DEF3"] "closing" -> "closed" [style = "dashed", color = "#AAAAAA"] "closed" -> "opening" [style = "solid", color = "#99DEF3"] "opening" -> "opened" [style = "dashed", color = "#AAAAAA"] } %PPSEPU
  45. digraph { graph [label = "Door", labelloc = "t fontcolor

    = "#333333", rankdi fontname = "Osaka-Mono", font charset = "UTF-8"] node [fontcolor = "#333333", fillcol fontname = "Osaka-Mono", style fontsize = "10", color = "#CCC edge [fontcolor = "#333333", fontnam fontsize = "9", color = "#AAAA opened [shape = "record", label = "{ EJHSBQI͸༗޲άϥϑ %PPSEPU
  46. charset = "UTF-8"] node [fontcolor = "#333333", fillcolor = "

    fontname = "Osaka-Mono", style = "so fontsize = "10", color = "#CCCCCC"] edge [fontcolor = "#333333", fontname = "O fontsize = "9", color = "#AAAAAA"] opened [shape = "record", label = "{opened|։͍͍ͯΔ}", color = "#BBBBBB"] closing [shape = "record", label = "{closi color = "#40C5EE"] closed [shape = "record", label = "{closed color = "#00D54B"] opening [shape = "record", label = "{openi color = "#40C5EE"] ϊʔυͷ໊લ ϊʔυ
  47. charset = "UTF-8"] node [fontcolor = "#333333", fillcolor = "

    fontname = "Osaka-Mono", style = "so fontsize = "10", color = "#CCCCCC"] edge [fontcolor = "#333333", fontname = "O fontsize = "9", color = "#AAAAAA"] opened [shape = "record", label = "{opened|։͍͍ͯΔ}", color = "#BBBBBB"] closing [shape = "record", label = "{closi color = "#40C5EE"] closed [shape = "record", label = "{closed color = "#00D54B"] opening [shape = "record", label = "{openi color = "#40C5EE"] <>ͷதʹදࣔ͞ΕΔத਎ ϊʔυ
  48. closing [shape = "record", label = "{closing color = "#40C5EE"]

    closed [shape = "record", label = "{closed|ด color = "#00D54B"] opening [shape = "record", label = "{opening color = "#40C5EE"] "opened" -> "closing" [style = "solid", color = "#99DEF3"] "closing" -> "closed" [style = "dashed", col "closed" -> "opening" [style = "solid", colo "opening" -> "opened" [style = "dashed", col } Τοδ ͰϊʔυΛͭͳ͛Δ