Slide 1

Slide 1 text

by. ▶ SLIDE START 1

Slide 2

Slide 2 text

͠Β΂Δ: takasek GitHubͰ͸ SwiftyͳϚΠΫϩϥΠϒϥϦ ࡞ͬͯ·͢ ▶Notifwift NSNotificationͷuserInfoΛ Swiftyʹѻ͏ ▶ActionClosurable target/actionΛ Ϋϩʔδϟه๏ʹม׵ 2

Slide 3

Slide 3 text

SwiftͷEnum͸ڧྗ 4 switchט·ͤΔͱ໢ཏతʹॻ͚Δ 4 ϝιουΛ࣋ͨͤΒΕΔ 4 Protocol΁ͷద߹΋ࢥ͍ͷ·· 4 associated valuesศར 4 Optional΋ਖ਼ମ͸Enum! 4 rawValueͱͷ૬ޓม׵΋Ͱ͖Δ 3

Slide 4

Slide 4 text

ΨϯΨϯ ͔͓ͭ͏ͥ! 4

Slide 5

Slide 5 text

⚠ɹ 5

Slide 6

Slide 6 text

EnumʹཔΓ͗ͯ͢ ຊདྷ࢖͏΂͖Ͱͳ͍ܗͰ EnumΛ࢖ͬͯ·ͤΜ͔! 6

Slide 7

Slide 7 text

ͱΜͰ΋ͳ͍Enumͷ ΉΕ͕ ͋ΒΘΕͨʂ ɹ ผΧςΰϦͷcase͕ࠞͬͨ͟Enum ɹ ҟͳΔίϯςΩετͰ࢖͍ճ͞ΕΔEnum ɹ άϧʔϐϯάͷͨΊ͚ͩͷEnum 7

Slide 8

Slide 8 text

ͱΜͰ΋ͳ͍Enumͷ ΉΕ͕ ͋ΒΘΕͨʂ ▶ ผΧςΰϦͷcase͕ࠞͬͨ͟Enum ɹ ҟͳΔίϯςΩετͰ࢖͍ճ͞ΕΔEnum ɹ άϧʔϐϯάͷͨΊ͚ͩͷEnum 8

Slide 9

Slide 9 text

▶ ผΧςΰϦͷcase͕ ɹࠞͬͨ͟Enumɹᶃ !γνϡΤʔγϣϯ! 4 ΅͏͚Μͷ͠ΐCellΛબͿ 4 API௨৴Ͱfetch͢Δ 4 struct SaveData 4 ௨৴ঢ়گ͸EnumͰ؅ཧ 4 enum LoadingState 9

Slide 10

Slide 10 text

