Playground駆動開発のすすめ / Playground driven development suggestion

070d33664df274636dad3da21c9b21fc?s=47 rockname
August 30, 2018

Playground駆動開発のすすめ / Playground driven development suggestion

070d33664df274636dad3da21c9b21fc?s=128

rockname

August 30, 2018
Tweet

Transcript

  1. iOSDC Japan 2018
 2018/08/30 גࣜձࣾϛΫγΟ/ΈͯͶࣄۀ෦ ؠ໊༐ً @rockname Playgroundۦಈ։ൃ ͷ͢͢Ί

  2. @rockname גࣜձࣾϛΫγΟ / ΈͯͶࣄۀ෦
 ΞϓϦ։ൃG 18৽ଔ iOS(Swift, objc), Android(Kotlin, Java),

    Rails(ruby)…
  3. UIͷ࣮૷Λ൐͏
 iOSΞϓϦ։ൃϑϩʔ

  4. 1 ϩδοΫΛ૊Ή 2 StoryboardͰϨΠΞ΢τ 3 ಈ࡞֬ೝ w ͦΕͧΕͷΞʔΩςΫνϟʹԠͯ͡ϩδοΫ͔Β૊ΜͰ͍͘ w $MFBO"SDIJUFDUVSFͳΒ%PNBJO͔Β

    w ςετॻ͘ w ΞχϝʔγϣϯͳͲಈతͳཁૉҎ֎͸ఆٛͯ͠͠·͏ w ࣮ػ΍4JNVMBUPSͰҙਤͨ͠ڍಈΛ͢Δ͔֬ೝ
  5. 1 ϩδοΫΛ૊Ή 2 StoryboardͰϨΠΞ΢τ 3 ಈ࡞֬ೝ w ͦΕͧΕͷΞʔΩςΫνϟʹԠͯ͡ϩδοΫ͔Β૊ΜͰ͍͘ w $MFBO"SDIJUFDUVSFͳΒ%PNBJO͔Β

    w ςετॻ͘ w ΞχϝʔγϣϯͳͲಈతͳཁૉҎ֎͸ఆٛͯ͠͠·͏ w ࣮ػ΍4JNVMBUPSͰҙਤͨ͠ڍಈΛ͢Δ͔֬ೝ 4 σβΠϯௐ੔
  6. 1 ϩδοΫΛ૊Ή 2 StoryboardͰϨΠΞ΢τ 3 ಈ࡞֬ೝ w ͦΕͧΕͷΞʔΩςΫνϟʹԠͯ͡ϩδοΫ͔Β૊ΜͰ͍͘ w $MFBO"SDIJUFDUVSFͳΒ%PNBJO͔Β

    w ςετॻ͘ w ΞχϝʔγϣϯͳͲಈతͳཁૉҎ֎͸ఆٛͯ͠͠·͏ w ࣮ػ΍4JNVMBUPSͰҙਤͨ͠ڍಈΛ͢Δ͔֬ೝ 4 σβΠϯௐ੔ ͕݁͜͜ߏਏ͍…
  7. • ෳ਺ղ૾౓ͰͷϨΠΞ΢τ • ৚݅ʹΑͬͯมΘΔදࣔ಺༰ • ϩʔΧϥΠζͷจݴ…

  8. Xcode Simulator
 /Device #VJME͕௨ΔͷΛ଴ͬͯ
 ϨΠΞ΢τΛ֬ೝ ϨΠΞ΢τΛௐ੔ͯ͠
 ࠶Ϗϧυ • ෳ਺ղ૾౓ͰͷϨΠΞ΢τ •

    ৚݅ʹΑͬͯมΘΔදࣔ಺༰ • ϩʔΧϥΠζͷจݴ…
  9. UIͷௐ੔Λ΋ͬͱૣ͍αΠΫϧͰճ͍ͨ͠…

  10. – Playground driven development “Playgroundۦಈ։ൃ”

  11. Playgroundۦಈ։ൃͱ͸ • ViewͷΈΛ୹࣌ؒͰϏϧυͯ͠ର৅ͷγʔϯΛ PlaygroundͰදࣔ͢Δ͜ͱͰσβΠϯௐ੔ͷϑ ϩʔΛૣ͘͢Δ։ൃख๏
 • Kickstarter͕ఏএ
 (https://github.com/kickstarter/ios-oss)

  12. Kickstarter͸͜Μͳײ͡

  13. Kickstarter͸͜Μͳײ͡

  14. Kickstarter͸͜Μͳײ͡

  15. ಋೖखॱ

  16. 1. Cocoa Touch frameworkΛ λʔήοτʹ௥Ճ

  17. 1. Cocoa Touch frameworkΛ λʔήοτʹ௥Ճ

  18. 2. ࡞੒ͨ͠Frameworkʹ
 ViewΛ௥Ճ͍ͯ͘͠

  19. 3. (CarthageΛ࢖༻ͨ͠৔߹ͷΈ)
 ViewͷදࣔʹඞཁͳϥΠϒϥϦΛ௥Ճ

  20. 4. PlaygroundΛ
 ϓϩδΣΫτʹ௥Ճ

  21. 5. PlaygroundͰViewΛදࣔ let vc = ViewController() PlaygroundPage.current.liveView = vc

  22. 5. PlaygroundͰViewΛදࣔ

  23. 5. PlaygroundͰViewΛදࣔ

  24. ͞ΒʹPlaygroundʹ৽ػೳ͕…

  25. 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
  26. What’s new in Playground
 - WWDC 2018 ҰʑίϝϯτΞ΢τ͢Δඞཁ͕ͳ͘ ϑϩʔΛڞ௨Խ͠΍͘͢ͳͬͨ Alex

    Brown, Core OS Engineer • Running Step by Step NEW
  27. ۩ମతʹͲΜͳखॱͰ σβΠϯௐ੔͢Δͷ

  28. DEMO IUUQTHJUIVCDPNSPDLOBNF1MBZHSPVOE%SJWFO%FWFMPQNFOU

  29. DEMOͷྲྀΕ • TwitterͷΑ͏ͳΞϓϦΛ࡞ͬͨʂ • σβΠϯ֬ೝ͢Δͧʂ ౤ߘ͕ ͳ͍/͋Δ ͱ͖ͷදࣔ͸ਖ਼͍͠ʁ ͪΌΜͱ ϩʔΧϥΠζ

    ͞ΕͯΔʁ খ͍͞, େ͖͍୺຤Ͱ ϨΠΞ΢τ ่Εͯͳ͍ʁ • मਖ਼ͯ͠ View͚ͩ ϏϧυͰ࠶֬ೝʂ
  30. ࣮૷આ໌

  31. 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
  32. 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
  33. 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ͳͲΛࢦఆ
  34. 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
  35. 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Λࢦఆ͢Δ
  36. ɾ
 ɾ
 ɾ 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
  37. ɾ
 ɾ
 ɾ 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ͷେ͖͞ΛมߋՄೳ
  38. 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
  39. 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Λࢦఆ
  40. 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
  41. 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
  42. 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Λࢦఆ
  43. 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
  44. 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ʹදࣔ͢Δ౤ߘΛಡΈࠐΉ
  45.  ViewΛදࣔ

  46.  ViewΛදࣔ

  47. Α͠ɺΈͯͶͰ΋ಋೖʂ

  48. Α͠ɺΈͯͶͰ΋ಋೖʂ

  49. ಋೖ·ͰͷಓͷΓ Viewʹදࣔ͢Δ΋ͷΛϞοΫͰ͖ΔΑ͏ʹઃܭ ଟݴޠରԠΛ͍ͯ͠ΔͷͰɺNSLocalizedStringͷ ॳظԽ࣌ʹBundleͷpathΛ౉͢ Embedded Frameworkͷಋೖ PlaygroundͷPageಋೖϑϩʔڞ௨Խɾڞ༗

  50. ৽نϓϩδΣΫτͳΒ ׂͱαΫοͱಋೖͰ͖ͦ͏

  51. Playgroundۦಈ։ൃͰ
 ര଎ʹ։ൃ͠Α͏