Slide 1

Slide 1 text

2017/04/28 ࠓͳΒݴ͑Δɺ ΫϥεϝιουͱSwiftͷྺ࢙ ʙ։ൃݱ৔ͷޫͱҋʙ େࡕΦϑΟε։ઃ1प೥ษڧձ

Slide 2

Slide 2 text

About Me

Slide 3

Slide 3 text

• ాத ޹໌ (Takaaki Tanaka) • Ϋϥεϝιουגࣜձࣾ • ϞόΠϧόοΫΤϯυ • @kongmingtrap • Swift / Objective-C / Scala / JavaScript … • GyazSquare / GitHub

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

ؓ࿩ٳ୊

Slide 7

Slide 7 text

Introduction

Slide 8

Slide 8 text

Introduction •Objective-CͰͷiOSͷ։ൃྺ͕໿3೥ •Swift͸ɺ΄΅ະܦݧ •Ұ͔ΒSwiftͰ࡞ΒΕͨϓϩδΣΫτʹܞ ΘΓ͔ͨͬͨ •Ver 1ͷࠒͷSwift͸҆ఆ͍ͯ͠ͳ͔ͬͨͨ ΊɺσϦόϦʔ༏ઌͰObjective-C͕࠾༻ ͞Ε͍ͯͨ

Slide 9

Slide 9 text

Introduction •Objective-CͰͷiOSͷ։ൃྺ͕໿3೥ •Swift͸ɺ΄΅ະܦݧ •Ұ͔ΒSwiftͰ࡞ΒΕͨϓϩδΣΫτʹܞ ΘΓ͔ͨͬͨ •Ver 1ͷࠒͷSwift͸҆ఆ͍ͯ͠ͳ͔ͬͨͨ ΊɺσϦόϦʔ༏ઌͰObjective-C͕࠾༻ ͞Ε͍ͯͨ

Slide 10

Slide 10 text

Introduction •Objective-CͰͷiOSͷ։ൃྺ͕໿3೥ •Swift͸ɺ΄΅ະܦݧ •Ұ͔ΒSwiftͰ࡞ΒΕͨϓϩδΣΫτʹܞ ΘΓ͔ͨͬͨ •Ver 1ͷࠒͷSwift͸҆ఆ͍ͯ͠ͳ͔ͬͨͨ ΊɺσϦόϦʔ༏ઌͰObjective-C͕࠾༻ ͞Ε͍ͯͨ Ϋϥεϝιου΁స৬

Slide 11

Slide 11 text

Classmethod with Swift

Slide 12

Slide 12 text

http://dev.classmethod.jp/smartphone/swift/

Slide 13

Slide 13 text

No content

Slide 14

Slide 14 text

http://amzn.asia/dnXD7zd ਡ๚ ༔ل

Slide 15

Slide 15 text

Introduction •ೖࣾ౰ॳ(2015೥10݄)ͷ࣌఺Ͱ͸Swiftͷϓϩ δΣΫτ͸1ͭͷΈ •ͦͷϓϩδΣΫτΛ୲౰ͤͯ͞΋Βͬͨ •͍͔ͭ͘ͷػೳͷ௥ՃΛ୲౰ •લ೚ऀ͸όοΫΤϯυ୲౰ͱͳ͍ͬͯͨʢPlay / Scalaʣ

Slide 16

Slide 16 text

Agenda

Slide 17

Slide 17 text

Agenda

Slide 18

Slide 18 text

Agenda •Contact with Architecture •Battle with Swift version •Delivery is first priority •Battle with Swift version, second

Slide 19

Slide 19 text

Agenda •Contact with Architecture •Battle with Swift version •Delivery is first priority •Battle with Swift version, second

Slide 20

Slide 20 text

Contact with Architecture

Slide 21

Slide 21 text

https://www.objc.io/issues/13-architecture/viper/ Architecting iOS Apps with VIPER

Slide 22

Slide 22 text

https://www.slideshare.net/UsrNameu1/viper-arch VIPER ΞʔΩςΫνϟʹΑΔ iOS ΞϓϦͷઃܭ

Slide 23

Slide 23 text

