Slide 1

Slide 1 text

ϨΠΞ΢ταΠΫϧΛ ஌Ζ͏ forαϙʔλʔζ$P-BCษڧձ K15؊

Slide 2

Slide 2 text

var employedBy = "YUMEMI Inc." var job = "iOS Developer" var favoriteLanguage = "Swift" var twitter = "@lovee" var qiita = "lovee" var github = "el-hoshino" var additionalInfo = """ ࣗশ Auto Layout ઈରࡴ͢ϚϯͰ͢ """ class Me: Developable, Talkable { }

Slide 3

Slide 3 text

J04ʢ6*,JUʣͷϨΠΞ΢ταΠΫϧ͸ͲͷΑ͏ʹಈ͍ͯΔ͔ ͲͷλΠϛϯάͰϨΠΞ΢τΛ૊Έͳ͓͢΂͖͔ "VUP-BZPVUͰϨΠΞ΢τΛ૊Ή࣌ͱίʔυͰϨΠΞ΢τ૊ Ή࣌ʹͦΕͧΕԿΛؾΛ͚ͭΔ΂͖͔ /PU"VUP-BZPVUͷ͍ܰએ఻ʢΛ͍ͤͯͩ͘͞͞Xʣ ࠓ೔࿩͢͜ͱ

Slide 4

Slide 4 text

͜ͷϨΠΞ΢τ͸۩ମతʹͲͷΑ͏ʹ૊ΜͰ͍Δͷ͔ έʔεόΠέʔε͗͢ΔͷͰΧόʔ͢Δͷ͸ແཧ Ͱ΋ฉ͖͍ͨͷ͋Ε͹࣭ٙԠ౴΍࠙਌ձͷ࣌ʹରԠ͍ͨ͠ "VUP-BZPVUͷ࢓૊Έ ڵຯ͋ͬͯ਺ֶಘҙͳϑϨϯζ͸ੋඇҴݟ͞ΜͷൃදΛ
 IUUQTXXXZPVUVCFDPNXBUDI W5)0OTZ%,&:2UT ࠓ೔࿩͞ͳ͍͜ͱ

Slide 5

Slide 5 text

ੲͷ iPhone ͸ղ૾౓͕ 1 छྨ͔͠ͳ͘ɺ
 ը໘ϨΠΞ΢τ͕ͱͯ΋؆୯ͩͬͨɻ

Slide 6

Slide 6 text

UIView ͷੜ੒࣌ʹ௚઀ frame Λࢦఆ͠ɺ
 ϨΠΞ΢τͷมԽߟ͑ͳͯ͘΋Α͔ͬͨɻ ը໘ճస͕ແޮͳΒ let view = UIView(frame: CGRect(x: 0, ɹɹy: 0, ɹɹwidth: 320, ɹɹheight: 480)) Swiftɿ UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)]; Objective-Cɿ

Slide 7

Slide 7 text

్த͔Βը໘छྨ͕૿͑ɺ
 ϨΠΞ΢τ͕໘౗ʹͳΓ࢝Ίͨɻ

Slide 8

Slide 8 text

ࠓ͸छྨ͕ଟ͗ͯ͢ɺ
 ΋͸΍ԿΛͲ͏͢Ε͹͍͍͔… ?

Slide 9

Slide 9 text

ϨΠΞ΢τ
 αΠΫϧ

Slide 10

Slide 10 text

ϨΠΞ΢τ͸ίετ͕ߴ͍ʢॏ͍ʣ ͳΔ΂͘ϨΠΞ΢τΛඞཁͳ࣌ʹඞཁ࠷௿ݶ͚ͩߦ͍͍ͨ ҙਤ͠ͳ͍৔ॴͰ࠶ϨΠΞ΢τΛىͤͨ͘͜͞ͳ͍ ϨΠΞ΢τΛࢥ͏Ͳ͓Γʹ࣮ݱ͢Δͷʹඞཁ ϨΠΞ΢τઃఆͯ͠Δ͚ͲɺαΠΫϧ͕ճΒͳ͔͍ͬͨͤ Ͱݟͨ໨͕૝ఆͱҧ͏͜ͱΛ๷͍͗ͨ ͳͥϨΠΞ΢ταΠΫϧ͕ॏཁ͔

