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
20190117_iOSLT_CBLinSwift.pdf
Search
shtnkgm
January 17, 2019
Programming
0
120
20190117_iOSLT_CBLinSwift.pdf
Code-Based Layout in Swift
shtnkgm
January 17, 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
iOSのコードベースレイアウト
shtnkgm
2
810
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
AIに任せる範囲を安全に広げるためにやっていること
fukucheee
0
150
ふつうのRubyist、ちいさなデバイス、大きな一年 / Ordinary Rubyists, Tiny Devices, Big Year
chobishiba
1
480
Ruby and LLM Ecosystem 2nd
koic
1
1.1k
[PHPerKaigi 2026]PHPerKaigi2025の企画CodeGolfが最高すぎて社内で内製して半年運営して得た内製と運営の知見
ikezoemakoto
0
210
仕様漏れ実装漏れをなくすトレーサビリティAI基盤のご紹介
orgachem
PRO
7
2.5k
それはエンジニアリングの糧である:AI開発のためにAIのOSSを開発する現場より / It serves as fuel for engineering: insights from the field of developing open-source AI for AI development.
nrslib
1
360
[SF Ruby Feb'26] The Silicon Heel
palkan
0
120
へんな働き方
yusukebe
5
2.7k
Linux Kernelの1文字のミスで 権限昇格ができた話
rqda
0
1.9k
ベクトル検索のフィルタを用いた機械学習モデルとの統合 / python-meetup-fukuoka-06-vector-attr
monochromegane
2
490
コーディングルールの鮮度を保ちたい / keep-fresh-go-internal-conventions
handlename
0
220
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
810
Featured
See All Featured
Mobile First: as difficult as doing things right
swwweet
225
10k
Visual Storytelling: How to be a Superhuman Communicator
reverentgeek
2
470
Lightning talk: Run Django tests with GitHub Actions
sabderemane
0
150
The Curious Case for Waylosing
cassininazir
0
270
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
10k
Building the Perfect Custom Keyboard
takai
2
710
Exploring the relationship between traditional SERPs and Gen AI search
raygrieselhuber
PRO
2
3.7k
Build your cross-platform service in a week with App Engine
jlugia
234
18k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
38
2.8k
Site-Speed That Sticks
csswizardry
13
1.1k
Into the Great Unknown - MozCon
thekraken
40
2.3k
WCS-LA-2024
lcolladotor
0
480
Transcript
CBL in Swift Shota Nakagami
Talking about "CBL"
!
CBL Code-Based layout
I ! Code-Based Layout
How to layout ? 4 StoryBoard 4 XIB 4 Code-BasedʢProgrammaticallyʣ
Storyboard & XIB features 4 Ease of use ☺ 4
Segue ☺ 4 Visual (multi device screen size) 4 Constraint Checker ☺ 4 Non-Reusable " 4 Hard to Resolve Conflict " 4 Hard to review (XML) "
Testable? ! class ViewController: UIViewController { let dependency: Dependency //
Dependency Injection with Initializer init(dependency: Dependency) { self.dependency = dependency } } 4 NG: Storyboard ☠ no initializer... 4 OK: XIB " 4 OK: CBL "
CBL features 4 Reusable ☺ 4 Speedy ☺ 4 Easy
to Resolve Conflict ☺ 4 Easy to Review ☺ 4 Cost of Learning " 4 Non-Visual "
StoryBoard XIB Codebased ! Segue ✅ # Visual ✅ ✅
$ Compiler Check ✅ ✅ % Testable (DI) ✅ ✅ ♻ Reusable ✅ ' Less Conflict ✅ ( Reviewable ✅
6 Tips for CBL
1. Initialization Closure 2. "Then" 3. Custom View Class 4.
lazy var 5. "SnapKit" 6. UIStackView
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... } }
messy viewDidLoad...
1. Initialization Closure
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... } }
viewDidLoad is clean, but...
class ViewController: UIViewController { let priceLabel: UILabel = { //
type annotation let label = UILabel() // renaming label.numberOfLines = 2 label.textColor = .red label.font = .boldSystemFont(ofSize: 14) return label // return }() let imageView: UIImageView = { // type annotation let view = UIImageView() // renaming view.contentMode = .scaleAspectFill view.clipsToBounds = true view.layer.cornerRadius = 4 return view // return }() override func viewDidLoad() { super.viewDidLoad() // addSubview, AutoLayout... } }
2. "Then" https://github.com/devxoul/Then
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... } }
3. Custom View Class
class ViewController: UIViewController { let priceLabel = PriceLabel() let imageView
= ItemImageView() override func viewDidLoad() { super.viewDidLoad() } }
private let captureButton = CaptureButton().then { $0.onTapped = { [weak
self] in self?.camera.capture() } }
private let captureButton = CaptureButton().then { $0.onTapped = { [weak
self] in // Compile Error self?.camera.capture() // Compile Error } }
4. lazy var
private lazy var captureButton = CaptureButton().then { $0.onTapped = {
[weak self] in self?.camera.capture() // OK } }
Codebased AutoLayout
NSLayoutAnchor ? // addSubview, AutoLayout... view.addSubview(button) 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
!
5. "SnapKit" https://github.com/SnapKit/SnapKit
view.addSubview(button) // 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 button.snp.makeConstraints { $0.edges.equalToSuperview() }
// readable button.snp.makeConstraints { $0.center.equalToSuperview() $0.size.equalTo(CGSize(width: 64, height: 64)) }
// Support Safe Area tableView.snp.makeConstraints { $0.top.bottom.equalTo(view.safeAreaLayoutGuide) $0.leading.trailing.equalToSuperview() }
6. UIStackView
UIStackView = Stack "Layouted" View Less Constraints ! stackView.addArrangedSubview(label) stackView.addArrangedSubview(imageView)
stackView.addArrangedSubview(button) label.snp.makeConstraints { $0.height.equalTo(20) } button.snp.makeConstraints { $0.height.equalTo(60) }
Summary
CBL: Code-Based layout 4 Testable, Speedy, and Reusable 4 Use
"6 Tips" to clean code When to Use 4 Use CBL for simple layout 4 Use XIB for complicated layout 4 Use StoryBoard for segue