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
Playground駆動開発のすすめ / Playground driven developm...
Search
rockname
August 30, 2018
Programming
6.8k
10
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Playground駆動開発のすすめ / Playground driven development suggestion
rockname
August 30, 2018
More Decks by rockname
See All by rockname
AIを活用したレシート読み取り機能の開発から得られた実践知 / AI Receipt Scan Practice
rockname
2
4.8k
Unlock the Potential of Swift Code Generation
rockname
0
580
生成AIを活用したレシート読み取り機能のアプリ開発の裏側 / AI Receipt Scan App Development
rockname
0
150
ゼロから理解するDependency Injection / Understanding Dependency Injection from the Ground Up
rockname
2
4.5k
サブスクリプション機能制御の設計における勘所
rockname
0
1.3k
Anatomy of Dynamic color
rockname
1
1.3k
キャッシュによる状態管理のアーキテクチャ / Cache-based state management architecture
rockname
10
21k
Optimistic Updatesで UXを向上させる / Improve UX with Optimistic Updates
rockname
2
1.6k
モバイルアプリのリストUIにおける 理想的なState表示について / The ideal state display in a mobile app list UI
rockname
6
2.2k
Other Decks in Programming
See All in Programming
才能?センス?知らん、 続けたもん勝ちだ。-- 結婚・出産・癌を越えてなお、私がプロダクトを創り続ける理由
16bitidol
2
860
Haskell/Servantを通してWebミドルウェアを捉え直す
pizzacat83
1
580
SLOをサービス品質の共通言語にするために 取り組んできたこと
wakana0222
0
510
ローカルLLMでどこまでコードが書けるか -拡張版 / How much code can be written on a local LLM Extended
kishida
12
4.8k
初めてのKubernetes 本番運用でハマった話
oku053
0
130
Laravel Boostに学ぶ、AIにPHPを書かせる技術 〜OSSの実装から蒸留するエージェント制御の王道〜
kentaroutakeda
3
460
共通化で考えるべきは、実装より公開する型だった
codeegg
0
250
1年で人数1.5倍、PR数5.5倍増。 品質とアウトカムはどうなったか、 何が効いたか
ike002jp
0
140
『コードを書く以外の』エンジニアリング〜課金基盤移行プロジェクト推進のためのTips4選
yuriko1211
0
500
JAWS-UG横浜 #102 AWSサ終供養LT会 成仏できない AWS サービスたち 〜本日、三体供養します〜
maroon1st
0
210
エンジニアにデザインハーネスを 〜デザインプロセスを規定するためのハーネス〜 / Design harness from an engineer's perspective
rkaga
2
1.5k
PHPだって関数型したい 〜できること、できないこと〜 / fp-in-php
jsoizo
0
210
Featured
See All Featured
Thoughts on Productivity
jonyablonski
76
5.2k
The Pragmatic Product Professional
lauravandoore
37
7.4k
Dominate Local Search Results - an insider guide to GBP, reviews, and Local SEO
greggifford
PRO
0
210
How to Ace a Technical Interview
jacobian
281
24k
Tips & Tricks on How to Get Your First Job In Tech
honzajavorek
1
600
Have SEOs Ruined the Internet? - User Awareness of SEO in 2025
akashhashmi
0
400
The agentic SEO stack - context over prompts
schlessera
0
850
Effective software design: The role of men in debugging patriarchy in IT @ Voxxed Days AMS
baasie
0
450
A Soul's Torment
seathinner
6
3.1k
Prompt Engineering for Job Search
mfonobong
0
380
How to Talk to Developers About Accessibility
jct
2
400
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
659
62k
Transcript
iOSDC Japan 2018 2018/08/30 גࣜձࣾϛΫγΟ/ΈͯͶࣄۀ෦ ؠ໊༐ً @rockname Playgroundۦಈ։ൃ ͷ͢͢Ί
@rockname גࣜձࣾϛΫγΟ / ΈͯͶࣄۀ෦ ΞϓϦ։ൃG 18৽ଔ iOS(Swift, objc), Android(Kotlin, Java),
Rails(ruby)…
UIͷ࣮Λ͏ iOSΞϓϦ։ൃϑϩʔ
1 ϩδοΫΛΉ 2 StoryboardͰϨΠΞτ 3 ಈ࡞֬ೝ w ͦΕͧΕͷΞʔΩςΫνϟʹԠͯ͡ϩδοΫ͔ΒΜͰ͍͘ w $MFBO"SDIJUFDUVSFͳΒ%PNBJO͔Β
w ςετॻ͘ w ΞχϝʔγϣϯͳͲಈతͳཁૉҎ֎ఆٛͯ͠͠·͏ w ࣮ػ4JNVMBUPSͰҙਤͨ͠ڍಈΛ͢Δ͔֬ೝ
1 ϩδοΫΛΉ 2 StoryboardͰϨΠΞτ 3 ಈ࡞֬ೝ w ͦΕͧΕͷΞʔΩςΫνϟʹԠͯ͡ϩδοΫ͔ΒΜͰ͍͘ w $MFBO"SDIJUFDUVSFͳΒ%PNBJO͔Β
w ςετॻ͘ w ΞχϝʔγϣϯͳͲಈతͳཁૉҎ֎ఆٛͯ͠͠·͏ w ࣮ػ4JNVMBUPSͰҙਤͨ͠ڍಈΛ͢Δ͔֬ೝ 4 σβΠϯௐ
1 ϩδοΫΛΉ 2 StoryboardͰϨΠΞτ 3 ಈ࡞֬ೝ w ͦΕͧΕͷΞʔΩςΫνϟʹԠͯ͡ϩδοΫ͔ΒΜͰ͍͘ w $MFBO"SDIJUFDUVSFͳΒ%PNBJO͔Β
w ςετॻ͘ w ΞχϝʔγϣϯͳͲಈతͳཁૉҎ֎ఆٛͯ͠͠·͏ w ࣮ػ4JNVMBUPSͰҙਤͨ͠ڍಈΛ͢Δ͔֬ೝ 4 σβΠϯௐ ͕݁͜͜ߏਏ͍…
• ෳղ૾ͰͷϨΠΞτ • ݅ʹΑͬͯมΘΔදࣔ༰ • ϩʔΧϥΠζͷจݴ…
Xcode Simulator /Device #VJME͕௨ΔͷΛͬͯ ϨΠΞτΛ֬ೝ ϨΠΞτΛௐͯ͠ ࠶Ϗϧυ • ෳղ૾ͰͷϨΠΞτ •
݅ʹΑͬͯมΘΔදࣔ༰ • ϩʔΧϥΠζͷจݴ…
UIͷௐΛͬͱૣ͍αΠΫϧͰճ͍ͨ͠…
– Playground driven development “Playgroundۦಈ։ൃ”
Playgroundۦಈ։ൃͱ • ViewͷΈΛ࣌ؒͰϏϧυͯ͠ରͷγʔϯΛ PlaygroundͰදࣔ͢Δ͜ͱͰσβΠϯௐͷϑ ϩʔΛૣ͘͢Δ։ൃख๏ • Kickstarter͕ఏএ (https://github.com/kickstarter/ios-oss)
Kickstarter͜Μͳײ͡
Kickstarter͜Μͳײ͡
Kickstarter͜Μͳײ͡
ಋೖखॱ
1. Cocoa Touch frameworkΛ λʔήοτʹՃ
1. Cocoa Touch frameworkΛ λʔήοτʹՃ
2. ࡞ͨ͠Frameworkʹ ViewΛՃ͍ͯ͘͠
3. (CarthageΛ༻ͨ͠߹ͷΈ) ViewͷදࣔʹඞཁͳϥΠϒϥϦΛՃ
4. PlaygroundΛ ϓϩδΣΫτʹՃ
5. PlaygroundͰViewΛදࣔ let vc = ViewController() PlaygroundPage.current.liveView = vc
5. PlaygroundͰViewΛදࣔ
5. PlaygroundͰViewΛදࣔ
͞ΒʹPlaygroundʹ৽ػೳ͕…
What’s new in Playground - WWDC 2018 Xcode10͔ΒPlaygroundͷஞ࣮࣍ߦ͕Մೳʹ…!! (https://developer.apple.com/videos/play/ wwdc2018/402/)
Alex Brown, Core OS Engineer • Running Step by Step NEW
What’s new in Playground - WWDC 2018 ҰʑίϝϯτΞτ͢Δඞཁ͕ͳ͘ ϑϩʔΛڞ௨Խ͘͢͠ͳͬͨ Alex
Brown, Core OS Engineer • Running Step by Step NEW
۩ମతʹͲΜͳखॱͰ σβΠϯௐ͢Δͷ
DEMO IUUQTHJUIVCDPNSPDLOBNF1MBZHSPVOE%SJWFO%FWFMPQNFOU
DEMOͷྲྀΕ • TwitterͷΑ͏ͳΞϓϦΛ࡞ͬͨʂ • σβΠϯ֬ೝ͢Δͧʂ ߘ͕ ͳ͍/͋Δ ͱ͖ͷදࣔਖ਼͍͠ʁ ͪΌΜͱ ϩʔΧϥΠζ
͞ΕͯΔʁ খ͍͞, େ͖͍Ͱ ϨΠΞτ ่Εͯͳ͍ʁ • मਖ਼ͯ͠ View͚ͩ ϏϧυͰ࠶֬ೝʂ
࣮આ໌
func display(device: Device, orientation: Orientation, language: Language) { let vc
= R.storyboard.twitter.instantiateInitialViewController()! let (parent, _) = playgroundControllers(device: device, orientation: .portrait, child: vc) AppEnvironment.language = language PlaygroundPage.current.liveView = parent vc.load(statuses) } 1SPKFDUQMBZHSPVOE5XJUUFSYDQMBZHSPVOEQBHF
func display(device: Device, orientation: Orientation, language: Language) { let vc
= R.storyboard.twitter.instantiateInitialViewController()! let (parent, _) = playgroundControllers(device: device, orientation: .portrait, child: vc) AppEnvironment.language = language PlaygroundPage.current.liveView = parent vc.load(statuses) } 1SPKFDUQMBZHSPVOE5XJUUFSYDQMBZHSPVOEQBHF
1SPKFDUQMBZHSPVOE5XJUUFSYDQMBZHSPVOEQBHF func display(device: Device, orientation: Orientation, language: Language) { let
vc = R.storyboard.twitter.instantiateInitialViewController()! let (parent, _) = playgroundControllers(device: device, orientation: .portrait, child: vc) AppEnvironment.language = language PlaygroundPage.current.liveView = parent vc.load(statuses) } simulatorͷsizeͳͲΛࢦఆ
public func playgroundControllers(device: Device = .phone4_7inch, orientation: Orientation, child: UIViewController,
additionalTraits: UITraitCollection) -> (parent: UIViewController, child: UIViewController) { let parent = UIViewController() parent.addChild(child) parent.view.addSubview(child.view) child.view.autoresizingMask = [.flexibleWidth, .flexibleHeight] let traits: UITraitCollection switch (device, orientation) { case (.phone3_5inch, .portrait): parent.view.frame = .init(x: 0, y: 0, width: 320, height: 480) traits = .init(traitsFrom: [ .init(horizontalSizeClass: .compact), .init(verticalSizeClass: .regular), .init(userInterfaceIdiom: .phone) ]) ɾ ɾ ɾ simulatorͷsizeͳͲΛࢦఆ 1SPKFDUQMBZHSPVOE4PVSDFTEFWJDFTXJGU
public func playgroundControllers(device: Device = .phone4_7inch, orientation: Orientation, child: UIViewController,
additionalTraits: UITraitCollection) -> (parent: UIViewController, child: UIViewController) { let parent = UIViewController() parent.addChild(child) parent.view.addSubview(child.view) child.view.autoresizingMask = [.flexibleWidth, .flexibleHeight] let traits: UITraitCollection switch (device, orientation) { case (.phone3_5inch, .portrait): parent.view.frame = .init(x: 0, y: 0, width: 320, height: 480) traits = .init(traitsFrom: [ .init(horizontalSizeClass: .compact), .init(verticalSizeClass: .regular), .init(userInterfaceIdiom: .phone) ]) 1SPKFDUQMBZHSPVOE4PVSDFTEFWJDFTXJGU ɾ ɾ ɾ simulatorͷsizeͳͲΛࢦఆ Device, OrientationʹԠͯ͡ sizeΛࢦఆ͢Δ
ɾ ɾ ɾ child.view.frame = parent.view.frame parent.preferredContentSize = parent.view.frame.size parent.view.backgroundColor
= .white child.view.backgroundColor = .white let allTraits = UITraitCollection.init(traitsFrom: [traits, additionalTraits]) parent.setOverrideTraitCollection(allTraits, forChild: child) return (parent, child) } simulatorͷsizeͳͲΛࢦఆ 1SPKFDUQMBZHSPVOE4PVSDFTEFWJDFTXJGU
ɾ ɾ ɾ child.view.frame = parent.view.frame parent.preferredContentSize = parent.view.frame.size parent.view.backgroundColor
= .white child.view.backgroundColor = .white let allTraits = UITraitCollection.init(traitsFrom: [traits, additionalTraits]) parent.setOverrideTraitCollection(allTraits, forChild: child) return (parent, child) } simulatorͷsizeͳͲΛࢦఆ 1SPKFDUQMBZHSPVOE4PVSDFTEFWJDFTXJGU preferredContentSizeΛࢦఆ͢Δ͜ͱͰ Playground্Ͱදࣔ͢ΔViewͷେ͖͞ΛมߋՄೳ
func display(device: Device, orientation: Orientation, language: Language) { let vc
= R.storyboard.twitter.instantiateInitialViewController()! let (parent, _) = playgroundControllers(device: device, orientation: .portrait, child: vc) AppEnvironment.language = language PlaygroundPage.current.liveView = parent vc.load(statuses) } 1SPKFDUQMBZHSPVOE5XJUUFSYDQMBZHSPVOEQBHF
func display(device: Device, orientation: Orientation, language: Language) { let vc
= R.storyboard.twitter.instantiateInitialViewController()! let (parent, _) = playgroundControllers(device: device, orientation: .portrait, child: vc) AppEnvironment.language = language PlaygroundPage.current.liveView = parent vc.load(statuses) } 1SPKFDUQMBZHSPVOE5XJUUFSYDQMBZHSPVOEQBHF LanguageΛࢦఆ
public struct AppEnvironment { public static var language: Language =
.ja public static var currentUser: String? = nil public var isLoggedIn: Bool { return AppEnvironment.currentUser != nil } } GlobalʹΞϓϦͷڥΛ͍࣋ͨͤͯΔ LanguageΛࢦఆ %PNBJO"QQ&OWJSPONFOUTXJGU
extension StringResourceType { func localized(language: Language = AppEnvironment.language) -> String
{ return NSLocalizedString(key, bundle: Bundle(path: stringsBundle.path(forResource: language.rawValue, ofType: "lproj") ?? "") ?? stringsBundle, comment: "") } } private class Pin {} public let stringsBundle = Bundle(for: Pin.self) LanguageΛࢦఆ 1SFTFOUBUJPOʜ4USJOH3FTPVSDF5ZQF MPDBMJ[FETXJGU
extension StringResourceType { func localized(language: Language = AppEnvironment.language) -> String
{ return NSLocalizedString(key, bundle: Bundle(path: stringsBundle.path(forResource: language.rawValue, ofType: "lproj") ?? "") ?? stringsBundle, comment: "") } } private class Pin {} public let stringsBundle = Bundle(for: Pin.self) 1SFTFOUBUJPOʜ4USJOH3FTPVSDF5ZQF MPDBMJ[FETXJGU NSLocalizedStringͷҾʹ LanguageʹԠͨ͡BundleΛ͢Α͏ʹ͢Δ LanguageΛࢦఆ
func display(device: Device, orientation: Orientation, language: Language) { let vc
= R.storyboard.twitter.instantiateInitialViewController()! let (parent, _) = playgroundControllers(device: device, orientation: .portrait, child: vc) AppEnvironment.language = language PlaygroundPage.current.liveView = parent vc.load(statuses) } 1SPKFDUQMBZHSPVOE5XJUUFSYDQMBZHSPVOEQBHF
func display(device: Device, orientation: Orientation, language: Language) { let vc
= R.storyboard.twitter.instantiateInitialViewController()! let (parent, _) = playgroundControllers(device: device, orientation: .portrait, child: vc) AppEnvironment.language = language PlaygroundPage.current.liveView = parent vc.load(statuses) } 1SPKFDUQMBZHSPVOE5XJUUFSYDQMBZHSPVOEQBHF Playground্ͰViewΛදࣔͯ͠ Cellʹදࣔ͢ΔߘΛಡΈࠐΉ
ViewΛදࣔ
ViewΛදࣔ
Α͠ɺΈͯͶͰಋೖʂ
Α͠ɺΈͯͶͰಋೖʂ
ಋೖ·ͰͷಓͷΓ Viewʹදࣔ͢ΔͷΛϞοΫͰ͖ΔΑ͏ʹઃܭ ଟݴޠରԠΛ͍ͯ͠ΔͷͰɺNSLocalizedStringͷ ॳظԽ࣌ʹBundleͷpathΛ͢ Embedded Frameworkͷಋೖ PlaygroundͷPageಋೖϑϩʔڞ௨Խɾڞ༗
৽نϓϩδΣΫτͳΒ ׂͱαΫοͱಋೖͰ͖ͦ͏
Playgroundۦಈ։ൃͰ രʹ։ൃ͠Α͏