Slide 11

Slide 11 text

UIViewController UIView viewDidDisappear() viewWillDisappear() layout runloop viewDidAppear() viewDidLayoutSubviews() layoutSubviews() viewWillLayoutSubviews() viewWillAppear() viewDidLoad() loadView()

Slide 12

Slide 12 text

UIViewController UIView Needs layout? viewDidLayoutSubviews() layoutSubviews() updateViewConstraints() updateConstraints() yes no Needs update constraint? viewWillLayoutSubviews() yes sleep no Needs layout? no yes Disappear? viewDidDisappear() viewWillDisappear() layout runloop viewDidAppear() viewDidLayoutSubviews() layoutSubviews() viewWillLayoutSubviews() viewWillAppear() viewDidLoad() loadView()

Slide 13

Slide 13 text

setNeedsLayout() Λݺͼग़ͨ͠ σόΠε͕ճసͨ͠ ࢠϏϡʔΛ௥Ճ΍࡟আΛͨ͠ ࣗ෼ͷϏϡʔ֊૚಺ͷ੍໿͕ߋ৽ͨ͠ ʢUIScrollView Ͱ͋ΔࢠϏϡʔʣ͕εΫϩʔϧͨ͠ ࣗ෼ͷࢠϏϡʔͷ frame ΍ transform ͳͲ͕มߋ͞Εͨ ͳͲͳͲ… ͸Ͳ͏΍ͬͯ൑ఆ͍ͯ͠Δͷ͔ʁ Needs layout?

Slide 14

Slide 14 text

setNeedsLayout() Λݺͼग़ͨ͠ σόΠε͕ճసͨ͠ ࢠϏϡʔΛ௥Ճ΍࡟আΛͨ͠ ࣗ෼ͷϏϡʔ֊૚಺ͷ੍໿͕ߋ৽ͨ͠ ʢUIScrollView Ͱ͋ΔࢠϏϡʔʣ͕εΫϩʔϧͨ͠ ࣗ෼ͷࢠϏϡʔͷ frame ΍ transform ͳͲ͕มߋ͞Εͨ ͳͲͳͲ… ͸Ͳ͏΍ͬͯ൑ఆ͍ͯ͠Δͷ͔ʁ Needs layout? ࣗ෼ͷ frame ΍ transform ͸
 ඞͣ਌ʹมߋͯ͠΋Β͓͏ʂ ࣗ෼ͷ frame ΍ transform Λมߋ͢Ε͹
 ਌ͷ layoutSubviews() ΋ݺ͹ΕΔʂ

Slide 15

Slide 15 text

setNeedsLayout() Λݺͼग़ͨ͠ σόΠε͕ճసͨ͠ ࢠϏϡʔΛ௥Ճ΍࡟আΛͨ͠ ࣗ෼ͷϏϡʔ֊૚಺ͷ੍໿͕ߋ৽ͨ͠ ʢUIScrollView Ͱ͋ΔࢠϏϡʔʣ͕εΫϩʔϧͨ͠ ࣗ෼ͷࢠϏϡʔͷ frame ΍ transform ͳͲ͕มߋ͞Εͨ ͳͲͳͲ… ͸Ͳ͏΍ͬͯ൑ఆ͍ͯ͠Δͷ͔ʁ Needs layout? ࠶ϨΠΞ΢τ͸ setNeedsLayout ͷ
 ௚ޙͰ͸ͳ͘ɺ࣍ͷϥϯϧʔϓ ϨΠΞ΢τ͸ίετ͕ߴ͍ ΋͘͠͸ layoutIfNeeded ݺͼग़࣌͠

Slide 16

Slide 16 text

Ͳ͏ϨΠΞ΢τ ͢Ε͹͍͍͔

Slide 17

Slide 17 text

