iOSのコードベースレイアウト

E45f9c343d90c74554c65c89c6f861bc?s=47 shtnkgm
January 31, 2019

 iOSのコードベースレイアウト

E45f9c343d90c74554c65c89c6f861bc?s=128

shtnkgm

January 31, 2019
Tweet

Transcript

  1. iOSͷίʔυϕʔεϨΠΞ΢τ Mobile Act TOKYO #5 @shtnkgm

  2. iOS Engineer Shota Nakagami @shtnkgm

  3. ࿩͢͜ͱ • iOSͷUIϨΠΞ΢τख๏ͷൺֱ • ίʔυϕʔεϨΠΞ΢τ Tips

  4. UIͷϨΠΞ΢τख๏ • ϓϩάϥϜͰهड़ʢίʔυϕʔεʣ • Storyboard • Interface BuilderʢXIBʣ

  5. ͦΕͧΕͷಛ௃

  6. StoryboardͱXIBͷಛ௃

  7. ྑ͍ͱ͜Ζ • ෳ਺ͷը໘αΠζͰ෼ذɺݟ͑ํνΣοΫʢSize Classesʣ • Ϗϧυલʹ੩తͳ੍໿ͷݕࠪ • Storyboardͷ৔߹͸Segue͕࢖͑Δ

  8. ΠϚΠνͳͱ͜Ζ • ίϐϖ΍ɺΧελϜΫϥεԽͳͲͷ࠶ར༻ɾमਖ਼͕ͮ͠Β͍ • XMLͳͷͰίϯϑϦΫτͷղফɺίʔυϨϏϡʔ͕೉͍͠ • GUIͰΆͪΆͪ͠ͳ͍ͱԿ͕ઃఆͯ͋͠Δͷ͔ٯʹΘ͔Βͳ͍

  9. ίʔυϕʔεϨΠΞ΢τͷಛ௃

  10. ྑ͍ͱ͜Ζ • ίϐϖ΍ίʔυஔ׵ͳͲͰεϐʔσΟʹ࠶ར༻ɾमਖ਼͕Մೳ • ίϯϑϦΫτͷղফ΍ϨϏϡʔ͕͠΍͍͢ • Կ͕ઃఆͯ͋͠Δͷ͔Ұཡੑ͕͋Δ

  11. ΠϚΠνͳͱ͜Ζ • UIKitͷϓϩύςΟ΍ϥΠϑαΠΫϧʹؔ͢Δ஌͕ࣝඞཁ • ࣮ߦ͢Δ·Ͱݟ͑ํ͸૝૾

  12. Dependency Injectionͷҧ͍

  13. Storyboard // NG: ίϯετϥΫλΠϯδΣΫγϣϯ͸ෆՄ let viewController = ViewController(dependency: Dependency()) //

    OK: ϓϩύςΟΠϯδΣΫγϣϯʹͳΒՄ let storyboard = UIStoryboard(name: "ViewController", bundle: nil) let viewController = storyboard.instantiateInitialViewController() viewController.dependency = Dependency()
  14. XIB / ίʔυϕʔε class ViewController: UIViewController { let dependency: Dependency

    init(dependency: Dependency) { self.dependency = dependency super.init(nibName: nil, bundle: nil) } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } }
  15. ൺֱ߲໨ Storyboard XIB ίʔυϕʔε ➡ Segue͕࢖͑Δ ✅ # GUIͰݟͯΘ͔Δ ✅

    ✅ $ αΠζ෼ذ͕༰қ ✅ ✅ % ੩తνΣοΫ ✅ ✅ &ίϯετϥΫλDI ✅ ✅ ♻ ࠶ར༻ੑ ✅ ( ίϯϑϦΫτ଱ੑ ✅ ) ϨϏϡʔ͠΍͢͞ ✅
  16. I ! Code-based Laout

  17. ίʔυϕʔεϨΠΞ΢τTipsʢ6ͭʣ

  18. 1. Initialization Closure

  19. 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... } }
  20. 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... } }
  21. 2. Then

  22. class ViewController: UIViewController { let priceLabel: UILabel = { //

    ܕΞϊςʔγϣϯ let label = UILabel() // ϩʔΧϧείʔϓͰͷ໋໊ label.numberOfLines = 2 // label label.textColor = .red // label label.font = .boldSystemFont(ofSize: 14) // label return label // ੜ੒ͨ͠Πϯελϯεͷreturn }() let imageView: UIImageView = { // ܕΞϊςʔγϣϯ let view = UIImageView() // ϩʔΧϧείʔϓͰͷ໋໊ view.contentMode = .scaleAspectFill // view view.clipsToBounds = true // view view.layer.cornerRadius = 4 // view return view // ੜ੒ͨ͠Πϯελϯεͷreturn }() override func viewDidLoad() { super.viewDidLoad() // addSubview, AutoLayout... } }
  23. 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... } }
  24. Thenͷ࣮૷ public protocol Then {} extension Then where Self: AnyObject

    { public func then(_ block: (Self) throws -> Void) rethrows -> Self { try block(self) return self } }
  25. 3. ΧελϜΫϥε

  26. ΧελϜΫϥεͰ࠶ར༻ੑΛߴΊɺΑΓγϯϓϧʹ class ViewController: UIViewController { let priceLabel = PriceLabel() //

    ΧελϜΫϥεԽ let imageView = ItemImageView() // ΧελϜΫϥεԽ override func viewDidLoad() { super.viewDidLoad() // addSubview, AutoLayout... } }
  27. 4. lazy var

  28. private let captureButton = CaptureButton().then { $0.onTapped = { [weak

    self] in // selfࢀর͍ͨ͠ self?.camera.capture() // selfࢀর͍ͨ͠ } }
  29. private let captureButton = CaptureButton().then { $0.onTapped = { [weak

    self] in // ίϯύΠϧΤϥʔ self?.camera.capture() // ίϯύΠϧΤϥʔ } }
  30. lazy varͰॳظԽ஗ԆɺselfΛࢀরՄʹ private lazy var captureButton = CaptureButton().then { $0.onTapped

    = { [weak self] in self?.camera.capture() // OK } }
  31. 5. SnapKit / PureLayout

  32. NSLayoutAnchorʢiOS9ʙʣ 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
  33. !

  34. SnapKit / PureLayout // SnapKit button.snp.makeConstraints { $0.edges.equalToSuperview() } //

    PureLaout button.autoPinEdgesToSuperviewEdges()
  35. // ಡΈ΍͍͢ button.snp.makeConstraints { $0.center.equalToSuperview() // ਌Ϗϡʔͷத৺ʹ $0.size.equalTo(CGSize(width: 64, height:

    64)) // αΠζࢦఆ } // Safe Areaʹ΋ϨΠΞ΢τΛషΓ΍͍͢ tableView.snp.makeConstraints { $0.top.bottom.equalTo(view.safeAreaLayoutGuide) // ্Լ͸Safe Areaʹ $0.leading.trailing.equalToSuperview() // ࠨӈ͸਌Ϗϡʔʹ }
  36. 6. UIStackView

  37. UIStackViewͰϨΠΞ΢τ͢Δ stackView.addArrangedSubview(label) stackView.addArrangedSubview(imageView) stackView.addArrangedSubview(button) label.snp.makeConstraints { $0.height.equalTo(20) } button.snp.makeConstraints {

    $0.height.equalTo(60) }
  38. ·ͱΊ • ίʔυϕʔεϨΠΞ΢τͰ΋TipsΛ࢖͑͹؆͔ܿͭεϐʔσΟ • Ͳͷख๏΋Ͱ͖ΔΑ͏ʹ͓͖ͯ͠ɺ࢖͍෼͚͍ͨ

  39. αϯϓϧίʔυ github.com/shtnkgm/ iOSUILayoutMethods

  40. ͋Γ͕ͱ͏͍͟͝·ͨ͠ʂ