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

Xcode Previews - IB없이 개발하기

VCNC
November 12, 2019

Xcode Previews - IB없이 개발하기

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

VCNC

November 12, 2019
Tweet

More Decks by VCNC

Other Decks in Programming

Transcript

  1. Xcode Previews Xcode Previews in UIKit Problems with Storyboard, XIB

    UI programming using Xcode Previews $POUFOUT
  2. struct PriceView_Preview: PreviewProvider { static var previews: some View {

    PriceView(price:…) .previewLayout(.sizeThatFits) .environment(\.colorScheme, .dark) } }
  3. • 2 Main Components • A preview build • Xcode

    extension ( live view ) 9DPEF1SFWJFXT
  4. • Normal Build • Xcode scheme, build settings ਸ ٮܰח

    ੌ߈੸ੋ ࠽٘ • Preview Build • ୶о compile optionҗ ೣԋ normal buildܳ ഛ੢ೠ ߹ب੄ ࠽٘ 9DPEF1SFWJFXT
  5. • Xcode build artifact ী normal ࠽٘৬ ೣԋ ઓ੤ •

    Object file, artifact ҕਬ • Additional Options • Interactive UI ࣻ੿ / dynamic behavior ೲਊ • ਗࠄ ౵ੌ ৻ ୶о੸ੋ ࣗझ ౵ੌ ࢤࢿ • ਗࠄ ࣗझ ௏٘ܳ ࠗ࠙੸ਵ۽ UIܳ ࣻ੿ೡ ࣻ ੓ח ௏٘۽ ߸҃ by method swizzling 1SFWJFX#VJME
  6. @_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
  7. • UIViewController ب Previews ࢎਊ оמ • UIViewControllerRepresentable protocol 9DPEF1SFWJFXTJO6*,JU

    func makeUIViewController(context: Self.Context) -> Self.UIViewControllerType func updateUIViewController( _ uiViewController: Self.UIViewControllerType, context: Self.Context )
  8. • UIView ب Previews ࢎਊ оמ • UIViewRepresentable protocol 9DPEF1SFWJFXTJO6*,JU

    func makeUIView(context: Self.Context) -> Self.UIViewType func updateUIView( _ uiView: Self.UIViewType, context: Self.Context )
  9. • Previews ীࢲ ࢎਊೞӝ ਤೠ protocol • UIKit -> SwiftUI

    • SwiftUI ܳ ࢎਊೡ ࣻ ੓ח ജ҃ীࢲ݅ ੉ਊ оמ 6*7JFX3FQSFTFOUBCMF
  10. • Debug ࠽٘ ࢸ੿ ߸҃ • iOS Deployment target :

    iOS13 • canImport, @available 9DPEF1SFWJFXTJ04
  11. #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
  12. • XML • ੍Ѣա ࣻ੿ೡ ࣻ হח XML • ࣻ

    ߔ઴ ੉࢚੄ ௾ ౵ੌ 3FBEBCJMJUZ
  13. • XML • ੍Ѣա ࣻ੿ೡ ࣻ হח XML • ࣻ

    ߔ઴ ੉࢚੄ ௾ ౵ੌ • э਷ Viewܳ ࣻ੿ೞݶ? • PR 3FBEBCJMJUZ
  14. • ౵ੌ੉ ੼੼ ழ૗ • যו࢜ ࣻभ ѐ੄ झ௼ܽ੉ ೞա੄

    ౵ੌী.. • Source control ߄Ե ٸ݃׮ 4UPSZCPBSET
  15. • IBח Swift ௏٘ܳ ੜ ݽܴ(vice versa) • IBOutlet, IBAction

    ਸ ా೧ োѾ • IBীࢲ Viewܳ ૑ਕب ௏٘ח Ӓ؀۽… • Cell in TableView ীࢲ identifier۽ оઉয়ӝ (Typecast ೙ࣻ ) 4XJGU*OUFSGBDFCVJMEFS
  16. • Color asset ਵ۽ ࢸ੿ೠ ࢝੉ viewDidLoad, viewWillAppear, awakeFromNib ࣻ੿

    ࠛо • Callstack • viewDidLoad(viewWillAppear) -> traitCollectionDidChanged ->
 ੿੄ػ asset color۽ trait collection ੸ਊ *OUFSGBDFCVJMEFSCVHT
  17. 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])
  18. 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))
  19. • ૒ҙ੸ਵ۽ ചݶਸ ੉೧ೞӝ য۰਑ • View ҳઑܳ ౵ঈೞӝ ਤ೧

    ੹୓ ௏٘ ౵ঈ ೙ਃ • View Hierarchy ↑ ➡ Time ↑ • Layout library੄ ೠ҅ 1SPHSBNNBUJDBMMZ6*
  20. • makeConstraints: э਷ ࠗݽܳ ыח Views݅ оמ • addSubview /

    makeConstraints ௏٘ ܻ࠙ • Nested ҳઑੌ ٸ children ਸ ݢ੷ ੘ࢿ 4OBQ,JU
  21. 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)
  22. @_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) } … }
  23. • SnapKit ӝ߈ Layout
 • addSubview -> SnapKit.makeConstraints • Dynamic

    member lookup -BZPVU func makeConstraints(_ closure: @escaping (ConstraintMaker) -> Void) -> Self
  24. • PreviewProvider protocol • Group / ForEach • previewLayout /

    previewDevice / environment • Development Assets • Pinning 9DPEF1SFWJFXT