Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
今なら言える、 クラスメソッドとSwiftの歴史 〜開発現場の光と闇〜
Search
Takaaki Tanaka
April 28, 2017
Technology
1.7k
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
今なら言える、 クラスメソッドとSwiftの歴史 〜開発現場の光と闇〜
大阪オフィス開設1周年勉強会の資料です
http://dev.classmethod.jp/news/mobileteam-inosaka-vol-3/
Takaaki Tanaka
April 28, 2017
More Decks by Takaaki Tanaka
See All by Takaaki Tanaka
[デモです] NotebookLM で作ったスライドの例
kongmingstrap
0
560
Zenn のウラガワ ~エンジニアのアウトプットを支える環境で Google Cloud が採用されているワケ~ #burikaigi #burikaigi_h
kongmingstrap
22
8.5k
AWS re:Invent 2024 ふりかえり
kongmingstrap
0
460
製造の課題に立ち向かう Manufacturing Data Engine と Manufacturing Connect の ご紹介
kongmingstrap
0
1.3k
Tellus の衛星データを見てみよう #mf_fukuoka
kongmingstrap
0
950
JAWS-UG 福岡 #16 re:Invent 現地に行った人のお話 #jawsugfuk #jawsug
kongmingstrap
0
750
AppMod の開発のイマを知るために現地に潜入した私が見たものは・・・? #GoogleCloudNext
kongmingstrap
0
860
Kong Gateway から読みとく、 API統合・API連携サービスの最新情報 #devio2023
kongmingstrap
0
2.3k
Cloud Run に憧れて Google Cloud を推進している話 / CX事業本部で使われている技術
kongmingstrap
0
370
Other Decks in Technology
See All in Technology
オブザーバビリティ、本当に活用できてる? 〜API連携×生成AIで成熟度を自動評価〜
dmmsre
1
3.6k
知らん間に、回ってる
ming_ayami
0
740
最適な自走を最小限の支援で — M&Aで拡大する組織で少人数SREが挑んだ1年 / SRE NEXT 2026
genda
0
1.5k
41歳でAWSが好きすぎてITエンジニアになったおっさんの話
yama3133
0
120
Network Firewallやっていき!
news_it_enj
0
170
AmplifyHostingConstructからSSRフレームワークのためのホスティング設計を考察する/amplify-hosting-construct
fossamagna
1
250
ボーイスカウトルールでメモリやスキルを改善しよう
azukiazusa1
4
1.5k
ソニー銀行におけるビジネスアジリティ向上のためのクラウドシフト戦略
srenext
0
860
AICoEでAIネイティブ組織への進化
yukiogawa
0
200
「AIに依存している」と 「AIを使いこなしている」の違い
k8yasuma
0
120
AI時代のPlaywright活用(システムテストを自動化する ー 実行エンジンにPla ywrightを選んだ理由)
ynisqa1988
1
660
壊して学ぶAWS CDK: そのcdk deployで消えるもの、残るもの
k_adachi_01
1
420
Featured
See All Featured
The Hidden Cost of Media on the Web [PixelPalooza 2025]
tammyeverts
2
360
Agile Actions for Facilitating Distributed Teams - ADO2019
mkilby
0
220
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.6k
The Invisible Side of Design
smashingmag
301
52k
Un-Boring Meetings
codingconduct
0
350
The Cost Of JavaScript in 2023
addyosmani
55
10k
Building Applications with DynamoDB
mza
96
7.1k
Rebuilding a faster, lazier Slack
samanthasiow
85
9.6k
Build your cross-platform service in a week with App Engine
jlugia
234
18k
Docker and Python
trallard
47
4k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
55k
How To Speak Unicorn (iThemes Webinar)
marktimemedia
1
510
Transcript
2017/04/28 ࠓͳΒݴ͑Δɺ ΫϥεϝιουͱSwiftͷྺ࢙ ʙ։ൃݱͷޫͱҋʙ େࡕΦϑΟε։ઃ1पษڧձ
About Me
• ాத ໌ (Takaaki Tanaka) • Ϋϥεϝιουגࣜձࣾ • ϞόΠϧόοΫΤϯυ •
@kongmingtrap • Swift / Objective-C / Scala / JavaScript … • GyazSquare / GitHub
None
None
ؓٳ
Introduction
Introduction •Objective-CͰͷiOSͷ։ൃྺ͕3 •Swiftɺ΄΅ະܦݧ •Ұ͔ΒSwiftͰ࡞ΒΕͨϓϩδΣΫτʹܞ ΘΓ͔ͨͬͨ •Ver 1ͷࠒͷSwift҆ఆ͍ͯ͠ͳ͔ͬͨͨ ΊɺσϦόϦʔ༏ઌͰObjective-C͕࠾༻ ͞Ε͍ͯͨ
Introduction •Objective-CͰͷiOSͷ։ൃྺ͕3 •Swiftɺ΄΅ະܦݧ •Ұ͔ΒSwiftͰ࡞ΒΕͨϓϩδΣΫτʹܞ ΘΓ͔ͨͬͨ •Ver 1ͷࠒͷSwift҆ఆ͍ͯ͠ͳ͔ͬͨͨ ΊɺσϦόϦʔ༏ઌͰObjective-C͕࠾༻ ͞Ε͍ͯͨ
Introduction •Objective-CͰͷiOSͷ։ൃྺ͕3 •Swiftɺ΄΅ະܦݧ •Ұ͔ΒSwiftͰ࡞ΒΕͨϓϩδΣΫτʹܞ ΘΓ͔ͨͬͨ •Ver 1ͷࠒͷSwift҆ఆ͍ͯ͠ͳ͔ͬͨͨ ΊɺσϦόϦʔ༏ઌͰObjective-C͕࠾༻ ͞Ε͍ͯͨ Ϋϥεϝιουస৬
Classmethod with Swift
http://dev.classmethod.jp/smartphone/swift/
None
http://amzn.asia/dnXD7zd ਡ๚ ༔ل
Introduction •ೖࣾॳ(201510݄)ͷ࣌ͰSwiftͷϓϩ δΣΫτ1ͭͷΈ •ͦͷϓϩδΣΫτΛ୲ͤͯ͞Βͬͨ •͍͔ͭ͘ͷػೳͷՃΛ୲ •લऀόοΫΤϯυ୲ͱͳ͍ͬͯͨʢPlay / Scalaʣ
Agenda
Agenda
Agenda •Contact with Architecture •Battle with Swift version •Delivery is
first priority •Battle with Swift version, second
Agenda •Contact with Architecture •Battle with Swift version •Delivery is
first priority •Battle with Swift version, second
Contact with Architecture
https://www.objc.io/issues/13-architecture/viper/ Architecting iOS Apps with VIPER
https://www.slideshare.net/UsrNameu1/viper-arch VIPER ΞʔΩςΫνϟʹΑΔ iOS ΞϓϦͷઃܭ
Contact with Architecture •σϦόϦʔ༏ઌͷ։ൃܦݧ͕ଟ͔ͬͨͨΊɺ ϚογϒViewControllerڐ༰͞Ε͕ͪͩͬͨ •ϨΠϠʔԽ͞ΕͨΫϦʔϯͳΞʔΩςΫνϟ ৽ͩͬͨ •ςετίʔυ͕ॆ࣮͍ͯͨ͠
Contact with Architecture •iOS 7αϙʔτ͍ͯͨͨ͠ΊɺҰ෦ͷϥΠϒϥ Ϧ͕CocoaPodsʹରԠ͍ͯ͠ͳ͔ͬͨ •CocoaPodsʹରԠ͍ͯ͠ͳ͔ͬͨϥΠϒϥϦ Submoduleܦ༝ͰΠϯϙʔτ͍ͯͨ͠ •ϑΝΠϧ͕ଟ͍ҝɺΞʔΩςΫνϟΛཧղ͠ ͳ͍ͱɺमਖ਼ʹ͕͔͔࣌ؒͬͨ
• CargoBay • CorePlot • MBProgressHUD • UICKeyChainStore • JASidePanels
• MagicalRecord • BlocksKit/UIKit • BlocksKit/MessageUI • Alamofire • SwiftyJSON • BrightFutures • OHHTTPStubs • Quick • Nimble
• CargoBay • CorePlot • MBProgressHUD • UICKeyChainStore • JASidePanels
• MagicalRecord • BlocksKit/UIKit • BlocksKit/MessageUI • Alamofire • SwiftyJSON • BrightFutures • OHHTTPStubs • Quick • Nimble
http://dev.classmethod.jp/smartphone/swift-brightfutures-1/
Future / Promise Future ฒྻʹ࣮ߦ͞ΕΔෳͷԋࢉΛऔΓѻ͏ͷʹศརͳ ํ๏Λఏڙ͢ΔɻͦΕޮతͰϊϯϒϩοΩϯάͳํ๏ͩɻ େ·͔ͳߟ͑ํγϯϓϧͳͷͰɺFuture ·ͩଘࡏ͠ͳ͍ ܭࢉ݁Ռʹର͢ΔϓϨʔεϗϧμͷΑ͏ͳͷͩɻ Ұൠత
ʹɺFuture ͷ݁Ռฒߦʹܭࢉ͞ΕޙͰूܭ͢Δ͜ͱ͕Ͱ͖ Δɻ ͜ͷΑ͏ʹฒߦͳλεΫΛ߹͢Δ͜ͱͰɺΑΓ͘ɺ ඇಉظͰɺϊϯϒϩοΩϯάͳฒྻίʔυͱͳΔ͜ͱ͕ଟ͍ɻ http://docs.scala-lang.org/ja/overviews/core/futures.html
http://docs.scala-lang.org/ja/overviews/core/futures.html
open func postWaveformWithLead( _ lead: Lead, subjectiveSymptoms: [Checkup.SubjectiveSymptom]?, createDate: Date,
saving: Bool, waveformData: Data) -> Future<Checkup, NSError> { let waveformUUID = UUID().uuidString return createLocalWaveformWithUuid( waveformUUID, lead: lead, subjectiveSymptoms: subjectiveSymptoms, createDate: createDate, waveformData: waveformData) .flatMap { [weak self] _ -> Future<JSON, NSError> in self?.uploadWaveformDatumWithLead( lead, subjectiveSymptoms: subjectiveSymptoms, createDate: createDate, saving: saving, waveformData: waveformData ) ?? Future(error: InteractorCancelError) } .flatMap { [weak self] json -> Future<Checkup, NSError> in self?.executeTaskAfterUploadWithJson(json, uuid: waveformUUID) ?? Future(error: InteractorCancelError) } }
open func postWaveformWithLead( _ lead: Lead, subjectiveSymptoms: [Checkup.SubjectiveSymptom]?, createDate: Date,
saving: Bool, waveformData: Data) -> Future<Checkup, NSError> { let waveformUUID = UUID().uuidString return createLocalWaveformWithUuid( waveformUUID, lead: lead, subjectiveSymptoms: subjectiveSymptoms, createDate: createDate, waveformData: waveformData) .flatMap { [weak self] _ -> Future<JSON, NSError> in self?.uploadWaveformDatumWithLead( lead, subjectiveSymptoms: subjectiveSymptoms, createDate: createDate, saving: saving, waveformData: waveformData ) ?? Future(error: InteractorCancelError) } .flatMap { [weak self] json -> Future<Checkup, NSError> in self?.executeTaskAfterUploadWithJson(json, uuid: waveformUUID) ?? Future(error: InteractorCancelError) } }
open func postWaveformWithLead( _ lead: Lead, subjectiveSymptoms: [Checkup.SubjectiveSymptom]?, createDate: Date,
saving: Bool, waveformData: Data) -> Future<Checkup, NSError> { let waveformUUID = UUID().uuidString return createLocalWaveformWithUuid( waveformUUID, lead: lead, subjectiveSymptoms: subjectiveSymptoms, createDate: createDate, waveformData: waveformData) .flatMap { [weak self] _ -> Future<JSON, NSError> in self?.uploadWaveformDatumWithLead( lead, subjectiveSymptoms: subjectiveSymptoms, createDate: createDate, saving: saving, waveformData: waveformData ) ?? Future(error: InteractorCancelError) } .flatMap { [weak self] json -> Future<Checkup, NSError> in self?.executeTaskAfterUploadWithJson(json, uuid: waveformUUID) ?? Future(error: InteractorCancelError) } }
open func postWaveformWithLead( _ lead: Lead, subjectiveSymptoms: [Checkup.SubjectiveSymptom]?, createDate: Date,
saving: Bool, waveformData: Data) -> Future<Checkup, NSError> { let waveformUUID = UUID().uuidString return createLocalWaveformWithUuid( waveformUUID, lead: lead, subjectiveSymptoms: subjectiveSymptoms, createDate: createDate, waveformData: waveformData) .flatMap { [weak self] _ -> Future<JSON, NSError> in self?.uploadWaveformDatumWithLead( lead, subjectiveSymptoms: subjectiveSymptoms, createDate: createDate, saving: saving, waveformData: waveformData ) ?? Future(error: InteractorCancelError) } .flatMap { [weak self] json -> Future<Checkup, NSError> in self?.executeTaskAfterUploadWithJson(json, uuid: waveformUUID) ?? Future(error: InteractorCancelError) } }
ͳΜͰ#PMUT͡Όͳ͍ΜͰ͢ ͔ʁ
ͳΜͰ#PMUT͡Όͳ͍ΜͰ͢ ͔ʁ ඇಉظॲཧ'VUVSFͰॻ͚ ඒ͍͠
ΞοϋΠ ඇಉظॲཧ'VUVSFͰॻ͚ ඒ͍͠
http://dev.classmethod.jp/server-side/scala-concurrent-future/
http://dev.classmethod.jp/server-side/scala-learn-flatmap/
ͳΜͰ3Y4XJGU͡Όͳ͍Μ Ͱ͔͢ʁ
ͳΜͰ3Y4XJGU͡Όͳ͍Μ Ͱ͔͢ʁ ඇಉظॲཧ'VUVSFͰॻ͚ ඒ͍͠
ͳΜͰ3Y4XJGU͡Όͳ͍Μ Ͱ͔͢ʁ ඇಉظॲཧ'VUVSFͰॻ͚ ඒ͍͠
Contact with Architecture •ར༻͢ΔϥΠϒϥϦνʔϜϝϯόʔͱϨ Ϗϡʔ͢Δ͜ͱඞਢ •ϚογϒViewControllerʹͳΒͳ͍Α͏ɺΞʔΩ ςΫνϟͷಋೖۃྗߦ͏ •ͲͷΞʔΩςΫνϟΛಋೖ͢Δ͔νʔϜͱσ ϦόϦʔͱ૬ஊ
Battle with Swift version
Swift 2.1 • Xcode 7 + iOS 9 SDKͰϏϧυ͕Մೳ •
Swift 2.x ܥͷAPIσβΠϯ • try / catch͕Ճ • Ұ෦ͷϓϩύςΟ͕Optionalʹͳͬͨ(SDK) • Dynamic LibraryରԠ(Xcode 7)
Migration • Xcode 7.1Ͱىಈͨ͠ࡍɺաڈͷSwift όʔ δϣϯͷ߹Convertը໘͕ىಈ͢Δ • ʮEdit > Convert
> To Current Swift Syntax.ʯ Ͱ࣮ߦՄೳ
None
Migration • Xcode 7.1Ͱىಈͨ͠ࡍɺաڈͷSwift όʔ δϣϯͷ߹Convertը໘͕ىಈ͢Δ • ʮEdit > Convert
> To Current Swift Syntax.ʯ Ͱ࣮ߦՄೳ • Swift 1.2 → Swift 2.1ͷ͍࣌ͷʹͳΒ ͳ͔ͬͨ ← New!
ಓͳमਖ਼࡞ۀ • BrightFuturesͷFutureͷܕ͕มߋʹͳͬͨ ͷͰमਖ਼
ಓͳमਖ਼࡞ۀ • Resultͷܕ͕มߋʹͳͬͨͷͰमਖ਼
ಓͳमਖ਼࡞ۀ • Dynamic LibraryରԠ • iOS 7Λαϙʔτ͔Βআ֎ͨ͠
ಓͳमਖ਼࡞ۀ • ϓϩύςΟͷOptionalରԠ
ಓͳमਖ਼࡞ۀ • ExceptionͷthrowରԠ
ಓͳमਖ਼࡞ۀ • map → forEachରԠ
iOS 9ରԠʢATSରԠʣ • S3ʹஔ͍ͨϑΝΠϧ͕औಘͰ͖ͳ͘ͳͬͨ • Preparing Your Apps for iOS
9Λࢀߟʹ Info.plistΛमਖ਼
Result
Battle with Swift version • iOS 7ͷαϙʔτͷ༗ແ͕ͦͷޙͷʹ େ͖ͳӨڹΛ༩͑ͨ • Τϥʔɾܯࠂͷ͕ଟͯ͘ରԠʹ͕࣌ؒ
͔͔ͬͨ • Ϗϧυͷ্͕͕ͬͨʢVer 1.2 : 12min → Ver 2.1 : 3minʣ
Delivery is first priority
Delivery is first priority
None
Battle with Swift version, second
Swift 3.0 • NS Prefix͔Βͷ٫ • ৽ͨͳΔAPIσβΠϯΨΠυϥΠϯ
Swift 3.0 • NS Prefix͔Βͷ٫ → Ұ෦Γ·ͨ͠ ʢNSNumberʣ • ৽ͨͳΔAPIσβΠϯΨΠυϥΠϯ
→ طଘ ͷϥΠϒϥϦͷϝιου໊มΘΓ͗͢ • ABI҆ఆԽ → Swift 4·ͰͬͯͶ
None
ʊਓਓਓਓਓਓਓਓਓʊ ʼɹࢼ͞ΕΔ৺ɹʻ ʉ:?:?:?:?:?:?:?:ʉ
Swift 2.3 • Xcode 8 + iOS 10 SDKͰϏϧυ͕Մೳ •
Swift 2.x ܥͷAPIσβΠϯ • ͱΓ͋͑ͣٸ͍ͰiOS 10ͰϏϧυ͢Δඞཁ ͕͋Δ߹
Swift 2.3 9DPEF3FMFBTF/PUFT • Xcode 8.2 ͕࠷ޙͷαϙʔτʹͳΔͨΊɺ Swift 3.0ͷରԠඞਢ
Migration to Swift 3.0
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Ҡߦͨ͠
Migration • Xcode 8.2Ͱىಈͨ͠ࡍɺաڈͷSwift όʔδϣ ϯͷ߹Convertը໘͕ىಈ͢Δ • ʮEdit > Convert
> To Current Swift Syntax.ʯͰ ࣮ߦՄೳ • Swift 1.2 → Swift 2.1ͷ͍࣌ͷʹͳΒͳ ͔ͬͨ
None
None
ʊਓਓਓਓਓਓਓਓਓʊ ʼɹ$POWFSU'BJMFEɹʻ ʉ:?:?:?:?:?:?:?:?:?ʉ
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!
ͦΕͰແ͍ΑΓϚγ • UIKitͷmethodͷม • Enumͷupper case → lower caseม •
NSPrefixͷϥΠϒϥϦͷม
ͻͨ͢Βಓͳ࡞ۀ • 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 "" }
ͻͨ͢Βಓͳ࡞ۀ • 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 "" } } }
ͻͨ͢Βಓͳ࡞ۀ • closureʹ@escapingͷՃ
ͻͨ͢Βಓͳ࡞ۀ • Ҡߦπʔϧ͕มͨ͠Օॴͷमਖ਼ • Ωϟετ → Ωϟετ → Ωϟετ Date
as NSDate as Date String as NSString as String
ͻͨ͢Βಓͳ࡞ۀ • Unit Testͷमਖ਼
Result
Result
files additions deletions Ver 2.1 147 1268 1130 Ver 3.0
247 4314 4372 Pull Request Diff
Battle with Swift version, second • Ͱ͖ΕೋͱΓͨ͘ͳ͍ • ίϯϑϦΫτղফͷͨΊɺݽಠͳ࡞ۀͱ ͳΔ
• ৺Λࢼ͞ΕΔ
Recap
Recap •৽نϓϩδΣΫτશͯSwiftʹ •ΞʔΩςΫνϟʹ͍ͭͯ૬ஊͰ͖Δ ͕ܗ͞Εͨ •ΞʔϦʔΞμϓλʔͱͯ͠ɺ͖᪴ͳ͕Β ϊϋΛͨΊ͍͚ͯΔ
Recap •Swiftͷݴޠ༷ͷมԽʹ൱Ԡͳ͠ʹରԠ ΛഭΒΕΔ •બͨ͠ΞʔΩςΫνϟʹΑͬͯҭ ίετ͕ൃੜ͢Δ •σϦόϦʔΛ༏ઌ͠ͳ͚ΕͳΒͳ͍ঢ় گඞͣൃੜ͢Δ
None
Thank you!
One more thing…
ʲ େࡕΦϑΟε։ઃ1प!! ʳ Ϋϥεϝιουͷ։ൃΛΔʂશ7ճษڧ http://dev.classmethod.jp/news/mobileteam-inosaka/
ʲ େࡕΦϑΟε։ઃ1प!! ʳ Ϋϥεϝιουͷ։ൃΛΔʂશ7ճษڧ http://dev.classmethod.jp/news/mobileteam-inosaka/
We're hiring!!
https://classmethod.jp/recruit/
AWSࣄۀ෦ AWSΤϯδχΞʢAWSγεςϜڥͷߏஙࢧԉʣ AWSιϦϡʔγϣϯΞʔΩςΫτʢAWSγεςϜڥ ίϯαϧɾߏஙɾӡ༻ࢧԉʣ AWSΦϖϨʔγϣϯίϯαϧλϯτʢAWSγεςϜڥͷӡ༻ࣗಈԽࢧԉʣ AWSαʔϏεσϕϩούʔʢAWSΛ׆༻ͨ͠αʔϏε։ൃʣ ϞόΠϧΞϓϦαʔϏε෦ iOS / AndroidΞϓϦ։ൃΤϯδχΞ
― ౦ژ / ࡳຈ / େࡕ ϞόΠϧόοΫΤϯυΤϯδχΞ ― ౦ژ / ࡳຈ / େࡕ DevOpsΤϯδχΞ ― ౦ژ / ࡳຈ / େࡕ ϓϩδΣΫτϚωʔδϟʔʢϞόΠϧΞϓϦʣ ― ౦ژ / େࡕ ݱࡏืूதͷ৬छ https://classmethod.jp/recruit/jobs/