Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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

rockname
August 30, 2018

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

rockname

August 30, 2018
Tweet

More Decks by rockname

Other Decks in Programming

Transcript

  1. iOSDC Japan 2018

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

    View full-size slide

  2. @rockname
    גࣜձࣾϛΫγΟ / ΈͯͶࣄۀ෦

    ΞϓϦ։ൃG 18৽ଔ
    iOS(Swift, objc), Android(Kotlin, Java), Rails(ruby)…

    View full-size slide

  3. UIͷ࣮૷Λ൐͏

    iOSΞϓϦ։ൃϑϩʔ

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  7. • ෳ਺ղ૾౓ͰͷϨΠΞ΢τ
    • ৚݅ʹΑͬͯมΘΔදࣔ಺༰
    • ϩʔΧϥΠζͷจݴ…

    View full-size slide

  8. Xcode Simulator

    /Device
    #VJME͕௨ΔͷΛ଴ͬͯ

    ϨΠΞ΢τΛ֬ೝ
    ϨΠΞ΢τΛௐ੔ͯ͠

    ࠶Ϗϧυ
    • ෳ਺ղ૾౓ͰͷϨΠΞ΢τ
    • ৚݅ʹΑͬͯมΘΔදࣔ಺༰
    • ϩʔΧϥΠζͷจݴ…

    View full-size slide

  9. UIͷௐ੔Λ΋ͬͱૣ͍αΠΫϧͰճ͍ͨ͠…

    View full-size slide

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

    View full-size slide

  11. Playgroundۦಈ։ൃͱ͸
    • ViewͷΈΛ୹࣌ؒͰϏϧυͯ͠ର৅ͷγʔϯΛ
    PlaygroundͰදࣔ͢Δ͜ͱͰσβΠϯௐ੔ͷϑ
    ϩʔΛૣ͘͢Δ։ൃख๏

    • Kickstarter͕ఏএ

    (https://github.com/kickstarter/ios-oss)

    View full-size slide

  12. Kickstarter͸͜Μͳײ͡

    View full-size slide

  13. Kickstarter͸͜Μͳײ͡

    View full-size slide

  14. Kickstarter͸͜Μͳײ͡

    View full-size slide

  15. ಋೖखॱ

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  18. 2. ࡞੒ͨ͠Frameworkʹ

    ViewΛ௥Ճ͍ͯ͘͠

    View full-size slide

  19. 3. (CarthageΛ࢖༻ͨ͠৔߹ͷΈ)

    ViewͷදࣔʹඞཁͳϥΠϒϥϦΛ௥Ճ

    View full-size slide

  20. 4. PlaygroundΛ

    ϓϩδΣΫτʹ௥Ճ

    View full-size slide

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

    View full-size slide

  22. 5. PlaygroundͰViewΛදࣔ

    View full-size slide

  23. 5. PlaygroundͰViewΛදࣔ

    View full-size slide

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

    View full-size slide

  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

    View full-size slide

  26. What’s new in Playground

    - WWDC 2018
    ҰʑίϝϯτΞ΢τ͢Δඞཁ͕ͳ͘
    ϑϩʔΛڞ௨Խ͠΍͘͢ͳͬͨ
    Alex Brown, Core OS Engineer

    Running Step by Step
    NEW

    View full-size slide

  27. ۩ମతʹͲΜͳखॱͰ
    σβΠϯௐ੔͢Δͷ

    View full-size slide

  28. DEMO
    IUUQTHJUIVCDPNSPDLOBNF1MBZHSPVOE%SJWFO%FWFMPQNFOU

    View full-size slide

  29. DEMOͷྲྀΕ
    • TwitterͷΑ͏ͳΞϓϦΛ࡞ͬͨʂ
    • σβΠϯ֬ೝ͢Δͧʂ
    ౤ߘ͕ ͳ͍/͋Δ ͱ͖ͷදࣔ͸ਖ਼͍͠ʁ
    ͪΌΜͱ ϩʔΧϥΠζ ͞ΕͯΔʁ
    খ͍͞, େ͖͍୺຤Ͱ ϨΠΞ΢τ ่Εͯͳ͍ʁ
    • मਖ਼ͯ͠ View͚ͩ ϏϧυͰ࠶֬ೝʂ

    View full-size slide

  30. ࣮૷આ໌

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  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ͳͲΛࢦఆ

    View full-size slide

  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

    View full-size slide

  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Λࢦఆ͢Δ

    View full-size slide

  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

    View full-size slide

  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ͷେ͖͞ΛมߋՄೳ

    View full-size slide

  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

    View full-size slide

  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Λࢦఆ

    View full-size slide

  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

    View full-size slide

  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ʜ4USJOH3FTPVSDF5ZQFMPDBMJ[FETXJGU

    View full-size slide

  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ʜ4USJOH3FTPVSDF5ZQFMPDBMJ[FETXJGU
    NSLocalizedStringͷҾ਺ʹ
    LanguageʹԠͨ͡BundleΛ౉͢Α͏ʹ͢Δ
    LanguageΛࢦఆ

    View full-size slide

  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

    View full-size slide

  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ʹදࣔ͢Δ౤ߘΛಡΈࠐΉ

    View full-size slide

  45. ViewΛදࣔ

    View full-size slide

  46. ViewΛදࣔ

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  51. Playgroundۦಈ։ൃͰ

    ര଎ʹ։ൃ͠Α͏

    View full-size slide