Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

iOS Engineer Shota Nakagami @shtnkgm

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

ͦΕͧΕͷಛ௃

Slide 6

Slide 6 text

StoryboardͱXIBͷಛ௃

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

Dependency Injectionͷҧ͍

Slide 13

Slide 13 text

Storyboard // NG: ίϯετϥΫλΠϯδΣΫγϣϯ͸ෆՄ let viewController = ViewController(dependency: Dependency()) // OK: ϓϩύςΟΠϯδΣΫγϣϯʹͳΒՄ let storyboard = UIStoryboard(name: "ViewController", bundle: nil) let viewController = storyboard.instantiateInitialViewController() viewController.dependency = Dependency()

Slide 14

Slide 14 text

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") } }

Slide 15

Slide 15 text

ൺֱ߲໨ Storyboard XIB ίʔυϕʔε ➡ Segue͕࢖͑Δ ✅ # GUIͰݟͯΘ͔Δ ✅ ✅ $ αΠζ෼ذ͕༰қ ✅ ✅ % ੩తνΣοΫ ✅ ✅ &ίϯετϥΫλDI ✅ ✅ ♻ ࠶ར༻ੑ ✅ ( ίϯϑϦΫτ଱ੑ ✅ ) ϨϏϡʔ͠΍͢͞ ✅

Slide 16

Slide 16 text

I ! Code-based Laout

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

1. Initialization Closure

Slide 19

Slide 19 text

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... } }

Slide 20

Slide 20 text

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... } }

Slide 21

Slide 21 text

2. Then

Slide 22

Slide 22 text

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... } }

Slide 23

Slide 23 text

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... } }

Slide 24

Slide 24 text

Thenͷ࣮૷ public protocol Then {} extension Then where Self: AnyObject { public func then(_ block: (Self) throws -> Void) rethrows -> Self { try block(self) return self } }

Slide 25

Slide 25 text

3. ΧελϜΫϥε

Slide 26

Slide 26 text

ΧελϜΫϥεͰ࠶ར༻ੑΛߴΊɺΑΓγϯϓϧʹ class ViewController: UIViewController { let priceLabel = PriceLabel() // ΧελϜΫϥεԽ let imageView = ItemImageView() // ΧελϜΫϥεԽ override func viewDidLoad() { super.viewDidLoad() // addSubview, AutoLayout... } }

Slide 27

Slide 27 text

4. lazy var

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

private let captureButton = CaptureButton().then { $0.onTapped = { [weak self] in // ίϯύΠϧΤϥʔ self?.camera.capture() // ίϯύΠϧΤϥʔ } }

Slide 30

Slide 30 text

lazy varͰॳظԽ஗ԆɺselfΛࢀরՄʹ private lazy var captureButton = CaptureButton().then { $0.onTapped = { [weak self] in self?.camera.capture() // OK } }

Slide 31

Slide 31 text

5. SnapKit / PureLayout

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

!

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

// ಡΈ΍͍͢ 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() // ࠨӈ͸਌Ϗϡʔʹ }

Slide 36

Slide 36 text

Slide 37

Slide 37 text

6. UIStackView

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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