Contact with Architecture •σϦόϦʔ༏ઌͷ։ൃܦݧ͕ଟ͔ͬͨͨΊɺ ϚογϒViewController΋ڐ༰͞Ε͕ͪͩͬͨ •ϨΠϠʔԽ͞ΕͨΫϦʔϯͳΞʔΩςΫνϟ͸ ࢐৽ͩͬͨ •ςετίʔυ͕ॆ࣮͍ͯͨ͠

Slide 24

Slide 24 text

Contact with Architecture •iOS 7΋αϙʔτ͍ͯͨͨ͠ΊɺҰ෦ͷϥΠϒϥ Ϧ͕CocoaPodsʹରԠ͍ͯ͠ͳ͔ͬͨ •CocoaPodsʹରԠ͍ͯ͠ͳ͔ͬͨϥΠϒϥϦ͸ Submoduleܦ༝ͰΠϯϙʔτ͍ͯͨ͠ •ϑΝΠϧ਺͕ଟ͍ҝɺΞʔΩςΫνϟΛཧղ͠ ͳ͍ͱɺमਖ਼ʹ͕͔͔࣌ؒͬͨ

Slide 25

Slide 25 text

• CargoBay • CorePlot • MBProgressHUD • UICKeyChainStore • JASidePanels • MagicalRecord • BlocksKit/UIKit • BlocksKit/MessageUI • Alamofire • SwiftyJSON • BrightFutures • OHHTTPStubs • Quick • Nimble

Slide 26

Slide 26 text

• CargoBay • CorePlot • MBProgressHUD • UICKeyChainStore • JASidePanels • MagicalRecord • BlocksKit/UIKit • BlocksKit/MessageUI • Alamofire • SwiftyJSON • BrightFutures • OHHTTPStubs • Quick • Nimble

Slide 27

Slide 27 text

http://dev.classmethod.jp/smartphone/swift-brightfutures-1/

Slide 28

Slide 28 text

Future / Promise Future ͸ฒྻʹ࣮ߦ͞ΕΔෳ਺ͷԋࢉΛऔΓѻ͏ͷʹศརͳ ํ๏Λఏڙ͢ΔɻͦΕ͸ޮ཰తͰϊϯϒϩοΩϯάͳํ๏ͩɻ େ·͔ͳߟ͑ํ͸γϯϓϧͳ΋ͷͰɺFuture ͸·ͩଘࡏ͠ͳ͍ ܭࢉ݁Ռʹର͢ΔϓϨʔεϗϧμͷΑ͏ͳ΋ͷͩɻ Ұൠత ʹɺFuture ͷ݁Ռ͸ฒߦʹܭࢉ͞ΕޙͰूܭ͢Δ͜ͱ͕Ͱ͖ Δɻ ͜ͷΑ͏ʹฒߦͳλεΫΛ߹੒͢Δ͜ͱͰɺΑΓ଎͘ɺ ඇಉظͰɺϊϯϒϩοΩϯάͳฒྻίʔυͱͳΔ͜ͱ͕ଟ͍ɻ http://docs.scala-lang.org/ja/overviews/core/futures.html

Slide 29

Slide 29 text

http://docs.scala-lang.org/ja/overviews/core/futures.html

Slide 30

Slide 30 text

open func postWaveformWithLead( _ lead: Lead, subjectiveSymptoms: [Checkup.SubjectiveSymptom]?, createDate: Date, saving: Bool, waveformData: Data) -> Future { let waveformUUID = UUID().uuidString return createLocalWaveformWithUuid( waveformUUID, lead: lead, subjectiveSymptoms: subjectiveSymptoms, createDate: createDate, waveformData: waveformData) .flatMap { [weak self] _ -> Future in self?.uploadWaveformDatumWithLead( lead, subjectiveSymptoms: subjectiveSymptoms, createDate: createDate, saving: saving, waveformData: waveformData ) ?? Future(error: InteractorCancelError) } .flatMap { [weak self] json -> Future in self?.executeTaskAfterUploadWithJson(json, uuid: waveformUUID) ?? Future(error: InteractorCancelError) } }

Slide 31

Slide 31 text

