Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Empty State表示共通化の事例 / Case of empty state commo...
Search
kentaro
December 18, 2018
Technology
3.9k
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Empty State表示共通化の事例 / Case of empty state commonization
potatotips #57の資料です。
https://potatotips.connpass.com/event/109263/
kentaro
December 18, 2018
Other Decks in Technology
See All in Technology
ハッカソンで入賞した話 @ Findy LT
asari194617
0
1.5k
トークンマネジメントでAIにとって働きやすい環境を実現する
hikaruegashira
0
140
三人寄ればチューリング完全
puhitaku
6
2.9k
コネクションをピン留めさせずに SELECTクエリのタイムアウトを設定した話
codmoninc
0
210
AIペネトレーションテスト・ セキュリティ検証「AgenticSec」紹介資料
laysakura
2
9.4k
【GCC2026】大規模言語モデルを活用した内製検索サービスの社内展開や業務活用
bandainamcostudios
PRO
0
520
RapidCopy2 Matrix I/Oエンジンによるファイルコピーソフトウェアの設計と実装
kengosawa2
1
300
20260817_生成AIの動向と中学校・高等学校での活用を考える_v1.00_公開用
doradora09
PRO
0
190
Sets in Go
ramalho
1
1.2k
AIコーディングの次。コードレビューと理解負荷を解消して組織の開発生産性を高める
moongift
PRO
2
2.7k
あなたの知らないバージョン命名規則
sat
PRO
2
180
AIのためのEthernet技術動向 (SerDes)
markunet
1
300
Featured
See All Featured
Embracing the Ebb and Flow
colly
88
5.1k
Optimising Largest Contentful Paint
csswizardry
37
3.9k
Context Engineering - Making Every Token Count
addyosmani
9
1.1k
More Than Pixels: Becoming A User Experience Designer
marktimemedia
3
500
Git: the NoSQL Database
bkeepers
PRO
432
67k
The Language of Interfaces
destraynor
162
27k
Gemini Prompt Engineering: Practical Techniques for Tangible AI Outcomes
mfonobong
2
490
The Hidden Cost of Media on the Web [PixelPalooza 2025]
tammyeverts
2
470
<Decoding/> the Language of Devs - We Love SEO 2024
nikkihalliwell
1
300
Unsuck your backbone
ammeep
672
58k
Redefining SEO in the New Era of Traffic Generation
szymonslowik
1
390
The SEO Collaboration Effect
kristinabergwall1
1
530
Transcript
&NQUZ4UBUFදࣔڞ௨Խͷࣄྫ QPUBUPUJQT,FOUBSP5BHVDIJ !LFOLFOLFO@
֓ཁ ϧʔϧܾΊ ࣮ʹ͍ͭͯ Ξ δ Σ ϯ
μ
֓ཁ
&NQUZ4UBUFͷදࣔΛ౷Ұͨ͠ Կ Λ ͠ ͨ ͷ ͔
ը໘࡞࣌ʹσβΠϯɾ࣮͞Ε͍ͯͨ ը໘ʹΑͬͯද͕ࣔόϥόϥ σβΠϯɾ࣮Λʮߟ͑Δʯ͕ൃੜ ͳ ͥ ͬ ͨ ͷ ͔
C F G P S F
B G U F S
w ΞϓϦͷ&NQUZ4UBUFද͕ࣔ౷Ұ͞Εͨ w ίετݮʢاըɾσβΠϯɾ࣮ʣ Կ ͕ ಘ Β Ε ͨ
ͷ ͔
ϧʔϧܾΊ
σβΠφʔͱ૬ஊ ༷ɾσβΠϯͷϧʔϧΛܾΊͨ ֓ ཁ
จݴΛදࣔ͢Δ͚ͩʢ࠶ݕࡧͷػೳ͚ͭͳ͍ʣ $73Λ͍ͬͯͳ͍ γϯϓϧͳ༷Ͱ0, ༷
දࣔ͢ΔཁૉʹରԠͨ͠จݴΛఆΊΔ ༧ใ ʮ༧ใ͋Γ·ͤΜʯ จ ݴ
w ϑΥϯτͷαΠζɾΧϥʔΛ౷Ұ w 7JFXͷதԝʹϥϕϧΛஔ σ β Π ϯ
ϧʔϧFTBʹ·ͱΊͯνʔϜʹڞ༗ ʢશࣾһӾཡՄೳʣ ʢΤϯδχΞ͚ʹJ04࣮·ͱΊهࡌʣ υ Ω ϡ ϝ ϯ τ Խ
࣮
protocolͱenumΛͬͯ ൚༻తʹར༻Ͱ͖ΔΑ͏ʹ࣮͢Δ ํ
FOVNͰදࣔཁૉΛදݱ ରԠ͢Δจݴఆٛ จ ݴ
/// 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: “") // ʢଞলུʣ } } }
QSJWBUFͰ࣮ ֎͔Β༨ܭͳૢ࡞ͤ͞ͳ͍ ݟ͕ͨ౷Ұ͞ΕΔ W J F X
/// 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) } }
֎͔Β͍ͭ͜Λ͍͡Δ &NQUZ4UBUF7JFXͱಉ͡ϑΝΠϧʹ࣮ ) P M E F S
/// 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) } }
ԼهΛࢀߟʹ&EHFʹର੍ͯ͠Λ͚ͭΔ 6*7JFXͷFYUFOTJPOΛ࣮ IUUQTTQFBLFSEFDLDPNLBNFJLFGBSFXFMMTOBQLJU ิ ɿ 7 J F X
ͷ F Y U F O T J P O
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) ]) } }
ڞ௨Խ༻ͷQSPUPDPMΛ࡞ Q S P U P D P M
// MARK: - ڞ௨Խ༻ϓϩτίϧ /// empty stateදࣔϓϩτίϧ protocol EmptyStateDisplayable where
Self: UIResponder { /// empty stateΛදࣔ͢ΔViewͷϗϧμʔ var emptyStateHolder: EmptyStateHolder { get } /// emptyStateViewΛadd͢Δ func addEmptyStateView() }
6*7JFX$POUSPMMFSɾ6*7JFX ͦΕͧΕσϑΥϧτ࣮ΛՃ ʢجຊˢΛݺͿ͚ͩʣ Q S P U P D P
M F Y U F O T J P O
// 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) } }
/// ར༻ଆͷ࣮ྫ /// 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 } }
&NQUZ4UBUFͰָΛͯ͠ ྗΛೖΕΔ͖ͱ͜Ζʹ ྗͰ͖ΔΑ͏ʹͳΔͱϋοϐʔ