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
🤔 with IB/thinking_with_interface_builder
Search
fromkk
March 28, 2018
Programming
4
3.4k
🤔 with IB/thinking_with_interface_builder
2018/03/28にエウレカ様で開催されたAKIBA.swift × エウレカ コードレイアウト勉強会で発表した内容です。
fromkk
March 28, 2018
Tweet
Share
More Decks by fromkk
See All by fromkk
note社の全員野球で品質向上活動について / note_qa_challenge #iOS_test_teatime
fromkk
2
1.6k
1年分のデータが見たいと言われてやったこと/yearly_data_with_note
fromkk
0
790
note iOSチームの自動化 ver.2021/automation_with_iOS_team_on_note_ver2021
fromkk
0
1.8k
Bitrise体験会説明資料/bitrise_explore
fromkk
1
980
noteのiOSアプリで実装したアクセシビリティの全て #iosdc #a /a11y_with_iOS_App_on_note
fromkk
1
2.9k
dSYMのアップロードで SPMを活用する/use_spm_with_upload_dsyms
fromkk
1
2.4k
Bitriseのリモートアクセス機能 #bitrise_meetup/remote_access_of_bitrise
fromkk
1
480
note社でのMagic Pod活用事例 #af_iosdc/magicpod_with_note
fromkk
2
9.8k
iOSには無いmacOS独自機能をCatalystで実装する #iosdc #d/make_macos_apps_with_catalyst
fromkk
9
1.9k
Other Decks in Programming
See All in Programming
スキーマ駆動開発による品質とスピードの両立 - 私達は何故、スキーマを書くのか
kentaroutakeda
0
170
大規模UIKitベースアプリへのTCAの段階的導入/gradual-adoption-of-tca-in-a-large-scale-uikit-based-app
takehilo
1
140
PostmanでAPIの動作確認が楽になった話
h455h1
0
170
"config" ってなんだ? / What is "config"?
okashoi
0
240
Tailwind CSSを本気でカスタマイズする方法
fsubal
13
5.2k
新宿ダンジョンを可視化してみた
satoshi7190
2
250
What We Can Learn From OSS
inouehi
0
420
try!Swift Tokyo 2024 参加報告 LT
akidon0000
1
220
2 週間で Twitter Bot を作ってみた
contour_gara
0
360
Milestoner
bkuhlmann
1
410
GraphQLサーバの構成要素を整理する #ハッカー鮨 #tsukijigraphql / graphql server technology selection
izumin5210
4
830
スクラムガイドのスプリントレトロスペクティブを改めて読みかえしてみた / Re-reading the Sprint Retrospective Section in the Scrum Guide
mackey0225
3
410
Featured
See All Featured
A Philosophy of Restraint
colly
197
16k
Side Projects
sachag
451
41k
Designing for humans not robots
tammielis
248
25k
A Tale of Four Properties
chriscoyier
151
22k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
501
140k
Building Applications with DynamoDB
mza
88
5.6k
Building Adaptive Systems
keathley
31
1.9k
The Illustrated Children's Guide to Kubernetes
chrisshort
31
46k
Keith and Marios Guide to Fast Websites
keithpitt
408
22k
Code Reviewing Like a Champion
maltzj
514
39k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
241
1.2M
Put a Button on it: Removing Barriers to Going Fast.
kastner
58
3k
Transcript
! with IB AKIBA.swift × ΤϨΧ ίʔυϨΠΞτษڧձ 1
Who is me? Kazuya Ueoka iOS application engineer in Timers
inc. Twitter: @fromkk Github: fromkk Qiita: fromkk 2
Interface Builder͋Δ͋Δ 3
Q. IBͷϑΝΠϧͱίʔυ͕ผʑͷσΟϨΫτϦʹ͍Δʁ 4
A. ಉ͡σΟϨΫτϦʹอଘ͠·͠ΐ͏ 5
Q. IB্Ͱमਖ਼ͨͣ͠ͳͷʹมߋ͕ө͞Εͳ͍? 6
A. IBͷϑΝΠϧΛमਖ਼͢ΔͷΛΊ·͠ΐ͏ جຊతʹίʔυͷมߋ͕ޙউͪ 7
Q. IBOutletআͯ͠͠·ͬͯམͪͨࣄແ͍ʁ *** Terminating app due to uncaught exception 'NSUnknownKeyException',
reason: '[<SampleWithoutIB.ViewController 0x7fe8d4e0a880> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key sampleLabel. 8
A. IB͔Β֬ೝग़དྷΔ • ! ʹͳͬͯΔ࣌ඥ͚͕͏·͍ͬͯ͘ͳ͍ • ϑΝΠϧͷཧ͕2Օॴʹͳͬͯ͠·͏ͷେม 9
Q. Πϯελϯε࡞Δ࣌ʹinitͨ͠Βམͪͨࣄແ͍ʁ 10
A. Extension࡞͙ͬͯ import UIKit protocol NibInstantiatable: class { static var
nibName: String { get } } extension NibInstantiatable where Self: UIView { static func instantiate(bundle: Bundle = Bundle.main, owner: Any? = nil, options: [AnyHashable: Any]? = nil) -> Self { return UINib(nibName: Self.nibName, bundle: bundle).instantiate(withOwner: owner, options: options).first as! Self } } protocol StoryboardInstantiatable: class { static var storyboardName: String { get } static var storyboardIdentifier: String { get } } extension StoryboardInstantiatable where Self: UIViewController { static func instantiate(bundle: Bundle = Bundle.main, identifier: String) -> Self { return UIStoryboard(name: Self.storyboardName, bundle: bundle).instantiateViewController(withIdentifier: Self.storyboardIdentifier) as! Self } } 11
Usage class HogeView: UIView, NibInstantiatable { static var nibName: String
{ return "nibName" } } let hogeView = HogeView.instantiate() 12
Q. IBϑΝΠϧͷϩʔΧϥΠζ໘ष͘ͳ͍ʁ 13
A. ༁ʹؔ͢ΔࣄLocalizable.stringʹू ࣗવͱ༁ίʔυͰରԠ͢Δࣄʹ @IBOutlet weak var sampleLabel: UILabel! { didSet
{ sampleLabel.text = NSLocalizedString("sample.label.text", comment: "ϥϕϧ") } } 14
Q. ৭ϑΥϯτΛڞ௨Ͱཧग़དྷͳ͍ 15
A. ίʔυͰ·ͱΊ͓͖ͯ·͠ΐ͏ • ਖ਼֬ʹ৭ʹؔͯ͠Xcode 9/iOS 11͔ΒColor Asset ར༻Մೳʹͳͬͨ • ԼҐޓੑΛߟ͑Δͱ·ͩ͑ͳ͍
16
৭ΛίʔυͰཧ͢Δ extension UIColor { struct MyColor { static let theme:
UIColor = #colorLiteral(red: 0.2, green: 0.2, blue: 0.2, alpha: 1) static let action: UIColor = #colorLiteral(red: 0.4, green: 0.4, blue: 0.4, alpha: 1) static let backgroundColor: UIColor = #colorLiteral(red: 0.8, green: 0.8, blue: 0.8, alpha: 1) . . . } } 17
ϑΥϯτΛίʔυͰཧ͢Δ extension UIFont { struct MyFont { private static func
font(with name: String, size: CGFloat) -> UIFont { let font = UIFont(name: name, size: size)! guard #available(iOS 11.0, *) else { return font } return UIFontMetrics.default.scaledFont(for: font) } private static func normal(with size: CGFloat) -> UIFont { return font(with: "Awesome-Font", size: size) } private static func bold(with size: CGFloat) -> UIFont { return font(with: "Awesome-Font-Bold", size: size) } static let largeTitle: UIFont = MyFont.normal(with: 34.0) static let title1: UIFont = MyFont.normal(with: 28.0) static let title2: UIFont = MyFont.normal(with: 22.0) static let title3: UIFont = MyFont.normal(with: 20.0) static let headline: UIFont = MyFont.bold(with: 17.0) static let body: UIFont = MyFont.normal(with: 17.0) static let callout: UIFont = MyFont.normal(with: 16.0) static let subheadline: UIFont = MyFont.normal(with: 15.0) static let footnote: UIFont = MyFont.normal(with: 13.0) static let caption1: UIFont = MyFont.normal(with: 12.0) static let caption2: UIFont = MyFont.normal(with: 11.0) } } 18
ଞʹ • ϑΝΠϧΛ։͍͚ͨͩͰDiff͕ൃੜͯ͠͠·͏ • PRͷ࣌ʹϨϏϡʔ͕͍͠ • Ϗϧυͯ͠ΈΔͱ৭͕ҧ͏ • etc... 19
Q. ن(ϧʔϧ)Ͱ͍͍͛ʁ 20
A. ͦͦϧʔϧগͳ͍ํ͕ྑ͍ 21
ϧʔϧഁΒΕΔҝʹ͋Δ • ਓ͕ൈ͚ͨΓೖͬͨΓͯ͠อͯΔʁ • IBͰAutoLayoutͷઃఆ͔͠͠ͳ͍ʁ • ϥϕϧͷ৭ϑΥϯτίʔυͰઃఆ͢ΔʁIBͷํָ͕͡Ό ͳ͍ʁ • ͦͷ࣌ʑͰָͳํ๏ΛબΜͩΓͯ͠ͳ͍ʁ
22
IB͑͞Θͳ͚Εߟ͑ΔࣄݮΔͷͰ 23
Interface BuilderࣺͯΑ͏ 24
1. AutoLayoutΛίʔυͰॻ͘ let sampleLabel = UILabel() sampleLabel.translatesAutoresizingMaskIntoConstraints = false view.addSubview(sampleLabel)
NSLayoutConstraint.activate([ sampleLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16.0), sampleLabel.topAnchor.constraint(equalTo: view.topAnchor, constant: 8.0), view.trailingAnchor.constraint(equalTo: sampleLabel.trailingAnchor, constant: 16.0), view.bottomAnchor.constraint(equalTo: sampleLabel.bottomAnchor, constant: 8.0) ]) 25
σϝϦοτ͋Δ 26
Q.translatesAutoresizingMaskIntoConstraints Λॻ͖ΕΔ 27
A. ബ͍ϥούʔ࡞Ζ͏ // ఆٛ extension UIView { func addSubview(_ view:
UIView, with layouts: (UIView) -> ([NSLayoutConstraint])) { view.translatesAutoresizingMaskIntoConstraints = false addSubview(view) NSLayoutConstraint.activate(layouts(view)) } } // ༻ addSubview(sampleLabel) { label -> [NSLayoutConstraint] in [ label.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16.0), label.topAnchor.constraint(equalTo: topAnchor, constant: 8.0), trailingAnchor.constraint(equalTo: label.trailingAnchor, constant: 16.0), bottomAnchor.constraint(equalTo: label.bottomAnchor, constant: 8.0) ] } 28
Q. SafeAreaਏ͍ let top: NSLayoutConstraint if #available(iOS 11.0, *) {
top = button.topAnchor.constraint(equalTop: view.safeAreaLayoutGuide.topAnchor, constant: 16.0) } else { top = button.topAnchor.constraint(equalTop: view.topAnchor, constant: 16.0) } NSLayoutConstraint.activate([ top, button.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16.0), button.widthAnchor.constraint(equalToConstant: 200.0), button.heightAnchor.constraint(equalToConstant: 48.0), ]) 29
A. ബ͍ϥούʔ࡞Ζ͏ extension UIView { struct MySafeAreaLayoutGuide { weak var
view: UIView! var topAnchor: NSLayoutYAxisAnchor { if #available(iOS 11.0, *) { return view.safeAreaLayoutGuide.topAnchor } else { return view.topAnchor } } var bottomAnchor: NSLayoutYAxisAnchor { if #available(iOS 11.0, *) { return view.safeAreaLayoutGuide.bottomAnchor } else { return view.bottomAnchor } } . . . } var myLayoutGuide: MySafeAreaLayoutGuide { return MySafeAreaLayoutGuide(view: self) } } 30
Usage NSLayoutConstraint.activate([ button.topAnchor.constraint(equalTo: view.myLayoutGuide.topAnchor), . . . ]) iOS 11ະຬΛΔ࣌ʹ
myLayoutGuide Λ safeAreaLayoutGuide ʹஔ͢Δ͚ͩͰࡁΉͷͰָ 31
Q. ϨΠΞτΛίʔυͰॻ͍͍ͯΔͱ Ͳͷը໘͔Θ͔Βͳ͘ͳͬͯ͠·͏ 32
A. ίʔυʹը໘֓ཁਤͤͯ͠·͏ 33
Diff͔Γ͍͢ 34
·ͱΊ 1.ϧʔϧΛݮΒ͢ҝʹIBࣺͯͯ͠·͍·͠ΐ͏ 2.AutoLayoutബ͍ϥούʔΛ࡞ͬͯίʔυͰॻ͘ 3.Ͳͷը໘͔͔ΓͮΒ͘ͳΔ࣌ίϝϯτΛۦ͢Δ 35
PR 1 36
37
38
39
PR 2 40
https://pre-wwdc.connpass.com/event/83343/ 41
͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠ 42