open func postWaveformWithLead( _ lead: Lead, subjectiveSymptoms: [Checkup.SubjectiveSymptom]?, createDate: Date, saving: Bool, waveformData: Data) -> Future { let waveformUUID = UUID().uuidString return createLocalWaveformWithUuid( waveformUUID, lead: lead, subjectiveSymptoms: subjectiveSymptoms, createDate: createDate, waveformData: waveformData) .flatMap { [weak self] _ -> Future in self?.uploadWaveformDatumWithLead( lead, subjectiveSymptoms: subjectiveSymptoms, createDate: createDate, saving: saving, waveformData: waveformData ) ?? Future(error: InteractorCancelError) } .flatMap { [weak self] json -> Future in self?.executeTaskAfterUploadWithJson(json, uuid: waveformUUID) ?? Future(error: InteractorCancelError) } }

Slide 32

Slide 32 text

open func postWaveformWithLead( _ lead: Lead, subjectiveSymptoms: [Checkup.SubjectiveSymptom]?, createDate: Date, saving: Bool, waveformData: Data) -> Future { let waveformUUID = UUID().uuidString return createLocalWaveformWithUuid( waveformUUID, lead: lead, subjectiveSymptoms: subjectiveSymptoms, createDate: createDate, waveformData: waveformData) .flatMap { [weak self] _ -> Future in self?.uploadWaveformDatumWithLead( lead, subjectiveSymptoms: subjectiveSymptoms, createDate: createDate, saving: saving, waveformData: waveformData ) ?? Future(error: InteractorCancelError) } .flatMap { [weak self] json -> Future in self?.executeTaskAfterUploadWithJson(json, uuid: waveformUUID) ?? Future(error: InteractorCancelError) } }

Slide 33

Slide 33 text

open func postWaveformWithLead( _ lead: Lead, subjectiveSymptoms: [Checkup.SubjectiveSymptom]?, createDate: Date, saving: Bool, waveformData: Data) -> Future { let waveformUUID = UUID().uuidString return createLocalWaveformWithUuid( waveformUUID, lead: lead, subjectiveSymptoms: subjectiveSymptoms, createDate: createDate, waveformData: waveformData) .flatMap { [weak self] _ -> Future in self?.uploadWaveformDatumWithLead( lead, subjectiveSymptoms: subjectiveSymptoms, createDate: createDate, saving: saving, waveformData: waveformData ) ?? Future(error: InteractorCancelError) } .flatMap { [weak self] json -> Future in self?.executeTaskAfterUploadWithJson(json, uuid: waveformUUID) ?? Future(error: InteractorCancelError) } }

Slide 34

Slide 34 text

ͳΜͰ#PMUT͡Όͳ͍ΜͰ͢ ͔ʁ

Slide 35

Slide 35 text

ͳΜͰ#PMUT͡Όͳ͍ΜͰ͢ ͔ʁ ඇಉظॲཧ͸'VUVSFͰॻ͚ ͹ඒ͍͠

Slide 36

Slide 36 text

ΞοϋΠ ඇಉظॲཧ͸'VUVSFͰॻ͚ ͹ඒ͍͠

Slide 37

Slide 37 text

http://dev.classmethod.jp/server-side/scala-concurrent-future/

Slide 38

Slide 38 text

http://dev.classmethod.jp/server-side/scala-learn-flatmap/

Slide 39

Slide 39 text

ͳΜͰ3Y4XJGU͡Όͳ͍Μ Ͱ͔͢ʁ

Slide 40

Slide 40 text

ͳΜͰ3Y4XJGU͡Όͳ͍Μ Ͱ͔͢ʁ ඇಉظॲཧ͸'VUVSFͰॻ͚ ͹ඒ͍͠

Slide 41

Slide 41 text

ͳΜͰ3Y4XJGU͡Όͳ͍Μ Ͱ͔͢ʁ ඇಉظॲཧ͸'VUVSFͰॻ͚ ͹ඒ͍͠

Slide 42

Slide 42 text

