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
iOSのコードベースレイアウト
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
shtnkgm
January 31, 2019
Programming
2
810
iOSのコードベースレイアウト
Mobile Act TOKYO #5
https://mobileact.connpass.com/event/114398
shtnkgm
January 31, 2019
Tweet
Share
More Decks by shtnkgm
See All by shtnkgm
Combine入門
shtnkgm
2
300
Property Wrappers
shtnkgm
0
370
Saliency Detection
shtnkgm
0
78
パフォーマンス改善とユニットテスト
shtnkgm
4
1.7k
20190117_iOSLT_CBLinSwift.pdf
shtnkgm
0
120
SwiftとFunctional Reactive Programming
shtnkgm
0
190
20180710_iOSLT_iOSでDarkModeを実装する
shtnkgm
0
110
20180410_iOSLT_SwiftとProtocol-OrientedProgramming
shtnkgm
0
130
20180220_iOSLT_Swiftとオブジェクト間の通知のパターン
shtnkgm
0
150
Other Decks in Programming
See All in Programming
What Spring Developers Should Know About Jakarta EE
ivargrimstad
0
470
AI時代の脳疲弊と向き合う ~言語学としてのPHP~
sakuraikotone
1
1.1k
AWS×クラウドネイティブソフトウェア設計 / AWS x Cloud-Native Software Design
nrslib
16
3.3k
Ruby and LLM Ecosystem 2nd
koic
1
1.1k
メッセージングを利用して時間的結合を分離しよう #phperkaigi
kajitack
2
110
Everything Claude Code OSS詳細 — 5層構造の中身と導入方法
targe
0
140
20260228_JAWS_Beginner_Kansai
takuyay0ne
5
600
Agentic AI: Evolution oder Revolution
mobilelarson
PRO
0
190
How to stabilize UI tests using XCTest
akkeylab
0
130
CSC307 Lecture 14
javiergs
PRO
0
480
go directiveを最新にしすぎないで欲しい話──あるいは、Go 1.26からgo mod initで作られるgo directiveの値が変わる話 / Go 1.26 リリースパーティ
arthur1
2
570
What Spring Developers Should Know About Jakarta EE
ivargrimstad
0
670
Featured
See All Featured
Statistics for Hackers
jakevdp
799
230k
The SEO Collaboration Effect
kristinabergwall1
0
400
HU Berlin: Industrial-Strength Natural Language Processing with spaCy and Prodigy
inesmontani
PRO
0
270
4 Signs Your Business is Dying
shpigford
187
22k
Documentation Writing (for coders)
carmenintech
77
5.3k
The AI Revolution Will Not Be Monopolized: How open-source beats economies of scale, even for LLMs
inesmontani
PRO
3
3.1k
Leo the Paperboy
mayatellez
4
1.5k
brightonSEO & MeasureFest 2025 - Christian Goodrich - Winning strategies for Black Friday CRO & PPC
cargoodrich
3
130
Java REST API Framework Comparison - PWX 2021
mraible
34
9.2k
Data-driven link building: lessons from a $708K investment (BrightonSEO talk)
szymonslowik
1
980
Claude Code どこまでも/ Claude Code Everywhere
nwiizo
64
53k
Measuring Dark Social's Impact On Conversion and Attribution
stephenakadiri
1
160
Transcript
iOSͷίʔυϕʔεϨΠΞτ Mobile Act TOKYO #5 @shtnkgm
iOS Engineer Shota Nakagami @shtnkgm
͢͜ͱ • iOSͷUIϨΠΞτख๏ͷൺֱ • ίʔυϕʔεϨΠΞτ Tips
UIͷϨΠΞτख๏ • ϓϩάϥϜͰهड़ʢίʔυϕʔεʣ • Storyboard • Interface BuilderʢXIBʣ
ͦΕͧΕͷಛ
StoryboardͱXIBͷಛ
ྑ͍ͱ͜Ζ • ෳͷը໘αΠζͰذɺݟ͑ํνΣοΫʢSize Classesʣ • Ϗϧυલʹ੩తͳ੍ͷݕࠪ • Storyboardͷ߹Segue͕͑Δ
ΠϚΠνͳͱ͜Ζ • ίϐϖɺΧελϜΫϥεԽͳͲͷ࠶ར༻ɾमਖ਼͕ͮ͠Β͍ • XMLͳͷͰίϯϑϦΫτͷղফɺίʔυϨϏϡʔ͕͍͠ • GUIͰΆͪΆͪ͠ͳ͍ͱԿ͕ઃఆͯ͋͠Δͷ͔ٯʹΘ͔Βͳ͍
ίʔυϕʔεϨΠΞτͷಛ
ྑ͍ͱ͜Ζ • ίϐϖίʔυஔͳͲͰεϐʔσΟʹ࠶ར༻ɾमਖ਼͕Մೳ • ίϯϑϦΫτͷղফϨϏϡʔ͕͍͢͠ • Կ͕ઃఆͯ͋͠Δͷ͔Ұཡੑ͕͋Δ
ΠϚΠνͳͱ͜Ζ • UIKitͷϓϩύςΟϥΠϑαΠΫϧʹؔ͢Δ͕ࣝඞཁ • ࣮ߦ͢Δ·Ͱݟ͑ํ૾
Dependency Injectionͷҧ͍
Storyboard // NG: ίϯετϥΫλΠϯδΣΫγϣϯෆՄ let viewController = ViewController(dependency: Dependency()) //
OK: ϓϩύςΟΠϯδΣΫγϣϯʹͳΒՄ let storyboard = UIStoryboard(name: "ViewController", bundle: nil) let viewController = storyboard.instantiateInitialViewController() viewController.dependency = Dependency()
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") } }
ൺֱ߲ Storyboard XIB ίʔυϕʔε ➡ Segue͕͑Δ ✅ # GUIͰݟͯΘ͔Δ ✅
✅ $ αΠζذ͕༰қ ✅ ✅ % ੩తνΣοΫ ✅ ✅ &ίϯετϥΫλDI ✅ ✅ ♻ ࠶ར༻ੑ ✅ ( ίϯϑϦΫτੑ ✅ ) ϨϏϡʔ͢͠͞ ✅
I ! Code-based Laout
ίʔυϕʔεϨΠΞτTipsʢ6ͭʣ
1. Initialization Closure
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... } }
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... } }
2. Then
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... } }
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... } }
Thenͷ࣮ public protocol Then {} extension Then where Self: AnyObject
{ public func then(_ block: (Self) throws -> Void) rethrows -> Self { try block(self) return self } }
3. ΧελϜΫϥε
ΧελϜΫϥεͰ࠶ར༻ੑΛߴΊɺΑΓγϯϓϧʹ class ViewController: UIViewController { let priceLabel = PriceLabel() //
ΧελϜΫϥεԽ let imageView = ItemImageView() // ΧελϜΫϥεԽ override func viewDidLoad() { super.viewDidLoad() // addSubview, AutoLayout... } }
4. lazy var
private let captureButton = CaptureButton().then { $0.onTapped = { [weak
self] in // selfࢀর͍ͨ͠ self?.camera.capture() // selfࢀর͍ͨ͠ } }
private let captureButton = CaptureButton().then { $0.onTapped = { [weak
self] in // ίϯύΠϧΤϥʔ self?.camera.capture() // ίϯύΠϧΤϥʔ } }
lazy varͰॳظԽԆɺselfΛࢀরՄʹ private lazy var captureButton = CaptureButton().then { $0.onTapped
= { [weak self] in self?.camera.capture() // OK } }
5. SnapKit / PureLayout
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
!
SnapKit / PureLayout // SnapKit button.snp.makeConstraints { $0.edges.equalToSuperview() } //
PureLaout button.autoPinEdgesToSuperviewEdges()
// ಡΈ͍͢ 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() // ࠨӈϏϡʔʹ }
☺
6. UIStackView
UIStackViewͰϨΠΞτ͢Δ stackView.addArrangedSubview(label) stackView.addArrangedSubview(imageView) stackView.addArrangedSubview(button) label.snp.makeConstraints { $0.height.equalTo(20) } button.snp.makeConstraints {
$0.height.equalTo(60) }
·ͱΊ • ίʔυϕʔεϨΠΞτͰTipsΛ͑؆͔ܿͭεϐʔσΟ • Ͳͷख๏Ͱ͖ΔΑ͏ʹ͓͖ͯ͠ɺ͍͚͍ͨ
αϯϓϧίʔυ github.com/shtnkgm/ iOSUILayoutMethods
͋Γ͕ͱ͏͍͟͝·ͨ͠ʂ