$30 off During Our Annual Pro Sale. View Details »

Xcode Previews でUIKitベースのアプリ開発を効率化する - iOSDC Japan 2020

kenmaz
September 21, 2020
12k

Xcode Previews でUIKitベースのアプリ開発を効率化する - iOSDC Japan 2020

iOSDC Japan 2020 で発表した内容です。
https://fortee.jp/iosdc-japan-2020/proposal/a88be712-b87a-4d87-bc6d-2579c2ce9b35

動画はこちら
https://www.youtube.com/watch?v=NnqGmeR0uqE

発表者ノート付きPDFは以下からダウンロードできます。
https://drive.google.com/file/d/1GSLyYTSxxW5Q-9C7JFUlYBRvbNdTmUml/view?usp=sharing

kenmaz

September 21, 2020
Tweet

More Decks by kenmaz

Transcript

  1. LFONB[
    !NFSQBZ
    9DPEF1SFWJFXTͰ6*,JUϕʔε
    ͷΞϓϦ։ൃΛޮ཰Խ͢Δ
    J04%$+"1"/

    JPTED

    View Slide

  2. View Slide

  3. 9DPEF1SFWJFXTͱ͸

    View Slide

  4. 9DPEF1SFWJFXT

    View Slide

  5. 9DPEF1SFWJFXT
    4XJGU6*ͷ
    7JFXίʔυ

    View Slide

  6. 9DPEF1SFWJFXT
    4XJGU6*ͷ
    7JFXίʔυ
    1SFWJFXίʔυ

    View Slide

  7. 9DPEF1SFWJFXT
    $BOWBT
    4XJGU6*ͷ
    7JFXίʔυ
    1SFWJFXίʔυ

    View Slide

  8. 4XJGU6*ʹΑΔ։ൃϑϩʔ

    View Slide

  9. 4XJGU6*ʹΑΔ։ൃϑϩʔ

    View Slide

  10. 4XJGU6*ʹΑΔ։ൃϑϩʔ

    View Slide

  11. 4XJGU6*ʹΑΔ։ൃϑϩʔ

    View Slide

  12. 6*,JUϕʔεͷΞϓϦ։ൃϑϩʔ
    Start Developing iOS Apps (Swift)
    https://developer.apple.com/library/archive/referencelibrary/GettingStarted/DevelopiOSAppsSwift/BuildABasicUI.html#//apple_ref/doc/uid/TP40015214-CH5-SW1

    View Slide

  13. 6*,JUϕʔεͷΞϓϦ։ൃϑϩʔ
    TUPSZCPBSEYJC
    Start Developing iOS Apps (Swift)
    https://developer.apple.com/library/archive/referencelibrary/GettingStarted/DevelopiOSAppsSwift/BuildABasicUI.html#//apple_ref/doc/uid/TP40015214-CH5-SW1

    View Slide

  14. 6*,JUϕʔεͷΞϓϦ։ൃϑϩʔ
    TUPSZCPBSEYJC 6*7JFX
    6*7JFX$POUSPMMFS
    Start Developing iOS Apps (Swift)
    https://developer.apple.com/library/archive/referencelibrary/GettingStarted/DevelopiOSAppsSwift/BuildABasicUI.html#//apple_ref/doc/uid/TP40015214-CH5-SW1

    View Slide

  15. 6*,JUϕʔεͷΞϓϦ։ൃϑϩʔ
    4JNVMBUPSىಈ
    TUPSZCPBSEYJC 6*7JFX
    6*7JFX$POUSPMMFS
    Start Developing iOS Apps (Swift)
    https://developer.apple.com/library/archive/referencelibrary/GettingStarted/DevelopiOSAppsSwift/BuildABasicUI.html#//apple_ref/doc/uid/TP40015214-CH5-SW1

    View Slide

  16. 6*,JUϕʔεͷΞϓϦ։ൃϑϩʔ
    4JNVMBUPSىಈ
    ίʔυमਖ਼
    TUPSZCPBSEYJC 6*7JFX
    6*7JFX$POUSPMMFS
    Start Developing iOS Apps (Swift)
    https://developer.apple.com/library/archive/referencelibrary/GettingStarted/DevelopiOSAppsSwift/BuildABasicUI.html#//apple_ref/doc/uid/TP40015214-CH5-SW1

    View Slide

  17. 6*,JUϕʔεͷΞϓϦ։ൃϑϩʔ
    4JNVMBUPSىಈ
    ίʔυमਖ਼
    TUPSZCPBSEYJC 6*7JFX
    6*7JFX$POUSPMMFS
    Start Developing iOS Apps (Swift)
    https://developer.apple.com/library/archive/referencelibrary/GettingStarted/DevelopiOSAppsSwift/BuildABasicUI.html#//apple_ref/doc/uid/TP40015214-CH5-SW1

    View Slide

  18. 6*,JUϕʔεͷΞϓϦ։ൃϑϩʔ
    4JNVMBUPSىಈ
    ίʔυमਖ਼
    TUPSZCPBSEYJC 6*7JFX
    6*7JFX$POUSPMMFS
    Start Developing iOS Apps (Swift)
    https://developer.apple.com/library/archive/referencelibrary/GettingStarted/DevelopiOSAppsSwift/BuildABasicUI.html#//apple_ref/doc/uid/TP40015214-CH5-SW1

    View Slide

  19. 6*,JUϕʔεͷΞϓϦ։ൃϑϩʔ
    4JNVMBUPSىಈ
    ίʔυमਖ਼
    TUPSZCPBSEYJC 6*7JFX
    6*7JFX$POUSPMMFS
    Start Developing iOS Apps (Swift)
    https://developer.apple.com/library/archive/referencelibrary/GettingStarted/DevelopiOSAppsSwift/BuildABasicUI.html#//apple_ref/doc/uid/TP40015214-CH5-SW1

    View Slide

  20. 6*,JUϕʔεͷΞϓϦ։ൃϑϩʔ
    4JNVMBUPSىಈ
    ίʔυमਖ਼
    TUPSZCPBSEYJC 6*7JFX
    6*7JFX$POUSPMMFS
    Start Developing iOS Apps (Swift)
    https://developer.apple.com/library/archive/referencelibrary/GettingStarted/DevelopiOSAppsSwift/BuildABasicUI.html#//apple_ref/doc/uid/TP40015214-CH5-SW1

    ɾɾ

    View Slide

  21. 6*,JUWT4XJGU6*։ൃϑϩʔͷൺֱ
    w 4XJGU6*͸ɺ9DPEF1SFWJFXTΛ࢖͏͜ͱͰޮ཰Α͘Ϗϡʔͷ։ൃ͕ߦ͑Δ
    w ͔͠͠ݱঢ়ଟ͘ͷΞϓϦ͕·ͩ6*,JUϕʔε
    w 4XJGU6*΁ͷҠߦΛߦ͏ʹ͸J04ະຬͷαϙʔτΛ੾Δඞཁ͕͋Δ
    w 6*,JUϕʔεͷΞϓϦ։ൃΛ4XJGU6*ͷΑ͏ʹޮ཰ԽͰ͖ͳ͍͔ɾɾɾ

    View Slide

  22. 6*,JUWT4XJGU6*։ൃϑϩʔͷൺֱ
    w 4XJGU6*͸ɺ9DPEF1SFWJFXTΛ࢖͏͜ͱͰޮ཰Α͘Ϗϡʔͷ։ൃ͕ߦ͑Δ
    w ͔͠͠ݱঢ়ଟ͘ͷΞϓϦ͕·ͩ6*,JUϕʔε
    w 4XJGU6*΁ͷҠߦΛߦ͏ʹ͸J04ະຬͷαϙʔτΛ੾Δඞཁ͕͋Δ
    w 6*,JUϕʔεͷΞϓϦ։ൃΛ4XJGU6*ͷΑ͏ʹޮ཰ԽͰ͖ͳ͍͔ɾɾɾ
    ˠ6*,JUϕʔεͷΞϓϦ։ൃϑϩʔʹ9DPEF1SFWJFXTΛ
    ૊ΈࠐΉ

    View Slide

  23. 6*,JUϕʔεͷΞϓϦ։ൃϑϩʔ9DPEF1SFWJFXT
    TUPSZCPBSEYJC 6*7JFX6*7JFX$POUSPMMFS

    View Slide

  24. 6*,JUϕʔεͷΞϓϦ։ൃϑϩʔ9DPEF1SFWJFXT
    TUPSZCPBSEYJC 6*7JFX6*7JFX$POUSPMMFS 1SFWJFX

    View Slide

  25. 1SFWJFXίʔυͷॻ͖ํ

    View Slide

  26. 6*7JFX3FQSFTFOUBCMF
    6*7JFX$POUSPMMFS3FQSFTFOUBCMF
    public protocol UIViewControllerRepresentable : View
    associatedtype UIViewControllerType : UIViewController
    func makeUIViewController(context: Self.Context) -> Self.UIViewControllerType
    public protocol UIViewRepresentable : View {
    associatedtype UIViewType : UIView
    func makeUIView(context: Self.Context) -> Self.UIViewType
    w 6*7JFX6*7JFX$POUSPMMFSΛ4XJGU6*ͷ7JFXͱͯ͠ѻ͑Δ

    View Slide

  27. 1SFWJFX1SPWJEFS
    public protocol PreviewProvider {
    associatedtype Previews : View
    static var previews: Self.Previews { get }
    w 9DPEFʹϓϨϏϡʔΛදࣔͤ͞ΔͨΊͷಛघͳϓϩτίϧ
    w 9DPEFͰ1SFWJFX1SPWJEFSͷίʔυΛ։͘ͱɺ9DPEF͕ͦΕΛݕ஌ɺ
    QSFWJFXTͰࢦఆͨ͠7JFXΛ$BOWBTͰϓϨϏϡʔදࣔ

    View Slide

  28. class HelloView: UIView {
    private lazy var button: UIButton = ...
    ྫɿ7JFXͷ࣮૷

    View Slide

  29. class HelloView: UIView {
    private lazy var button: UIButton = ...
    ྫɿ7JFXͷ࣮૷
    struct Input {
    let backgroundColor: UIColor
    let buttonTitle: String
    let isButtonEnabled: Bool
    }
    func apply(input: Input) {
    backgroundColor = input.backgroundColor
    button.setTitle(input.buttonTitle)
    button.isEnabled = input.isButtonEnabled
    }
    }

    View Slide

  30. class HelloView: UIView {
    private lazy var button: UIButton = ...
    ྫɿ7JFXͷ࣮૷
    struct Input {
    let backgroundColor: UIColor
    let buttonTitle: String
    let isButtonEnabled: Bool
    }
    func apply(input: Input) {
    backgroundColor = input.backgroundColor
    button.setTitle(input.buttonTitle)
    button.isEnabled = input.isButtonEnabled
    }
    }
    IUUQTEFWFMPQFSBQQMFDPNWJEFPTQMBZXXED
    4USVDUVSFZPVSBQQGPS4XJGU6*QSFWJFXT
    1SFWJFXBCMFͳ7JFX
    1SFWJFX
    7JFX
    7JFX.PEFM
    "QQ
    7JFXͷঢ়ଶΛ஫ೖ
    1SFWJFX࣌
    ΞϓϦέʔγϣϯ࣮ߦ࣌

    View Slide

  31. final class HelloViewRepresentable: UIViewRepresentable {
    let input: HelloView.Input
    init(input: HelloView.Input) {
    self.input = input
    }
    func makeUIView(context: Context) -> HelloView {
    let view = HelloView()
    view.apply(input: input)
    return view
    }
    ...
    }
    ྫɿ6*7JFX3FQSFTFOUBCMFͷ࣮૷

    View Slide

  32. ྫɿ1SFWJFX1SPWJEFSͷ࣮૷
    struct HelloView_Preview: PreviewProvider {
    static var previews: some View {
    Group {
    HelloViewRepresentable(input: .init(
    backgroundColor: .white,
    buttonTitle: "Click Me",
    isButtonEnabled: true))
    HelloViewRepresentable(input: .init(
    backgroundColor: .yellow,
    buttonTitle: "Warning",
    isButtonEnabled: true))
    HelloViewRepresentable(input: .init(
    backgroundColor: .lightGray,
    buttonTitle: "Disabled",
    isButtonEnabled: false))
    }
    }
    }

    View Slide

  33. &EJUPS$BOWBT
    ΋͘͠͸
    $NE0QUJPO&OUFS
    1SFWJFX$BOWBTͷදࣔ

    View Slide

  34. &EJUPS$BOWBT
    ΋͘͠͸
    $NE0QUJPO&OUFS
    1SFWJFX$BOWBTͷදࣔ

    View Slide

  35. ϝϧϖΠͰͷ׆༻ྫ

    View Slide

  36. View Slide

  37. View Slide

  38. View Slide

  39. View Slide

  40. View Slide

  41. View Slide

  42. View Slide

  43. View Slide

  44. View Slide

  45. View Slide

  46. View Slide

  47. View Slide

  48. View Slide

  49. View Slide

  50. ͦͷଞͷ׆༻ํ๏
    w ϓϨϏϡʔͷը૾ΛΩϟϓνϟͯ͠ϓϧϦΫΤετͷઆ໌จʹషΔ
    w ը໘ͷ࢓༷Λ೺Ѳ͢ΔͨΊʹ1SFWJFXΛ࢖͏
    w 1SFWJFXʹ࢖ͬͨ7JFXΛ4OBQTIPU5FTUʹྲྀ༻͢Δʢܭըதʣ

    View Slide

  51. ͦͷଞͷ׆༻ํ๏
    w ϓϨϏϡʔͷը૾ΛΩϟϓνϟͯ͠ϓϧϦΫΤετͷઆ໌จʹషΔ
    w ը໘ͷ࢓༷Λ೺Ѳ͢ΔͨΊʹ1SFWJFXΛ࢖͏
    w 1SFWJFXʹ࢖ͬͨ7JFXΛ4OBQTIPU5FTUʹྲྀ༻͢Δʢܭըதʣ

    View Slide

  52. طଘͷϓϩδΣΫτʹ1SFWJFXΛ௥Ճ͢Δ

    View Slide

  53. ؀ڥ
    w 9DPEFҎ߱
    w NBD04$BUBMJOBҎ߱

    View Slide

  54. 1SFWJFXίʔυͷ഑ஔઌλʔήοτ
    λʔήοτͷछผ 1SFWJFXͷදࣔ 1SFWJFXͷσόοά
    "QQMJDBUJPO ✅ ✅
    'SBNFXPSL ✅ ❌
    4UBUJD-JCSBSZ ❌ ❌
    1SFWJFX༻ͷ"QQMJDBUJPO5BSHFUΛ࡞੒ͯ͠1SFWJFXίʔυΛ௥Ճ

    View Slide

  55. J04ະຬͷαϙʔτ
    w 1SFWJFXΛ࢖༻͢Δʹ͸4XJGU6*ͷΠϯϙʔτ͕ඞཁ
    w J04ະຬͷ؀ڥͰ͸4XJGU6*͕Πϯϙʔτ͞Εͳ͍Α͏ʹ͢Δඞཁ͕͋Δ
    w ରԠ
    ϚΫϩΛ࢖ͬͯ1SFWJFXίʔυΛϏϧυ͔Βআ֎͢Δ
    w ରԠ
    1SFWJFXઐ༻ͷλʔήοτΛ௥Ճ͢Δ

    View Slide

  56. + #if DEBUG && canImport(SwiftUI)
    import SwiftUI
    class HelloViewRepresentable: UIViewRepresentable {
    ...
    }
    + @available(iOS 13, *)
    struct HelloView_Preview: PreviewProvider {
    ...
    }
    + #endif
    J043FMFBTF/PUFT4XJGU6*,OPXO*TTVF

    ˞ʣ9DPEFͷόά
    w 9DPEF࢖༻࣌ͷΈ
    0UIFS-JOLFS'MBHʹXFBL@GSBNFXPSL4XJGU6*Λ௥Ճ
    J04ະຬͷ؀ڥͰ͸
    w 4XJGU6*ϞδϡʔϧͷΠϯϙʔτ
    w 1SFWJFXίʔυͷϩʔυ
    ͕εΩοϓ͞ΕΔ
    J04ະຬͷαϙʔτ
    ରԠ
    ϚΫϩΛ࢖ͬͯ1SFWJFXίʔυΛϏϧυ͔Βআ֎͢Δ

    View Slide

  57. J04ະຬͷαϙʔτ
    ରԠ
    1SFWJFXઐ༻ͷλʔήοτΛ௥Ճ͢Δ

    View Slide

  58. J04ະຬͷαϙʔτ
    ରԠ
    1SFWJFXઐ༻ͷλʔήοτΛ௥Ճ͢Δ
    1SFWJFX༻ͷλʔήοτΛผ్࡞੒ %FQMPZNFOU5BSHFUJ04Y

    View Slide

  59. J04ະຬͷαϙʔτ
    ରԠ
    1SFWJFXઐ༻ͷλʔήοτΛ௥Ճ͢Δ
    1SFWJFX༻ͷλʔήοτΛผ్࡞੒ %FQMPZNFOU5BSHFUJ04Y

    1SFWJFX༻ͷλʔήοτʹ1SFWJFXίʔυΛ௥Ճ

    View Slide

  60. J04ະຬͷαϙʔτ
    ରԠ
    1SFWJFXઐ༻ͷλʔήοτΛ௥Ճ͢Δ
    1SFWJFX༻ͷλʔήοτΛผ్࡞੒ %FQMPZNFOU5BSHFUJ04Y

    7JFXίʔυ΋1SFWJFXλʔήοτʹ௥Ճ
    1SFWJFX༻ͷλʔήοτʹ1SFWJFXίʔυΛ௥Ճ

    View Slide

  61. J04ະຬͷαϙʔτ
    ରԠ
    1SFWJFXઐ༻ͷλʔήοτΛ௥Ճ͢Δ
    1SFWJFX༻ͷλʔήοτΛผ్࡞੒ %FQMPZNFOU5BSHFUJ04Y

    7JFXίʔυ΋1SFWJFXλʔήοτʹ௥Ճ
    1SFWJFX༻ͷλʔήοτʹ1SFWJFXίʔυΛ௥Ճ
    ˠ9DPEF(FOΛ࢖ͬͯ9DPEFϓϩδΣΫτΛࣗಈੜ੒͢Δͷ͕͓͢͢Ί
    9DPEF(FOIUUQTHJUIVCDPNZPOBTLPMC9DPEF(FO

    View Slide

  62. iOSDC2019 / ϞόΠϧܾࡁΞϓϦͷ࡞Γํ / How to develop a mobile payment app
    IUUQTTQFBLFSEFDLDPNLFONB[IPXUPEFWFMPQBNPCJMFQBZNFOUBQQ
    w ϝϧΧϦΞϓϦ͸ػೳ͝ͱʹ'SBNFXPSLʹ
    ෼ׂ͞Ε͍ͯΔ
    w ֤'SBNFXPSLϓϩδΣΫτ͝ͱͷ
    4BOECPYΞϓϦΛ࢖ͬͯ௨ৗ͸։ൃ
    ϝϧϖΠͰͷߏ੒
    ˠ1SFWJFXίʔυ͸4BOECPYΞϓϦͷ
    λʔήοτʹ௥Ճ

    View Slide

  63. 9DPEF1SFWJFXTͷ࢓૊Έ

    View Slide

  64. View Slide

  65. View Slide

  66. View Slide

  67. View Slide

  68. View Slide

  69. )FMMP7JFX1SFWJFXQSFWJFXUIVOLTXJGU

    View Slide

  70. %ZOBNJD.FUIPE3FQMBDFNFOU
    w EZOBNJDΩʔϫʔυΛ෇͚ͨϝϯόʔͷ࣮૷Λɺ@EZOBNJD3FQMBDFNFOUଐੑΛ෇͚
    ͨϝϯόʔͷ࣮૷ʹࠩ͠ସ͑Δػೳ 4XJGUd

    IUUQTHJUIVCDPNBQQMFTXJGUQVMM

    View Slide

  71. %ZOBNJD.FUIPE3FQMBDFNFOU
    w EZOBNJDΩʔϫʔυΛ෇͚ͨϝϯόʔͷ࣮૷Λɺ@EZOBNJD3FQMBDFNFOUଐੑΛ෇͚
    ͨϝϯόʔͷ࣮૷ʹࠩ͠ସ͑Δػೳ 4XJGUd

    public class Thing {
    public dynamic var someNumber: Int {
    return 10
    }
    }
    IUUQTHJUIVCDPNBQQMFTXJGUQVMM

    View Slide

  72. %ZOBNJD.FUIPE3FQMBDFNFOU
    w EZOBNJDΩʔϫʔυΛ෇͚ͨϝϯόʔͷ࣮૷Λɺ@EZOBNJD3FQMBDFNFOUଐੑΛ෇͚
    ͨϝϯόʔͷ࣮૷ʹࠩ͠ସ͑Δػೳ 4XJGUd

    public class Thing {
    public dynamic var someNumber: Int {
    return 10
    }
    }
    IUUQTHJUIVCDPNBQQMFTXJGUQVMM
    extension Thing {
    @_dynamicReplacement(for: someNumber)
    var newNumber: Int {
    return 43
    }
    }

    View Slide

  73. %ZOBNJD.FUIPE3FQMBDFNFOU
    w EZOBNJDΩʔϫʔυΛ෇͚ͨϝϯόʔͷ࣮૷Λɺ@EZOBNJD3FQMBDFNFOUଐੑΛ෇͚
    ͨϝϯόʔͷ࣮૷ʹࠩ͠ସ͑Δػೳ 4XJGUd

    public class Thing {
    public dynamic var someNumber: Int {
    return 10
    }
    }
    IUUQTHJUIVCDPNBQQMFTXJGUQVMM
    extension Thing {
    @_dynamicReplacement(for: someNumber)
    var newNumber: Int {
    return 43
    }
    }
    print(Thing().someNumber) //43

    View Slide

  74. // HelloViewPreview.swift
    struct HelloView_Preview: PreviewProvider {
    static var previews: some View {
    Group {
    HelloViewRepresentable(
    input: .init(
    backgroundColor: .white,
    buttonTitle: "Click Me",
    isButtonEnabled: true
    )
    )
    }
    }
    }
    // HelloViewPreview.3.preview-thunk.swift
    extension HelloView_Preview {
    @_dynamicReplacement(for: previews)
    private static var __preview__previews: some View {
    #sourceLocation(file: "/Users/kenmaz/Projects/iOSDC2020App/iOSDC2020App/HelloViewPreview.swift", line: 26)
    AnyView(__designTimeSelection(Group {
    __designTimeSelection(HelloViewRepresentable(
    input: .init(
    backgroundColor: .white,
    buttonTitle: __designTimeString(
    "#3084.[2].[0].property.[0].[0].arg[0].value.[0].arg[0].value.arg[1].value.[0].value",
    fallback: "Click Me"),
    isButtonEnabled: __designTimeBoolean(
    "#3084.[2].[0].property.[0].[0].arg[0].value.[0].arg[0].value.arg[2].value",
    fallback: true)
    )
    ), "#3084.[2].[0].property.[0].[0].arg[0].value.[0]")
    }, "#3084.[2].[0].property.[0].[0]"))
    #sourceLocation()
    }

    View Slide

  75. // HelloViewPreview.swift
    struct HelloView_Preview: PreviewProvider {
    static var previews: some View {
    Group {
    HelloViewRepresentable(
    input: .init(
    backgroundColor: .white,
    buttonTitle: "Click Me",
    isButtonEnabled: true
    )
    )
    }
    }
    }
    // HelloViewPreview.3.preview-thunk.swift
    extension HelloView_Preview {
    @_dynamicReplacement(for: previews)
    private static var __preview__previews: some View {
    #sourceLocation(file: "/Users/kenmaz/Projects/iOSDC2020App/iOSDC2020App/HelloViewPreview.swift", line: 26)
    AnyView(__designTimeSelection(Group {
    __designTimeSelection(HelloViewRepresentable(
    input: .init(
    backgroundColor: .white,
    buttonTitle: __designTimeString(
    "#3084.[2].[0].property.[0].[0].arg[0].value.[0].arg[0].value.arg[1].value.[0].value",
    fallback: "Click Me"),
    isButtonEnabled: __designTimeBoolean(
    "#3084.[2].[0].property.[0].[0].arg[0].value.[0].arg[0].value.arg[2].value",
    fallback: true)
    )
    ), "#3084.[2].[0].property.[0].[0].arg[0].value.[0]")
    }, "#3084.[2].[0].property.[0].[0]"))
    #sourceLocation()
    }
    ˞EZOBNJDΩʔϫʔυ͸Ϗϧυ࣌ʹ௥Ճ͞ΕΔʢΆ͍ʣ

    View Slide

  76. View Slide

  77. ϑϧϏϧυ

    View Slide

  78. දࣔ

    View Slide

  79. ίʔυมߋ

    View Slide

  80. ίʔυੜ੒

    View Slide

  81. Ϗϧυ

    View Slide

  82. EMPQFO

    View Slide

  83. ߋ৽

    View Slide

  84. 1JO1SFWJFX
    w 1JO1SFWJFXϘλϯΛԡ͢ͱɺ$BOWBTΛ։͍ͨ··ଞͷTXJGUϑΝΠϧ
    ΛฤूͰ͖Δ

    View Slide

  85. 1JO1SFWJFX
    w 1JO1SFWJFXϘλϯΛԡ͢ͱɺ$BOWBTΛ։͍ͨ··ଞͷTXJGUϑΝΠϧ
    ΛฤूͰ͖Δ

    View Slide

  86. 1JO1SFWJFX
    w 1JO1SFWJFXϘλϯΛԡ͢ͱɺ$BOWBTΛ։͍ͨ··ଞͷTXJGUϑΝΠϧ
    ΛฤूͰ͖Δ
    w 1JO1SFWJFXΦϯʹ͢Δͱɺ
    1SFWJFXίʔυҎ֎ͷTXJGUίʔ
    υʹରͯ͠΋QSFWJFXUIVOL͕
    ੜ੒͞ΕΔ
    w 1SFWJFXίʔυҎ֎ͷมߋʹର
    ͯ͠΋ଈ࣌൓ө͕ޮ͘

    View Slide

  87. // HelloViewPreview.swift
    struct HelloView_Preview: PreviewProvider {
    static var previews: some View {
    Group {
    HelloViewRepresentable(
    input: .init(
    backgroundColor: .white,
    buttonTitle: "Click Me",
    isButtonEnabled: true
    )
    )
    }
    }
    }
    // HelloViewPreview.3.preview-thunk.swift
    extension HelloView_Preview {
    @_dynamicReplacement(for: previews)
    private static var __preview__previews: some View {
    #sourceLocation(file: "/Users/kenmaz/Projects/iOSDC2020App/iOSDC2020App/HelloViewPreview.swift", line: 26)
    AnyView(__designTimeSelection(Group {
    __designTimeSelection(HelloViewRepresentable(
    input: .init(
    backgroundColor: .white,
    buttonTitle: __designTimeString(
    "#3084.[2].[0].property.[0].[0].arg[0].value.[0].arg[0].value.arg[1].value.[0].value",
    fallback: "Click Me"),
    isButtonEnabled: __designTimeBoolean(
    "#3084.[2].[0].property.[0].[0].arg[0].value.[0].arg[0].value.arg[2].value",
    fallback: true)
    )
    ), "#3084.[2].[0].property.[0].[0].arg[0].value.[0]")
    }, "#3084.[2].[0].property.[0].[0]"))
    #sourceLocation()
    }

    View Slide

  88. // HelloViewPreview.swift
    struct HelloView_Preview: PreviewProvider {
    static var previews: some View {
    Group {
    HelloViewRepresentable(
    input: .init(
    backgroundColor: .white,
    buttonTitle: "Click Me",
    isButtonEnabled: true
    )
    )
    }
    }
    }
    // HelloViewPreview.3.preview-thunk.swift
    extension HelloView_Preview {
    @_dynamicReplacement(for: previews)
    private static var __preview__previews: some View {
    #sourceLocation(file: "/Users/kenmaz/Projects/iOSDC2020App/iOSDC2020App/HelloViewPreview.swift", line: 26)
    AnyView(__designTimeSelection(Group {
    __designTimeSelection(HelloViewRepresentable(
    input: .init(
    backgroundColor: .white,
    buttonTitle: __designTimeString(
    "#3084.[2].[0].property.[0].[0].arg[0].value.[0].arg[0].value.arg[1].value.[0].value",
    fallback: "Click Me"),
    isButtonEnabled: __designTimeBoolean(
    "#3084.[2].[0].property.[0].[0].arg[0].value.[0].arg[0].value.arg[2].value",
    fallback: true)
    )
    ), "#3084.[2].[0].property.[0].[0].arg[0].value.[0]")
    }, "#3084.[2].[0].property.[0].[0]"))
    #sourceLocation()
    }

    View Slide

  89. @EFTJHO5JNF4USJOH@EFTJHO5JNF#PPMFBO
    buttonTitle: __designTimeString(
    "#3084.[2].[0].property.[0].[0].arg[0].value.[0].arg[0].value.arg[1].value.[0].value",
    fallback: "Click Me"
    )

    View Slide

  90. @EFTJHO5JNF4USJOH@EFTJHO5JNF#PPMFBO
    buttonTitle: __designTimeString(
    "#3084.[2].[0].property.[0].[0].arg[0].value.[0].arg[0].value.arg[1].value.[0].value",
    fallback: "Click Me"
    )

    View Slide

  91. w 9DPEF1SFWJFXTΛ࢖ͬͯ6*,JUϕʔεͷΞϓϦ։ൃΛޮ཰ԽͰ͖Δ
    w มߋ㲗֬ೝͷαΠΫϧͷߴ଎Խ
    w ͍ΖΜͳঢ়ଶͷϏϡʔΛҰ౓ʹදࣔɾ֬ೝͰ͖Δ
    w 1SFWJFXΛ࣮ߦՄೳͳը໘࢓༷ॻͱͯ͠ڞ༗Ͱ͖Δ
    w 9DPEF1SFWJFXTΛಋೖͯ͠طଘΞϓϦΛ4XJGU6*ͷ։ൃελΠϧʹدͤΔ
    w 4XJGU6*΁ͷҠߦ͕ΑΓεϜʔζʹ
    ·ͱΊ

    View Slide

  92. ࢀߟจݙ
    w "QQMF%FWFMPQFS4UBSU%FWFMPQJOHJ04"QQT 4XJGU

    w 88%$4USVDUVSFZPVSBQQGPS4XJGU6*QSFWJFXT
    w 88%$.BTUFSJOH9DPEF1SFWJFXT
    w J043FMFBTF/PUFT4XJGU6*,OPXO*TTVF

    w (VBSETRVBSF%FWCMPH#FIJOE4XJGU6*1SFWJFXT
    w LBUFJOPJHBLVLVO*OTJEF4XJGU6* )PX)PUSFMPBEJOHJNQMFNFOUFE

    w BQQMFTXJGU%ZOBNJDGVODUJPOSFQMBDFNFOU
    w J04%$ϞόΠϧܾࡁΞϓϦͷ࡞Γํ)PXUPEFWFMPQBNPCJMFQBZNFOUBQQ
    w NFSDBSJFOHJOFFSJOH9DPEF1SFWJFXTΛ༻͍ͨ6*,JUϕʔεͷϓϩδΣΫτͷ։ൃޮ཰Խ

    View Slide

  93. View Slide