Contact with Architecture •ར༻͢ΔϥΠϒϥϦ͸νʔϜϝϯόʔͱϨ Ϗϡʔ͢Δ͜ͱ͸ඞਢ •ϚογϒViewControllerʹͳΒͳ͍Α͏ɺΞʔΩ ςΫνϟͷಋೖ͸ۃྗߦ͏ •ͲͷΞʔΩςΫνϟΛಋೖ͢Δ͔͸νʔϜͱσ ϦόϦʔͱ૬ஊ

Slide 43

Slide 43 text

Battle with Swift version

Slide 44

Slide 44 text

Swift 2.1 • Xcode 7 + iOS 9 SDKͰϏϧυ͕Մೳ • Swift 2.x ܥͷAPIσβΠϯ • try / catch͕௥Ճ • Ұ෦ͷϓϩύςΟ͕Optionalʹͳͬͨ(SDK) • Dynamic LibraryରԠ(Xcode 7)

Slide 45

Slide 45 text

Migration • Xcode 7.1Ͱىಈͨ͠ࡍɺաڈͷSwift όʔ δϣϯͷ৔߹͸Convertը໘͕ىಈ͢Δ • ʮEdit > Convert > To Current Swift Syntax.ʯ Ͱ΋࣮ߦՄೳ

Slide 46

Slide 46 text

No content

Slide 47

Slide 47 text

Migration • Xcode 7.1Ͱىಈͨ͠ࡍɺաڈͷSwift όʔ δϣϯͷ৔߹͸Convertը໘͕ىಈ͢Δ • ʮEdit > Convert > To Current Swift Syntax.ʯ Ͱ΋࣮ߦՄೳ • Swift 1.2 → Swift 2.1ͷ࣌͸࢖͍΋ͷʹͳΒ ͳ͔ͬͨ ← New!

Slide 48

Slide 48 text

஍ಓͳमਖ਼࡞ۀ • BrightFuturesͷFutureͷܕ͕มߋʹͳͬͨ ͷͰमਖ਼

Slide 49

Slide 49 text

஍ಓͳमਖ਼࡞ۀ • Resultͷܕ͕มߋʹͳͬͨͷͰमਖ਼

Slide 50

Slide 50 text

஍ಓͳमਖ਼࡞ۀ • Dynamic LibraryରԠ • iOS 7Λαϙʔτ͔Βআ֎ͨ͠

Slide 51

Slide 51 text

஍ಓͳमਖ਼࡞ۀ • ϓϩύςΟͷOptionalରԠ

Slide 52

Slide 52 text

஍ಓͳमਖ਼࡞ۀ • ExceptionͷthrowରԠ

Slide 53

Slide 53 text

஍ಓͳमਖ਼࡞ۀ • map → forEachରԠ

Slide 54

Slide 54 text

iOS 9ରԠʢATSରԠʣ • S3ʹஔ͍ͨϑΝΠϧ͕औಘͰ͖ͳ͘ͳͬͨ • Preparing Your Apps for iOS 9Λࢀߟʹ Info.plistΛमਖ਼

Slide 55

Slide 55 text

Result

Slide 56

Slide 56 text

Battle with Swift version • iOS 7ͷαϙʔτͷ༗ແ͕ͦͷޙͷ޻਺ʹ େ͖ͳӨڹΛ༩͑ͨ • Τϥʔɾܯࠂͷ਺͕ଟͯ͘ରԠʹ͕࣌ؒ ͔͔ͬͨ • Ϗϧυͷ଎౓্͕͕ͬͨʢVer 1.2 : 12min → Ver 2.1 : 3minʣ

Slide 57

Slide 57 text

Delivery is first priority

Slide 58

Slide 58 text

Delivery is first priority

Slide 59

Slide 59 text

No content

Slide 60

Slide 60 text

Battle with Swift version, second

Slide 61

Slide 61 text

Swift 3.0 • NS Prefix͔Βͷ୤٫ • ৽ͨͳΔAPIσβΠϯΨΠυϥΠϯ

Slide 62

Slide 62 text

Swift 3.0 • NS Prefix͔Βͷ୤٫ → Ұ෦࢒Γ·ͨ͠ ʢNSNumberʣ • ৽ͨͳΔAPIσβΠϯΨΠυϥΠϯ → طଘ ͷϥΠϒϥϦͷϝιου໊มΘΓ͗͢ • ABI҆ఆԽ → Swift 4·Ͱ଴ͬͯͶ