جຊUIViewͷlayoutSubviewsΛΦʔόʔϥΠυ͠ɺͦ ͷத਎ͰϨΠΞ΢τ͢Ε͹͍͍ ϏϡʔͷframeϓϩύςΟʔ͸ɺ਌͕؅ཧ͢΂͖ ಺༰ʹԠͯ͡αΠζ͕มΘΔϏϡʔ͸ɺsizeThatFitsͰ
 ͳΜͱ͔ͳΔ label.frame.size = label.sizeThatFits(bounds.size) ඞཁʹԠͯ͡ΦʔόʔϥΠυ΋Մ ࠶౓ϨΠΞ΢τ͕ඞཁʹͳͬͨΒsetNeedsLayoutΛݺͿ ϨΠΞ΢τ͕ඞཁͱ͍͏ϑϥάཱ͕͚ͭͩͳͷͰɺҰ౓ͷ ॲཧʹෳ਺ճݺΜͰ΋ϨΠΞ΢τ͸ޙͰҰճ͚ͩճΔ ίʔυʢ"VUP-BZPVUͳ͠ʣͰ૊Ή৔߹

Slide 18

Slide 18 text

ίʔυʢ"VUP-BZPVUͳ͠ʣͰ૊Ή৔߹ class ViewController: UIViewController { lazy var myView = View(frame: UIScreen.main.bounds) override func loadView() { self.view = self.myView } override func viewDidLoad() { super.viewDidLoad() self.myView.button.addTarget(self, action: #selector(self.switchButtonSize), for: .touchUpInside) } @objc func switchButtonSize() { self.myView.showsLargeButton = !self.myView.showsLargeButton self.view.setNeedsLayout() } } class View: UIView { let button = UIButton() var showsLargeButton = false override func layoutSubviews() { if showsLargeButton { self.button.frame = self.bounds } else { self.button.frame.size = .init(width: 100, height: 100) self.button.frame.origin = .zero } } }

Slide 19

Slide 19 text

ίʔυʢ"VUP-BZPVUͳ͠ʣͰ૊Ή৔߹ class ViewController: UIViewController { lazy var myView = View(frame: UIScreen.main.bounds) override func loadView() { self.view = self.myView } override func viewDidLoad() { super.viewDidLoad() self.myView.button.addTarget(self, action: #selector(self.switchButtonSize), for: .touchUpInside) } @objc func switchButtonSize() { self.myView.showsLargeButton = !self.myView.showsLargeButton self.view.setNeedsLayout() } } class View: UIView { let button = UIButton() var showsLargeButton = false override func layoutSubviews() { if showsLargeButton { self.button.frame = self.bounds } else { self.button.frame.size = .init(width: 100, height: 100) self.button.frame.origin = .zero } } }

Slide 20

Slide 20 text

"VUP-BZPVUͰ૊Ή৔߹ class ViewController: UIViewController { lazy var button: UIButton = { let button = UIButton() button.translatesAutoresizingMaskIntoConstraints = false button.addTarget(self, action: #selector(self.switchButtonSize), for: .touchUpInside) return button }() var showsLargeButton = false lazy var top = button.topAnchor.constraint(equalTo: view.topAnchor) lazy var left = button.leftAnchor.constraint(equalTo: view.leftAnchor) lazy var bottom = button.bottomAnchor.constraint(equalTo: view.bottomAnchor) lazy var right = button.rightAnchor.constraint(equalTo: view.rightAnchor) lazy var width = button.widthAnchor.constraint(equalToConstant: 100) lazy var height = button.heightAnchor.constraint(equalToConstant: 100) override func viewDidLoad() { super.viewDidLoad() self.view.addSubview(button) self.view.setNeedsUpdateConstraints() } override func updateViewConstraints() { self.updateButtonConstraints() super.updateViewConstraints() } @objc func switchButtonSize() { self.showsLargeButton = !self.showsLargeButton self.updateButtonConstraints() } func updateButtonConstraints() { top.isActive = true left.isActive = true if showsLargeButton { bottom.isActive = true right.isActive = true width.isActive = false height.isActive = false } else { bottom.isActive = false right.isActive = false width.isActive = true height.isActive = true } } }

Slide 21

Slide 21 text

"VUP-BZPVUͰ૊Ή৔߹ @objc func switchButtonSize() { self.showsLargeButton = !self.showsLargeButton self.updateButtonConstraints() } func updateButtonConstraints() { top.isActive = true left.isActive = true if showsLargeButton { bottom.isActive = true right.isActive = true width.isActive = false height.isActive = false } else { bottom.isActive = false right.isActive = false width.isActive = true height.isActive = true } }

