Empty State表示共通化の事例 / Case of empty state commonization

6b768efbefea5fb63dc24321d61d7242?s=47 kentaro
December 18, 2018

Empty State表示共通化の事例 / Case of empty state commonization

potatotips #57の資料です。
https://potatotips.connpass.com/event/109263/

6b768efbefea5fb63dc24321d61d7242?s=128

kentaro

December 18, 2018
Tweet

Transcript

  1. &NQUZ4UBUFදࣔڞ௨Խͷࣄྫ QPUBUPUJQT,FOUBSP5BHVDIJ !LFOLFOLFO@

  2.  ֓ཁ  ϧʔϧܾΊ  ࣮૷ʹ͍ͭͯ Ξ δ Σ ϯ

    μ
  3. ֓ཁ

  4. &NQUZ4UBUFͷදࣔΛ౷Ұͨ͠ Կ Λ ͠ ͨ ͷ ͔

  5. ը໘࡞੒࣌ʹ౎౓σβΠϯɾ࣮૷͞Ε͍ͯͨ ը໘ʹΑͬͯද͕ࣔόϥόϥ σβΠϯɾ࣮૷Λʮߟ͑Δʯ޻਺͕ൃੜ ͳ ͥ ΍ ͬ ͨ ͷ ͔

  6. C F G P S F

  7. B G U F S

  8. w ΞϓϦ಺ͷ&NQUZ4UBUFද͕ࣔ౷Ұ͞Εͨ w ίετ࡟ݮʢاըɾσβΠϯɾ࣮૷ʣ Կ ͕ ಘ Β Ε ͨ

    ͷ ͔
  9. ϧʔϧܾΊ

  10. σβΠφʔͱ૬ஊ ࢓༷ɾσβΠϯͷϧʔϧΛܾΊͨ ֓ ཁ

  11. จݴΛදࣔ͢Δ͚ͩʢ࠶ݕࡧ౳ͷػೳ͚ͭͳ͍ʣ $73Λ௥͍ͬͯͳ͍ γϯϓϧͳ࢓༷Ͱ0, ࢓ ༷

  12. දࣔ͢ΔཁૉʹରԠͨ͠จݴΛఆΊΔ ༧໿৘ใ ʮ༧໿৘ใ͸͋Γ·ͤΜʯ จ ݴ

  13. w ϑΥϯτͷαΠζɾΧϥʔΛ౷Ұ w 7JFXͷதԝʹϥϕϧΛ഑ஔ σ β Π ϯ

  14. ϧʔϧ͸FTBʹ·ͱΊͯνʔϜʹڞ༗ ʢશࣾһӾཡՄೳʣ ʢΤϯδχΞ޲͚ʹJ04࣮૷·ͱΊ΋هࡌʣ υ Ω ϡ ϝ ϯ τ Խ

  15. ࣮૷

  16. protocolͱenumΛ࢖ͬͯ ൚༻తʹར༻Ͱ͖ΔΑ͏ʹ࣮૷͢Δ ํ ਑

  17. FOVNͰදࣔཁૉΛදݱ ରԠ͢Δจݴ΋ఆٛ จ ݴ

  18. /// empty stateΛఆٛ͢Δenum enum EmptyState { /// ༧໿ case reservation

    /// ςʔϒϧ case table // ʢଞলུʣ /// λΠτϧ var title: String { switch self { case .reservation: return NSLocalizedString("key_of_reservation", comment: "") case .table: return NSLocalizedString("key_of_table", comment: “") // ʢଞলུʣ } } }
  19. QSJWBUFͰ࣮૷ ֎͔Β༨ܭͳૢ࡞ͤ͞ͳ͍ ݟͨ໨͕౷Ұ͞ΕΔ W J F X

  20. /// empty state༻ͷView private final class EmptyStateView: UIView { ///

    λΠτϧϥϕϧ private let titleLabel: UILabel = { let titleLabel = UILabel() // ϥϕϧͷઃఆ return titleLabel }() init(_ state: EmptyState) { super.init(frame: .zero) setup(with: state) } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } /// ηοτΞοϓΛ͢Δ private func setup(with state: EmptyState) { titleLabel.text = state.title addSubview(titleLabel) titleLabel.edges(equalTo: self) } }
  21. ֎͔Β͸͍ͭ͜Λ͍͡Δ &NQUZ4UBUF7JFXͱಉ͡ϑΝΠϧʹ࣮૷ ) P M E F S

  22. /// empty stateΛදࣔ͢ΔViewͷϗϧμʔ final class EmptyStateHolder { /// ຊϓϩύςΟܦ༝ͰviewͷisHiddenΛ֎͔Βηοτ͢Δ var

    isHidden = false { didSet { view.isHidden = isHidden } } /// empty stateΛදࣔ͢ΔView /// /// fileprivateʹͯ͠༨ܭͳPropertyΛϑΝΠϧ֎͔Βૢ࡞ͤ͞ͳ͍ /// ͱ͢Δ͜ͱͰݟͨ໨͕ΞϓϦ಺Ͱ౷Ұ͞ΕΔ͜ͱΛ୲อ fileprivate let view: EmptyStateView /// state͔Βࣗ਎Λੜ੒͢Δ /// 1ՕॴͰෳ਺λΠϓͷEmptyStateΛग़͢ཁ͕݅ͳ͍લఏͷ࣮૷ /// /// - Parameter state: EmptyState init(_ state: EmptyState) { view = EmptyStateView(state) } }
  23. ԼهΛࢀߟʹ&EHFʹର੍ͯ͠໿Λ͚ͭΔ 6*7JFXͷFYUFOTJPOΛ࣮૷ IUUQTTQFBLFSEFDLDPNLBNFJLFGBSFXFMMTOBQLJU ิ ଍ ɿ 7 J F X

    ͷ F Y U F O T J P O
  24. extension UIView { /// ࣗ਎ͷEdgeʹର੍ͯ͠໿Λ͚ͭΔ /// /// - Parameters: ///

    - view: ੍໿ͷج४ͱͳΔview /// - offset: ੍໿஋ (σϑΥϧτ஋: .zero ) func edges(equalTo view: UIView, offset: UIEdgeInsets = .zero) { translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ topAnchor.constraint(equalTo: view.topAnchor, constant: offset.top), bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -offset.bottom), leftAnchor.constraint(equalTo: view.leftAnchor, constant: offset.left), rightAnchor.constraint(equalTo: view.rightAnchor, constant: -offset.right) ]) } }
  25. ڞ௨Խ༻ͷQSPUPDPMΛ࡞੒ Q S P U P D P M

  26. // MARK: - ڞ௨Խ༻ϓϩτίϧ /// empty stateදࣔϓϩτίϧ protocol EmptyStateDisplayable where

    Self: UIResponder { /// empty stateΛදࣔ͢ΔViewͷϗϧμʔ var emptyStateHolder: EmptyStateHolder { get } /// emptyStateViewΛadd͢Δ func addEmptyStateView() }
  27. 6*7JFX$POUSPMMFSɾ6*7JFX ͦΕͧΕσϑΥϧτ࣮૷Λ௥Ճ ʢجຊˢΛݺͿ͚ͩʣ Q S P U P D P

    M  F Y U F O T J P O
  28. // MARK: - UIViewControllerͷ৔߹ extension EmptyStateDisplayable where Self: UIViewController {

    /// emptyStateViewΛviewʹaddSubview͢Δ func addEmptyStateView() { view.addSubview(emptyStateHolder.view) emptyStateHolder.view.edges(equalTo: view) } } // MARK: - UIViewͷ৔߹ extension EmptyStateDisplayable where Self: UIView { /// emptyStateViewΛࣗ਎ʹaddSubview͢Δ func addEmptyStateView() { addSubview(emptyStateHolder.view) emptyStateHolder.view.edges(equalTo: self) } }
  29. /// ར༻ଆͷ࣮૷ྫ /// EmptyStateDisplayableʹ४ڌͤ͞Δ final class SampleViewController: UIViewController, EmptyStateDisplayable {

    /// EmptyStateDisplayableͷϓϩύςΟ /// ରԠ͢ΔEmptyState(enum)͔ΒॳظԽ let emptyStateHolder = EmptyStateHolder(.reservation) override func viewDidLoad() { super.viewDidLoad() // EmptyStateDisplayableͷϝιουΛݺ΂͹EmptyStateView͕addSubView͞ΕΔ addEmptyStateView() // EmptyStateΛදࣔ͢Δ৚݅ʹ߹ΘͤͯemptyStateHolder.isHiddenʹ஋Ληοτ emptyStateHolder.isHidden = false } }
  30. &NQUZ4UBUFͰ͸ָΛͯ͠ ྗΛೖΕΔ΂͖ͱ͜Ζʹ ஫ྗͰ͖ΔΑ͏ʹͳΔͱϋοϐʔ