Slide 63

Slide 63 text

No content

Slide 64

Slide 64 text

ʊਓਓਓਓਓਓਓਓਓʊ ʼɹࢼ͞ΕΔ஧੣৺ɹʻ ʉ:?:?:?:?:?:?:?:ʉ

Slide 65

Slide 65 text

Swift 2.3 • Xcode 8 + iOS 10 SDKͰϏϧυ͕Մೳ • Swift 2.x ܥͷAPIσβΠϯ • ͱΓ͋͑ͣٸ͍ͰiOS 10ͰϏϧυ͢Δඞཁ ͕͋Δ৔߹

Slide 66

Slide 66 text

Swift 2.3 9DPEF3FMFBTF/PUFT • Xcode 8.2 ͕࠷ޙͷαϙʔτʹͳΔͨΊɺ Swift 3.0΁ͷରԠ͸ඞਢ

Slide 67

Slide 67 text

Migration to Swift 3.0

Slide 68

Slide 68 text

Swift 2.2΁ͷҠߦ • Xcode 7.2 + Swift 2.1 ͷ։ൃ؀ڥΛXcode 8.2 Ͱىಈͨ͠ࡍɺʮEdit > Convert > To Current Swift Syntax.ʯͷର৅ʹTarget͕දࣔ ͞Εͳ͔ͬͨ • ͱΓ͋͑ͣɺXcode 7.3ͰSwift 2.1͔ΒSwift 2.2΁Ҡߦͨ͠

Slide 69

Slide 69 text

Migration • Xcode 8.2Ͱىಈͨ͠ࡍɺաڈͷSwift όʔδϣ ϯͷ৔߹͸Convertը໘͕ىಈ͢Δ • ʮEdit > Convert > To Current Swift Syntax.ʯͰ΋ ࣮ߦՄೳ • Swift 1.2 → Swift 2.1ͷ࣌͸࢖͍΋ͷʹͳΒͳ ͔ͬͨ

Slide 70

Slide 70 text

No content

Slide 71

Slide 71 text

No content

Slide 72

Slide 72 text

ʊਓਓਓਓਓਓਓਓਓʊ ʼɹ$POWFSU'BJMFEɹʻ ʉ:?:?:?:?:?:?:?:?:?ʉ

Slide 73

Slide 73 text

Migration • Xcode 8.2Ͱىಈͨ͠ࡍɺաڈͷSwift όʔδϣ ϯͷ৔߹͸Convertը໘͕ىಈ͢Δ • ʮEdit > Convert > To Current Swift Syntax.ʯͰ΋ ࣮ߦՄೳ • Swift 1.2 → Swift 2.1ͷ࣌͸࢖͍΋ͷʹͳΒͳ ͔ͬͨ • Swift 2.2 → Swift 3.0ͷ࣌΋࢖͍΋ͷʹͳΒͳ ͔ͬͨ ← New!

Slide 74

Slide 74 text

ͦΕͰ΋ແ͍ΑΓ͸Ϛγ • UIKitͷmethodͷม׵ • Enumͷupper case → lower caseม׵ • NSPrefixͷϥΠϒϥϦͷม׵

Slide 75

Slide 75 text

ͻͨ͢Β஍ಓͳ࡞ۀ • CurryԽͨ͠ϝιουͷमਖ਼ public static func log(level level: Level)(@autoclosure name: () -> String) (@autoclosure message: () -> String) -> String { if level.rawValue <= Logger.currentLevel.rawValue { let full = "\(level.description): \(name()) - \(message())" print(full) return full } return "" }

Slide 76

Slide 76 text

ͻͨ͢Β஍ಓͳ࡞ۀ • CurryԽͨ͠ϝιουͷमਖ਼ public static func log(level: Level) -> ((@escaping () -> String) -> ((@escaping () -> String) -> String)) { return { (name: @escaping (() -> String)) in return { (message: @escaping (() -> String)) in if level.rawValue <= Logger.currentLevel.rawValue { let full = "\(level.description): \(name())) - \(message())" print(full) return full } return "" } } }

Slide 77

Slide 77 text