final class ΅͏͚Μͷ͠ΐListViewModel { enum LoadingState { case idle case proceeding case succeeded case error } let loadingState = Variable(.idle) let saveData = Variable(nil) func fetchSaveData(at index: Int) { SaveDataAPI(of: index).fetch { [weak self] (data: SaveData?) in if let data = data { self?.saveData.value = data self?.loadingState.value = .succeeded } else { self?.loadingState.value = .error } } } 10

Slide 11

Slide 11 text

!ɹ 11

Slide 12

Slide 12 text

final class ΅͏͚Μͷ͠ΐListViewModel { enum LoadingState { case idle case proceeding // !͍ͭ͜Β͸͔֬ʹʮ௨৴ঢ়ଶʯ͚ͩͲ… case succeeded case error // !͍ͭ͜Β͸ʮ௨৴݁ՌʯΛදͯ͠Δ } let loadingState = Variable(.idle) let saveData = Variable(nil) //ɹ ! SaveDataͱLoadingState.error ͸ //ɹɹɹͲͬͪ΋ʮ௨৴݁Ռʯͱݴ͏ҙຯͰ໾ׂ͕ॏෳ 12

Slide 13

Slide 13 text

ͬͪ͜ͷઃܭͷ΄͏͕ਖ਼͍͠ final class ΅͏͚Μͷ͠ΐListViewModel { enum LoadingState { case idle case proceeding //!௨৴ঢ়ଶ͚ͩΛࣔ͢Enumʹ͠·͠ΐ͏ //"Ή͠Ζ Bool ͰࡁΉ } let loadingState = Variable(.idle) let saveData = Variable?>(nil) //!௨৴ޙ͸ɺ݁Ռ(Error or SaveData)͕ඞͣೖΔ 13

Slide 14

Slide 14 text

14

Slide 15

Slide 15 text

▶ ผΧςΰϦͷcase͕ࠞͬͨ͟Enumɹᶄ !γνϡΤʔγϣϯ! 4 ΩϟϥΛ࡞੒ 4 struct Character 4 Ωϟϥ͸ ͠ΐ͗͘ΐ͏ Λ࣋ͭ 4 enum Job 15

Slide 16

Slide 16 text

struct Character { enum Job: String { case Ώ͏͠Ό = "hero" case ͤΜ͠ = "soldier" case ·΄͏͔͍ͭ = "wizard" case ͦ͏Γΐ = "priest" case undefined } let job: Job ... init(json: JSON) { ... job = Job(json["job"].stringValue) ?? .undefined ... } 16

Slide 17

Slide 17 text

!ɹ 17

Slide 18

Slide 18 text

enum Job: String { case Ώ͏͠Ό = "hero" case ͤΜ͠ = "soldier" case Ϳͱ͏͔ = "fighter" case ·΄͏͔͍ͭ = "wizard" case ͦ͏Γΐ = "priest" case undefined // ! ཻ౓͕͓͔͍͠ } let job: Job // ! Required ͜͏͡Όͳͯ͘ɺ 18

Slide 19

Slide 19 text

enum Job: String { case Ώ͏͠Ό = "hero" case ͤΜ͠ = "soldier" case Ϳͱ͏͔ = "fighter" case ·΄͏͔͍ͭ = "wizard" case ͦ͏Γΐ = "priest" //case undefined ͳͲͳ͍ } let job: Job? // ! Optional ͜͏Ͱ͠ΐʂ 19

Slide 20

Slide 20 text

▶ ผΧςΰϦͷcase͕ࠞͬͨ͟Enumɹᶄ ΋ͬͱݴ͑͹ɺ let job: Job // ! Optionalʹͨ͘͠ͳ͍ͳΒ init?(json: JSON) { guard job = Job(json["job"].stringValue) else { // Enum͕࡞Εͳ͍৔߹ɺ // failable initializerʹͯ͠ܕ͝ͱ௵ͦ͏ return nil } self.job = job ... } 20

Slide 21

Slide 21 text

࢓༷ͱͯ͠ ʮΩϟϥʹ ͠ΐ͗͘ΐ͏ ͕͋ΔʯͳΒ ܕઃܭͱͯ͠΋ඞͣ ʮ ͠ΐ͗͘ΐ͏ ͕͋Δʯ΂͖ 21

Slide 22

Slide 22 text

ʮ ͠ΐ͗͘ΐ͏ ͕ͳ͍ʯܕઃܭΛڐ͢ͱ ίʔυΛॻ্͘Ͱ΋ৗʹ ʮ ͠ΐ͗͘ΐ͏ ͕ͳ͍ʯέʔεΛ ߟྀ͠ͳ͖Ό͍͚ͳ͘ͳΔ 22

Slide 23

Slide 23 text

ग़య: ܕ҆શੑͱ͸Կ͔ | ϓϩάϥϛϯά | POSTD http://postd.cc/what-is-type-safety/ 23

Slide 24

Slide 24 text

Swift͸ܕ҆શݴޠ 24

Slide 25

Slide 25 text

͔ͤͬ͘ͳΒ ܕγεςϜͷԸܙΛ ड͚ΒΕΔ ΑΓྑ͍ܕઃܭΛ! 25

Slide 26

Slide 26 text

26

Slide 27

Slide 27 text

ͱΜͰ΋ͳ͍Enumͷ ΉΕ͕ ͋ΒΘΕͨʂ ɹ ผΧςΰϦͷcase͕ࠞͬͨ͟Enum ▶ ҟͳΔίϯςΩετͰ࢖͍ճ͞ΕΔEnum ɹ άϧʔϐϯάͷͨΊ͚ͩͷEnum 27

Slide 28

Slide 28 text

!γνϡΤʔγϣϯ! 4 ͯΜ͠ΐ͘͠·͢ 4 ͨͩ͠ɺΏ͏͠Όʹ͸ ɹɹͯΜ͠ΐ͘Ͱ͖·ͤΜ 28

Slide 29

Slide 29 text

final class μʔϚͷਆ఼ViewModel { /// TableViewCellͷrowͱׂͯ͠Γ౰ͯΔ഑ྻ let options: [Character.Job] = [ //.Ώ͏͠Ό, !స৬ෆՄೳͳͷͰলུ .ͤΜ͠, .Ϳͱ͏͔, .·΄͏͔͍ͭ, .ͦ͏Γΐ ] let targetCharacter: Character func select(_ selection: Character.Job) { switch selection { case .Ώ͏͠Ό: return //Ώ͏͠Όʹ͸స৬Ͱ͖ͳ͍ default: changeJob( of: targetCharacter, to: selection) } } ... } 29

Slide 30

Slide 30 text

!ɹ 30

Slide 31

Slide 31 text

switch selection { case .Ώ͏͠Ό: return //Ώ͏͠Όʹ͸స৬Ͱ͖ͳ͍ default: changeJob(of: targetCharacter, to: selection) } ! ࠓճ͸ૣظreturnͰࡁΉύλʔϯ͔΋͠Εͳ͍͚Ͳɺ ৔߹ʹΑͬͯ͸ɺ࠷ѱॻ͚Δॲཧ͕ͳͯ͘ fatalError() ͠ͳ͖Ό͍͚ͳ͍΍ͭͩ 31

Slide 32

Slide 32 text

Կނ બ୒ࢶʹͳ͍ Ώ͏͠Όͷ͜ͱΛ ؾʹ͠ͳ͖Ό ͳΒΜͷͩ 32

Slide 33

Slide 33 text

Ώ͏͠Ό΁ͷస৬caseɺ ࣮ӡ༻্͸͋Γ͑ͳ͍͚ΕͲɺ ϩδοΫ্͸ଘࡏͯ͠͠·͏͔Β ࢓ํͳ͍… 33

Slide 34

Slide 34 text

Enum͔Β .Ώ͏͠Ό Λ֎͢͜ͱͳΜͯ Ͱ͖ͳ͍͠… 34

Slide 35

Slide 35 text

ຊ౰ʹʁ 35

Slide 36

Slide 36 text

ʮΩϟϥͷ ͠ΐ͗͘ΐ͏ʯͱ ʮస৬Ͱ͖Δ ͠ΐ͗͘ΐ͏ʯ͸ ίϯςΩετ͕ҧ͏ 36

Slide 37

Slide 37 text

ίϯςΩετ͕ҧ͏ͳΒɺ ͦΕ͸ผͷEnumͰ؅ཧ͢Ε͹͍͍ ͭ·Γɺ͜͏Ͱ͸ͳ͘… final class μʔϚͷਆ఼ViewModel { let options: [Character.Job] func select(_ selection: Character.Job) { switch selection { case .Ώ͏͠Ό: return //Ώ͏͠Όʹ͸స৬Ͱ͖ͳ͍ default: changeJob(of: targetCharacter, to: selection) } } ... } 37

Slide 38

Slide 38 text

ίϯςΩετ͕ҧ͏ͳΒɺ ͦΕ͸ผͷEnumͰ؅ཧ͢Ε͹͍͍ ͜͏ʂ final class μʔϚͷਆ఼ViewModel { enum ChangableJob { //స৬ͱ͍͏ίϯςΩετͰͷΈ࢖͏ʂ case ͤΜ͠, Ϳͱ͏͔, ·΄͏͔͍ͭ, ͦ͏Γΐ } let options: [ChangableJob] func select(_ selection: ChangableJob) { //બ୒ࢶʹ͋Δ͠ΐ͗͘ΐ͏͔͠౉ͬͯ͜ͳ͍ //΋͏ɺΏ͏͠Όͷ͜ͱ͸ߟ͑ͳͯ͘ྑ͍…ʂ changeJob(of: targetCharacter, to: selection) } ... } 38

Slide 39

Slide 39 text

ίϯςΩετڥքΛҙࣝͯ͠ ద੾ʹEnumͷద༻ൣғΛ෼அ͢Ε͹ ࢓༷มߋɾ௥Ճ͕ൃੜͨ͠৔߹ʹ΋ ӨڹΛہॴԽͰ͖·͢! 39

Slide 40

Slide 40 text

40

Slide 41

Slide 41 text

ͱΜͰ΋ͳ͍Enumͷ ΉΕ͕ ͋ΒΘΕͨʂ ɹ ผΧςΰϦͷcase͕ࠞͬͨ͟Enum ɹ ҟͳΔίϯςΩετͰ࢖͍ճ͞ΕΔEnum ▶ άϧʔϐϯάͷͨΊ͚ͩͷEnum 41

Slide 42

Slide 42 text

!γνϡΤʔγϣϯ! ɹɹɹɹɹɹͦ͏ͼͷछผΛબΜͰ͔Βɹ⾣ɹͦ͏ͼΛબͼ·͢ 42

Slide 43

Slide 43 text

struct Equipment: Item { enum Kind { case Ϳ͖ case ΑΖ͍ case ͨͯ case ͔Ϳͱ } let kind: Kind ... } 43

Slide 44

Slide 44 text

final class ͦ͏ͼListViewModel { let character: Character //ର৅Ωϟϥ let equipments: [Equipment] //TableViewʹදࣔ͢ΔΞΠςϜͷϦετ init(character: Character, for kind: Equipment.Kind) { self.equipments = character.items //Ωϟϥͷ͍࣋ͬͯΔΞΠςϜͷதͰɺ .flatMap { $0 as? Equipment } // ͦ͏ͼͰ͋Γɺ .filter { $0.kind == kind } // ࢦఆ͞ΕͨछผͱҰக͢Δ΋ͷΛTableViewʹදࣔ self.character = character } func select(equipment: Equipment) { //ͦ͏ͼͷछྨʹΑͬͯɺ΍Δ͜ͱ͕มΘΔ switch equipment.kind { case .Ϳ͖: performProcess(asWeapon: equipment) case .ΑΖ͍: performProcess(asArmor: equipment) case .ͨͯ: performProcess(asShield: equipment) case .͔Ϳͱ: performProcess(asHelmet: equipment) } } private func performProcess(asWeapon weapon: Equipment) { guard case .Ϳ͖ = weapon.kind else { return } ... } ... } 44

Slide 45

Slide 45 text

!ɹ 45

Slide 46

Slide 46 text

͜ͷίʔυɺ ݏͳ೏͍͕͠·͢Ͷ switch equipment.kind { case .Ϳ͖: performProcess(asWeapon: equipment) case .ΑΖ͍: ... } private func performProcess( asWeapon weapon: Equipment) { guard case .Ϳ͖ = weapon.kind else { return } ... 46

Slide 47

Slide 47 text

Կނ ͢ͰʹͿ͖ͩͱ ಛఆͰ͖ͯΔΞΠςϜʹ ౎౓νΣοΫೖΕͳ͖Ό ͳΒΜͷͩ 47

Slide 48

Slide 48 text

Enumͷར఺ ͻͱͭͷܕͰ ෳ਺ͷέʔεΛ వΊͯදݱͰ͖Δ 48

Slide 49

Slide 49 text

Enumͷܽ఺ ෳ਺ͷέʔε͕ ͻͱͭͷܕʹ వΊΒΕͯ͠·͏ 49

Slide 50

Slide 50 text

…͍ͬͯ͏͔ ʮͦ͏ͼʯͷछผͬͯผʹ ྻڍ͢Δඞཁͳ͘ͳ͍ʁ 50

Slide 51

Slide 51 text

!͜ͷը໘Ͱ͸ ྻڍ͕ඞཁ͚ͩͲɺ ͦͷίϯςΩετʹ റΒΕΔඞཁ͕ ͳ͍ͬͯ͜ͱ͸ɺ طʹઆ໌ͨ͠ͱ͓Γ 51

Slide 52

Slide 52 text

ͳΒɺ͜ΕͰ͍͍Μ͡Όͳ͍ʁ struct Weapon: Item, Equipable { ... } struct Armor: Item, Equipable { ... } struct Shield: Item, Equipable { ... } struct Helmet: Item, Equipable { ... } 52

Slide 53

Slide 53 text

final class ͦ͏ͼListViewModel { let character: Character //ର৅Ωϟϥ let equipments: [E] //TableViewʹදࣔ͢ΔΞΠςϜͷϦετ init(character: Character) { self.equipments = character.items //Ωϟϥͷ͍࣋ͬͯΔΞΠςϜͷதͰɺ .flatMap { $0 as? E } // ͦͷͦ͏ͼछผͷ΋ͷΛTableViewʹදࣔ self.character = character } func select(equipment: E) { switch equipment { case let e as Weapon: performProcess(weapon: e) case let e as Armor: performProcess(armor: e) case let e as Shield: performProcess(shield: e) case let e as Helmet: performProcess(helmet: e) default: () } } // ܕϨϕϧͰ Ϳ͖ ͩͱಛఆͰ͖͍ͯΔʂʂ private func performProcess(weapon: Weapon) { ... } } 53

Slide 54

Slide 54 text

ܕ҆શ! 54

Slide 55

Slide 55 text

ʮࣅͨΑ͏ͳ΋ͷΛ άϧʔϐϯά͢Δͱ͖ʹ ͱΓ͋͑ͣEnumʯ 55

Slide 56

Slide 56 text

…͢Δલʹɺ ͪΐͬͱߟ͑ͯΈ·ͤΜ͔ ը໘ͷදࣔཁૉͱ͔ɺAPIͷ޲͖ઌͱ͔ɺ ΍Γ͕ͪͰ͢ΑͶ… 56

Slide 57

Slide 57 text

57

Slide 58

Slide 58 text

࠷ޙʹɺ EnumΛ࢖͏΂͖͔νΣοΫγʔτ 4 ͦͷάϧʔϓ͸switchจͰ໢ཏ͢Δඞཁ͕͋Δ͔ʁ 4 ͳ͍ͳΒɺprotocol + ݸผͷstructͰྑ͍ͷͰ ͸ʁ 4 ͋Δ͍͸άϧʔϐϯάࣗମɺෆཁͳͷͰ͸ʁ 4 ΧςΰϦͷҧ͏case͕ࠞͬͯ͟ͳ͍͔ʁ 4 ͦͷEnum͸ɺίϯςΩετʹԊͬͨ΋ͷ͔ʁ 58

Slide 59

Slide 59 text

59

Slide 60

Slide 60 text

!…ͱ͸͍͑ String enum͸ศརͰ͚͢ͲͶͬʂ enum ;͔ͬͭͷ͡Ύ΋Μ: String { case lv25 = "΄Γ͍Ώ͏ɹ͑͡ʹͭ͘͢ͲɹΒ͑͘͢͝ɹͱͩΑ" case lv20 = "·Δ͔ͭ͸ɹ΍ͭ͸Γ͔͍ͤɹ͍ͪͩͭͨɹͷͩΑ" case lv24 = "ΓΏ͏͓͏ɹ͓·͑͸΋͏͠ɹ͵Θ͔ͭͨɹ͔͹͔" case lv27 = "ͲΒ͑͘͸ɹͶͱ͛ʹͳͭͯɹͭ·Βͳ͍ɹ͋͏ͱ" case lv17 = "͑;͑;͸ɹͲΒ͑͘ΑΓ΋ɹ͓΋͠Ζ͍ɹ·͡͞" } passwordTextView.text = ;͔ͬͭͷ͡Ύ΋Μ.lv25.rawValue 60