Slide 22

Slide 22 text

ϨΠΞ΢τʢʹݶΒͣ6*ܥશൠʣ͸ϝΠϯεϨουͰʂ ϨΠΞ΢ταΠΫϧ಺ͰϨΠΞ΢τҾ͖ى͜͞ͳ͍ setNeedsLayout΍setNeedsUpdateConstraintsΛ ݺ͹ͳ͍ ϨΠΞ΢ταΠΫϧͷݺͼग़͠ΛͳΔ΂͘࠷খݶʹ ࢠϏϡʔͷ௥Ճ͸ͳΔ΂͘viewDidLoad͔ viewWillLayoutSubviews಺ʹ layoutIfNeededΛΉ΍Έʹݺ͹ͳ͍ ຊ౰ʹඞཁͳ͚࣌ͩݺͿ ஫ҙ఺ʢڞ௨ʣ ΞχϝʔγϣϯϒϩοΫͱ͔

Slide 23

Slide 23 text

sizeThatFitsΛ͏·͘׆༻͠ɺϨΠΞ΢τॲཧΛ࠷খݶʹ ཈͑Δ sizeThatFitsͷΦʔόʔϥΠυ͢Δ࣌ʹɺத਎ͰͳΔ΂͘ ϨΠΞ΢τॲཧͤ͞ͳ͍ ࣗ෼ࣗ਎Ͱࣗ෼ࣗ਎ͷframe౳Λมߋ͠ͳ͍ʂ ஫ҙ఺ʢίʔυʣ

Slide 24

Slide 24 text

Ϗϡʔؔ܎Λ͏·͘׆༻੍ͯ͠໿Λ૊Ή ؔ܎ੑΛਖ਼͘͠ઃఆͰ͖ͯΕ͹setNeedsLayout(); layoutIfNeeded()ͷίϯϘ͸ཁΒͳ͍͸ͣʂ ੍໿ͷߋ৽ස౓ΛͳΔ΂͘࠷খݶʹ ՄೳͳݶΓ੍໿Λ౎౓ੜ੒ʗ࡟আ͢ΔͷͰͳ͘ɺಉ੍͡໿ Λྲྀ༻͠constantsΛมߋ͢Δ͔ɺ੍໿ΛisActiveͰ ੾Γସ͑Δ isActiveͰ੾Γସ͑Δ৔߹͸੍໿ͷอ࣋ʹ஫ҙ ίϯςϯπʹԠͨ͡αΠζઃఆ͸intrinsicContentSize ΛΦʔόʔϥΠυ ஫ҙ఺ʢ"VUP-BZPVUʣ

Slide 25

Slide 25 text

એ఻

Slide 26

Slide 26 text

/PU"VUP-BZPVUઈࢍެ։த IUUQTHJUIVCDPNFMIPTIJOP/PU"VUP-BZPVU

Slide 27

Slide 27 text

ίʔυʢ/PU"VUP-BZPVUʣͰ૊Ή৔߹ class ViewController: UIViewController { lazy var myView = View(frame: UIScreen.main.bounds) override func loadView() { self.view = self.myView } override func viewDidLoad() { super.viewDidLoad() self.myView.button.addTarget(self, action: #selector(self.switchButtonSize), for: .touchUpInside) } @objc func switchButtonSize() { self.myView.showsLargeButton = !self.myView.showsLargeButton self.view.setNeedsLayout() } } class View: UIView { let button = UIButton() var showsLargeButton = false override func layoutSubviews() { if showsLargeButton { self.nal.layout(button, by: { $0.stickOnParent() }) } else { self.nal.layout(button, by: { $0 .setTopLeft(by: { $0.topLeft }) .setSize(to: .init(width: 100, height: 100)) }) } } }

Slide 28

Slide 28 text

J04ΞϓϦઃܭύλʔϯೖ໳ࣥචܾఆ IUUQTQFBLTDDJ04@BSDIJUFDUVSF

Slide 29

Slide 29 text

גࣜձࣾΏΊΈɺΤϯδχΞืूத IUUQTXXXZVNFNJDPKQKBQBHFSFDSVJU