ͻͨ͢Β஍ಓͳ࡞ۀ • closureʹ@escapingͷ௥Ճ

Slide 78

Slide 78 text

ͻͨ͢Β஍ಓͳ࡞ۀ • Ҡߦπʔϧ͕ม׵ͨ͠Օॴͷमਖ਼ • Ωϟετ → Ωϟετ → Ωϟετ Date as NSDate as Date String as NSString as String

Slide 79

Slide 79 text

ͻͨ͢Β஍ಓͳ࡞ۀ • Unit Testͷमਖ਼

Slide 80

Slide 80 text

Result

Slide 81

Slide 81 text

Result

Slide 82

Slide 82 text

files additions deletions Ver 2.1 147 1268 1130 Ver 3.0 247 4314 4372 Pull Request Diff

Slide 83

Slide 83 text

Battle with Swift version, second • Ͱ͖Ε͹ೋ౓ͱ΍Γͨ͘ͳ͍ • ίϯϑϦΫτղফͷͨΊɺݽಠͳ࡞ۀͱ ͳΔ • ஧੣৺Λࢼ͞ΕΔ

Slide 84

Slide 84 text

Recap

Slide 85

Slide 85 text

Recap •৽نϓϩδΣΫτ͸શͯSwiftʹ •ΞʔΩςΫνϟʹ͍ͭͯ૬ஊͰ͖Δ౔৕ ͕ܗ੒͞Εͨ •ΞʔϦʔΞμϓλʔͱͯ͠ɺ͖᪴ͳ͕Β΋ ϊ΢ϋ΢ΛͨΊ͍͚ͯΔ

Slide 86

Slide 86 text

Recap •Swiftͷݴޠ࢓༷ͷมԽʹ൱Ԡͳ͠ʹରԠ ΛഭΒΕΔ •બ୒ͨ͠ΞʔΩςΫνϟʹΑͬͯ͸ҭ੒ ίετ͕ൃੜ͢Δ •σϦόϦʔΛ༏ઌ͠ͳ͚Ε͹ͳΒͳ͍ঢ় گ͸ඞͣൃੜ͢Δ

Slide 87

Slide 87 text

No content

Slide 88

Slide 88 text

Thank you!

Slide 89

Slide 89 text

One more thing…

Slide 90

Slide 90 text

ʲ େࡕΦϑΟε։ઃ1प೥!! ʳ Ϋϥεϝιουͷ։ൃΛ஌Δʂશ7ճษڧ http://dev.classmethod.jp/news/mobileteam-inosaka/

Slide 91

Slide 91 text

ʲ େࡕΦϑΟε։ઃ1प೥!! ʳ Ϋϥεϝιουͷ։ൃΛ஌Δʂશ7ճษڧ http://dev.classmethod.jp/news/mobileteam-inosaka/

Slide 92

Slide 92 text

We're hiring!!

Slide 93

Slide 93 text

https://classmethod.jp/recruit/

Slide 94

Slide 94 text

AWSࣄۀ෦ AWSΤϯδχΞʢAWSγεςϜ؀ڥͷߏஙࢧԉʣ AWSιϦϡʔγϣϯΞʔΩςΫτʢAWSγεςϜ؀ڥ ίϯαϧɾߏஙɾӡ༻ࢧԉʣ AWSΦϖϨʔγϣϯίϯαϧλϯτʢAWSγεςϜ؀ڥͷӡ༻ࣗಈԽࢧԉʣ AWSαʔϏεσϕϩούʔʢAWSΛ׆༻ͨ͠αʔϏε։ൃʣ
 ϞόΠϧΞϓϦαʔϏε෦ iOS / AndroidΞϓϦ։ൃΤϯδχΞ ― ౦ژ / ࡳຈ / େࡕ ϞόΠϧόοΫΤϯυΤϯδχΞ ― ౦ژ / ࡳຈ / େࡕ DevOpsΤϯδχΞ ― ౦ژ / ࡳຈ / େࡕ ϓϩδΣΫτϚωʔδϟʔʢϞόΠϧΞϓϦʣ ― ౦ژ / େࡕ ݱࡏืूதͷ৬छ https://classmethod.jp/recruit/jobs/