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

20190117_iOSLT_CBLinSwift.pdf

shtnkgm
January 17, 2019

 20190117_iOSLT_CBLinSwift.pdf

Code-Based Layout in Swift

shtnkgm

January 17, 2019
Tweet

More Decks by shtnkgm

Other Decks in Programming

Transcript

  1. CBL in Swift
    Shota Nakagami

    View Slide

  2. Talking about "CBL"

    View Slide

  3. !

    View Slide

  4. CBL
    Code-Based layout

    View Slide

  5. I
    !
    Code-Based Layout

    View Slide

  6. How to layout ?
    4 StoryBoard
    4 XIB
    4 Code-BasedʢProgrammaticallyʣ

    View Slide

  7. Storyboard & XIB features
    4 Ease of use

    4 Segue

    4 Visual (multi device screen size)
    4 Constraint Checker

    4 Non-Reusable
    "
    4 Hard to Resolve Conflict
    "
    4 Hard to review (XML)
    "

    View Slide

  8. Testable?
    !
    class ViewController: UIViewController {
    let dependency: Dependency
    // Dependency Injection with Initializer
    init(dependency: Dependency) { self.dependency = dependency }
    }
    4 NG: Storyboard

    no initializer...
    4 OK: XIB
    "
    4 OK: CBL
    "

    View Slide

  9. CBL features
    4 Reusable

    4 Speedy

    4 Easy to Resolve Conflict

    4 Easy to Review

    4 Cost of Learning
    "
    4 Non-Visual
    "

    View Slide

  10. StoryBoard XIB Codebased
    ! Segue ✅
    # Visual ✅ ✅
    $ Compiler Check ✅ ✅
    % Testable (DI) ✅ ✅
    ♻ Reusable ✅
    ' Less Conflict ✅
    ( Reviewable ✅

    View Slide

  11. 6 Tips for CBL

    View Slide

  12. 1. Initialization Closure
    2. "Then"
    3. Custom View Class
    4. lazy var
    5. "SnapKit"
    6. UIStackView

    View Slide

  13. class ViewController: UIViewController {
    let priceLabel = UILabel()
    let imageView = UIImageView()
    override func viewDidLoad() {
    super.viewDidLoad()
    priceLabel.numberOfLines = 2
    priceLabel.textColor = .red
    priceLabel.font = .boldSystemFont(ofSize: 14)
    imageView.contentMode = .scaleAspectFill
    imageView.clipsToBounds = true
    imageView.layer.cornerRadius = 4
    // addSubview, AutoLayout...
    }
    }

    View Slide

  14. messy viewDidLoad...

    View Slide

  15. 1. Initialization Closure

    View Slide

  16. class ViewController: UIViewController {
    let priceLabel: UILabel = {
    let label = UILabel()
    label.numberOfLines = 2
    label.textColor = .red
    label.font = .boldSystemFont(ofSize: 14)
    return label
    }()
    let imageView: UIImageView = {
    let view = UIImageView()
    view.contentMode = .scaleAspectFill
    view.clipsToBounds = true
    view.layer.cornerRadius = 4
    return view
    }()
    override func viewDidLoad() {
    super.viewDidLoad()
    // addSubview, AutoLayout...
    }
    }

    View Slide

  17. viewDidLoad is clean, but...

    View Slide

  18. class ViewController: UIViewController {
    let priceLabel: UILabel = { // type annotation
    let label = UILabel() // renaming
    label.numberOfLines = 2
    label.textColor = .red
    label.font = .boldSystemFont(ofSize: 14)
    return label // return
    }()
    let imageView: UIImageView = { // type annotation
    let view = UIImageView() // renaming
    view.contentMode = .scaleAspectFill
    view.clipsToBounds = true
    view.layer.cornerRadius = 4
    return view // return
    }()
    override func viewDidLoad() {
    super.viewDidLoad()
    // addSubview, AutoLayout...
    }
    }

    View Slide

  19. 2. "Then"
    https://github.com/devxoul/Then

    View Slide

  20. class ViewController: UIViewController {
    let priceLabel = UILabel().then {
    $0.numberOfLines = 2
    $0.textColor = .red
    $0.font = .boldSystemFont(ofSize: 14)
    }
    let imageView = UIImageView().then {
    $0.contentMode = .scaleAspectFill
    $0.clipsToBounds = true
    $0.layer.cornerRadius = 4
    }
    override func viewDidLoad() {
    super.viewDidLoad()
    // addSubview, AutoLayout...
    }
    }

    View Slide

  21. 3. Custom View Class

    View Slide

  22. class ViewController: UIViewController {
    let priceLabel = PriceLabel()
    let imageView = ItemImageView()
    override func viewDidLoad() {
    super.viewDidLoad()
    }
    }

    View Slide

  23. private let captureButton = CaptureButton().then {
    $0.onTapped = { [weak self] in
    self?.camera.capture()
    }
    }

    View Slide

  24. private let captureButton = CaptureButton().then {
    $0.onTapped = { [weak self] in // Compile Error
    self?.camera.capture() // Compile Error
    }
    }

    View Slide

  25. 4. lazy var

    View Slide

  26. private lazy var captureButton = CaptureButton().then {
    $0.onTapped = { [weak self] in
    self?.camera.capture() // OK
    }
    }

    View Slide

  27. Codebased AutoLayout

    View Slide

  28. NSLayoutAnchor ?
    // addSubview, AutoLayout...
    view.addSubview(button)
    button.leadingAnchor.constraintEqualToAnchor(view.leadingAnchor).active = true
    button.trailingAnchor.constraintEqualToAnchor(view.trailingAnchor).active = true
    button.topAnchor.constraintEqualToAnchor(view.topAnchor).active = true
    button.bottomAnchor.constraintEqualToAnchor(view.bottomAnchor).active = true

    View Slide

  29. !

    View Slide

  30. 5. "SnapKit"
    https://github.com/SnapKit/SnapKit

    View Slide

  31. view.addSubview(button)
    // button.leadingAnchor.constraintEqualToAnchor(view.leadingAnchor).active = true
    // button.trailingAnchor.constraintEqualToAnchor(view.trailingAnchor).active = true
    // button.topAnchor.constraintEqualToAnchor(view.topAnchor).active = true
    // button.bottomAnchor.constraintEqualToAnchor(view.bottomAnchor).active = true
    button.snp.makeConstraints { $0.edges.equalToSuperview() }

    View Slide

  32. // readable
    button.snp.makeConstraints {
    $0.center.equalToSuperview()
    $0.size.equalTo(CGSize(width: 64, height: 64))
    }
    // Support Safe Area
    tableView.snp.makeConstraints {
    $0.top.bottom.equalTo(view.safeAreaLayoutGuide)
    $0.leading.trailing.equalToSuperview()
    }

    View Slide

  33. 6. UIStackView

    View Slide

  34. UIStackView = Stack "Layouted" View
    Less Constraints
    !
    stackView.addArrangedSubview(label)
    stackView.addArrangedSubview(imageView)
    stackView.addArrangedSubview(button)
    label.snp.makeConstraints { $0.height.equalTo(20) }
    button.snp.makeConstraints { $0.height.equalTo(60) }

    View Slide

  35. Summary

    View Slide

  36. CBL: Code-Based layout
    4 Testable, Speedy, and Reusable
    4 Use "6 Tips" to clean code
    When to Use
    4 Use CBL for simple layout
    4 Use XIB for complicated layout
    4 Use StoryBoard for segue

    View Slide