Xcode Previews - IB없이 개발하기

6a11050c8147e4f5fbf2637907c27964?s=47 VCNC
November 12, 2019

Xcode Previews - IB없이 개발하기

모바일 개발자에게 화면을 예쁘게 만드는 것은 매우 중요한 업무 중 하나이다. 하지만 이를 달성하기 위해서는 매번 구현, 빌드, 전달, 해당화면 띄우기 등 너무나 많은 시간과 노력이 요구된다. 그뿐만 아니라 잘 동작하는 앱을 만들기 위해서는 dynamic content size, 다크모드 등 다양한 환경과 여러 디바이스에서 확인해야 한다. 이러한 문제를 해결하기 위해 Xcode11에서 Previews 라는 기능이 추가되었다. 이번 세션에서는 Xcode Previews 에 대한 소개와 동작 원리를 파악하고 간단한 데모를 통해 해당 기능을 이해해보려고 한다. 더 나아가 SwiftUI 를 사용하지 않는 기존의 서비스에서 Previews 기능을 사용하는 방법을 알아보고, 이를 이용해 타다가 어떻게 UI 작업을 진행하는지 공유하고자 한다.

6a11050c8147e4f5fbf2637907c27964?s=128

VCNC

November 12, 2019
Tweet

Transcript

  1. 3.

    Xcode Previews Xcode Previews in UIKit Problems with Storyboard, XIB

    UI programming using Xcode Previews $POUFOUT
  2. 15.

    struct PriceView_Preview: PreviewProvider { static var previews: some View {

    PriceView(price:…) .previewLayout(.sizeThatFits) .environment(\.colorScheme, .dark) } }
  3. 16.
  4. 17.
  5. 19.

    • 2 Main Components • A preview build • Xcode

    extension ( live view ) 9DPEF1SFWJFXT
  6. 20.

    • Normal Build • Xcode scheme, build settings ਸ ٮܰח

    ੌ߈੸ੋ ࠽٘ • Preview Build • ୶о compile optionҗ ೣԋ normal buildܳ ഛ੢ೠ ߹ب੄ ࠽٘ 9DPEF1SFWJFXT
  7. 21.

    • Xcode build artifact ী normal ࠽٘৬ ೣԋ ઓ੤ •

    Object file, artifact ҕਬ • Additional Options • Interactive UI ࣻ੿ / dynamic behavior ೲਊ • ਗࠄ ౵ੌ ৻ ୶о੸ੋ ࣗझ ౵ੌ ࢤࢿ • ਗࠄ ࣗझ ௏٘ܳ ࠗ࠙੸ਵ۽ UIܳ ࣻ੿ೡ ࣻ ੓ח ௏٘۽ ߸҃ by method swizzling 1SFWJFX#VJME
  8. 24.

    @_private(sourceFile: "ContentView.swift") import LetSwiftPreview import SwiftUI import SwiftUI extension ContentView_Previews

    { @_dynamicReplacement(for: previews) private static var __preview__previews: some View { #sourceLocation(file: "/Users/nate/Documents/samples/SwiftUI/ LetSwiftPreview/LetSwiftPreview/LetSwiftPreview/ContentView.swift", line: 19) AnyView(__designTimeSelection(ContentView(), "#40077.[2].[0].property.[0]. [0]")) #sourceLocation() } } typealias ContentView = LetSwiftPreview.ContentView typealias ContentView_Previews = LetSwiftPreview.ContentView_Previews
  9. 25.
  10. 27.

    • UIViewController ب Previews ࢎਊ оמ • UIViewControllerRepresentable protocol 9DPEF1SFWJFXTJO6*,JU

    func makeUIViewController(context: Self.Context) -> Self.UIViewControllerType func updateUIViewController( _ uiViewController: Self.UIViewControllerType, context: Self.Context )
  11. 28.

    • UIView ب Previews ࢎਊ оמ • UIViewRepresentable protocol 9DPEF1SFWJFXTJO6*,JU

    func makeUIView(context: Self.Context) -> Self.UIViewType func updateUIView( _ uiView: Self.UIViewType, context: Self.Context )
  12. 29.

    • Previews ীࢲ ࢎਊೞӝ ਤೠ protocol • UIKit -> SwiftUI

    • SwiftUI ܳ ࢎਊೡ ࣻ ੓ח ജ҃ীࢲ݅ ੉ਊ оמ 6*7JFX3FQSFTFOUBCMF
  13. 30.

    • Debug ࠽٘ ࢸ੿ ߸҃ • iOS Deployment target :

    iOS13 • canImport, @available 9DPEF1SFWJFXTJ04
  14. 31.

    #if canImport(SwiftUI) && DEBUG import SwiftUI @available(iOS 13.0, *) struct

    PriceView_Preview: UIViewRepresentable, PreviewProvider { let price: Price func makeUIView(context: Self.Context) -> PriceView { PriceView().also { $0.price = price } } func updateUIView(_ view: PriceView, context: Self.Context) { … } static var previews: some View { PriceView_Preview(price: …) } } #endif
  15. 32.
  16. 34.

    • XML • ੍Ѣա ࣻ੿ೡ ࣻ হח XML • ࣻ

    ߔ઴ ੉࢚੄ ௾ ౵ੌ 3FBEBCJMJUZ
  17. 36.

    • XML • ੍Ѣա ࣻ੿ೡ ࣻ হח XML • ࣻ

    ߔ઴ ੉࢚੄ ௾ ౵ੌ • э਷ Viewܳ ࣻ੿ೞݶ? • PR 3FBEBCJMJUZ
  18. 37.
  19. 38.

    • ౵ੌ੉ ੼੼ ழ૗ • যו࢜ ࣻभ ѐ੄ झ௼ܽ੉ ೞա੄

    ౵ੌী.. • Source control ߄Ե ٸ݃׮ 4UPSZCPBSET
  20. 39.

    • IBח Swift ௏٘ܳ ੜ ݽܴ(vice versa) • IBOutlet, IBAction

    ਸ ా೧ োѾ • IBীࢲ Viewܳ ૑ਕب ௏٘ח Ӓ؀۽… • Cell in TableView ীࢲ identifier۽ оઉয়ӝ (Typecast ೙ࣻ ) 4XJGU*OUFSGBDFCVJMEFS
  21. 40.

    • Color asset ਵ۽ ࢸ੿ೠ ࢝੉ viewDidLoad, viewWillAppear, awakeFromNib ࣻ੿

    ࠛо • Callstack • viewDidLoad(viewWillAppear) -> traitCollectionDidChanged ->
 ੿੄ػ asset color۽ trait collection ੸ਊ *OUFSGBDFCVJMEFSCVHT
  22. 44.

    header.translatesAutoresizingMaskIntoConstraints = false let cn1 = NSLayoutConstraint(item: header, attribute: .leading,

    relatedBy: .equal, toItem: view, attribute: .leading, multiplier: 1.0, constant: 20) let cn2 = NSLayoutConstraint(item: header, attribute: .trailing, relatedBy: .equal, toItem: view, attribute: .trailing, multiplier: 1.0, constant: -20) let cn3 = NSLayoutConstraint(item: header, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: 60) let cn4 = NSLayoutConstraint(item: header, attribute: .top, relatedBy: .equal, toItem: view, attribute: .top, multiplier: 1.0, constant: 20) view.addConstraints([cn1, cn2, cn3, cn4])
  23. 48.

    blackView.snp.makeConstraints { make in make.center.equalTo(view) make.size.equalTo(CGSize(width: 100, height: 100)) }

    redView.snp.makeConstraints { make in make.top.equalTo(blackView.snp.bottom).offset(20.0) make.right.equalTo(blackView.snp.left).offset(-20.0) make.size.equalTo(CGSize(width: 100, height: 100)) } yellowView.snp.makeConstraints { make in make.top.equalTo(blackView.snp.bottom).offset(20.0) make.left.equalTo(blackView.snp.right).offset(20.0) make.size.equalTo(CGSize(width: 100, height: 100)) } blueView.snp.makeConstraints { make in make.bottom.equalTo(blackView.snp.top).offset(-20.0) make.left.equalTo(blackView.snp.right).offset(20.0) make.size.equalTo(CGSize(width: 100, height: 100)) } greenView.snp.makeConstraints { make in make.bottom.equalTo(blackView.snp.top).offset(-20.0) make.right.equalTo(blackView.snp.left).offset(-20.0) make.size.equalTo(CGSize(width: 100, height: 100))
  24. 49.

    • ૒ҙ੸ਵ۽ ചݶਸ ੉೧ೞӝ য۰਑ • View ҳઑܳ ౵ঈೞӝ ਤ೧

    ੹୓ ௏٘ ౵ঈ ೙ਃ • View Hierarchy ↑ ➡ Time ↑ • Layout library੄ ೠ҅ 1SPHSBNNBUJDBMMZ6*
  25. 50.

    • makeConstraints: э਷ ࠗݽܳ ыח Views݅ оמ • addSubview /

    makeConstraints ௏٘ ܻ࠙ • Nested ҳઑੌ ٸ children ਸ ݢ੷ ੘ࢿ 4OBQ,JU
  26. 54.

    UIView() { UIView().identifier(“upper") .backgroundColor(.cyan) .makeConstraints { $0.top.left.right.equalToSuperview() $0.height.equalTo(30) } UIView().identifier("lower")

    .backgroundColor(.blue) .makeConstraints { $0.top.equalTo($0.views.upper.bottom) $0.bottom.left.right.equalToSuperview() $0.height.equalTo(30) } } .identifier(“yellow") .assign(to: \.container, on: self)
  27. 55.
  28. 59.

    @_functionBuilder struct ViewBulder { static func buildBlock() -> Builder {

    BuilderImpl(children: []) } static func buildEither(first: UIView) -> Builder { BuilderImpl(children: [first]) } static func buildEither(second: UIView) -> Builder { BuilderImpl(children: [second]) } static func buildIf(_ view: UIView?) -> Builder { BuilderImpl(children: view.map { [$0] } ?? []) } static func buildBlock(_ views: UIView...) -> Builder { BuilderImpl(children: views) } … }
  29. 60.

    • SnapKit ӝ߈ Layout
 • addSubview -> SnapKit.makeConstraints • Dynamic

    member lookup -BZPVU func makeConstraints(_ closure: @escaping (ConstraintMaker) -> Void) -> Self
  30. 63.
  31. 64.

    • PreviewProvider protocol • Group / ForEach • previewLayout /

    previewDevice / environment • Development Assets • Pinning 9DPEF1SFWJFXT
  32. 70.