<h1><center> setNeedsLayout vs layoutIfNeeded </center></h1> ###### tags: `๐Ÿ’ป TIL` ###### date: `2024-01-30T15:12:33.284Z` > [color=#724cd1][name=๋ฐ๋ฆญ] > [Corn ๋ธ”๋กœ๊ทธ - setNeedsLayout vs layoutIfNeeded](https://baked-corn.tistory.com/105) > [Demystifying iOS Layout](https://tech.gc.com/demystifying-ios-layout/) > [layoutSubviews() - Apple Documentation](https://developer.apple.com/documentation/uikit/uiview/1622482-layoutsubviews) > [setNeedsLayout() - Apple Documentation](https://developer.apple.com/documentation/uikit/uiview/1622601-setneedslayout) > [layoutIfNeeded() - Apple Documentation](https://developer.apple.com/documentation/uikit/uiview/1622507-layoutifneeded) # ๊ฐœ์š” > ์ตœ๊ทผ์— ํ•œ ํ”„๋กœ์ ํŠธ์—์„œ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์ค„ ๋•Œ ์ œ๋Œ€๋กœ ์•Œ์ง€ ๋ชปํ•˜๊ณ  setNeedsLayout์„ ์‚ฌ์šฉํ•ด์„œ ๋ทฐ๋ฅผ ์—…๋ฐ์ดํŠธ ํ•ด๋ณธ ์ ์ด ์žˆ๋‹ค. ๊ทธ ๋•Œ ์ œ๋Œ€๋กœ ์•Œ์ง€ ๋ชปํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ง€๊ธˆ ํ•™์Šตํ•˜๊ณ ์ž ํ•œ๋‹ค. ์ผ๋‹จ ๋‘ ๊ฐœ์˜ ๋ฉ”์„œ๋“œ๋ฅผ ๋น„๊ตํ•˜๊ธฐ์— ์•ž์„œ `main run loop` ๊ฐœ๋…์— ๋Œ€ํ•ด ์•Œ์•„์•ผ ํ•œ๋‹ค. [Run Loop](https://hackmd.io/tev-lJIOTN6IMcRqYT4qyw)๋Š” ์—ฌ๊ธฐ์„œ ํ™•์ธํ•˜์ž. ## Main Run Loop Main Thread์—์„œ๋Š” ์•ฑ ์‹œ์ž‘ ๊ณผ์ •(UIApplication) ์ค‘์— ์ž๋™์œผ๋กœ Run Loop๊ฐ€ ์‹คํ–‰๋œ๋‹ค. Main Run Loop๋Š” ํ„ฐ์น˜ ์ด๋ฒคํŠธ, ์œ„์น˜ ๋ณ€ํ™”, ๋””๋ฐ”์ด์Šค ํšŒ์ „, ํƒ€์ด๋จธ ๋“ฑ์˜ ์ด๋ฒคํŠธ๋“ค์„ ์ฒ˜๋ฆฌํ•˜๊ฒŒ ๋œ๋‹ค. ์ด๋Ÿฐ ์ฒ˜๋ฆฌ ๊ณผ์ •์€ ๊ฐ ์ด๋ฒคํŠธ์— ์ ์ ˆํ•œ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์ฐพ์•„ ์ฒ˜๋ฆฌ ๊ถŒํ•œ์„ ์œ„์ž„ํ•ด์„œ ์ง„ํ–‰ํ•˜๊ฒŒ ๋œ๋‹ค. Main Run Loop์—์„œ ์ด๋ฒคํŠธ๊ฐ€ ์ฒ˜๋ฆฌ๋˜๋Š” ๊ณผ์ •์—์„œ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๊ฑฐ๋‚˜ ํฌ๊ธฐ, ์œ„์น˜๊ฐ€ ์ด๋™ํ•˜๋Š” ์• ๋‹ˆ๋ฉ”์ด์…˜ ์‹คํ–‰์œผ๋กœ position์˜ ๊ฐ’์„ ๋ฐ”๊พธ๋Š” ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ์‹คํ–‰๋  ๋•Œ๋„ ์žˆ๋‹ค. **ํ•˜์ง€๋งŒ** ์ด๋Ÿฐ ๋ณ€ํ™”๋Š” ์ฆ‰๊ฐ์ ์œผ๋กœ ๋ฐ˜์˜๋˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋‹ค. System์€ layout or position์ด ๋ฐ”๋€Œ๋Š” ๋ทฐ๋ฅผ ์ฒดํฌํ•œ๋‹ค. ๋ทฐ๊ฐ€ ๊ฐฑ์‹ ๋˜๋Š” ์‹œ์ ์€ ๋ชจ๋“  ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ์ข…๋ฃŒ๋˜๊ณ  Main Run Loop๋กœ ๊ถŒํ•œ์ด ๋˜๋Œ์•„ ์˜ค๋Š” ์‹œ์ ์ธ Update Cycle์—์„œ ๋œ๋‹ค.(Position, layout์˜ ๋ณ€ํ™”๋ฅผ ์ ์šฉ) **NOTE** > Update Cycle: ๋ฐœ์ƒํ•œ ์ด๋ฒคํŠธ๋“ค์„ ๋ชจ๋‘ ์ฒ˜๋ฆฌํ•˜๊ณ  ๊ถŒํ•œ์ด Main Run Loop๋กœ ๋Œ์•„์˜ค๊ฒŒ ๋˜๋Š” ์‹œ์  ![แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2024-01-30 21.34.31](https://hackmd.io/_uploads/S1M1avUqp.png) ๋‹ค์‹œ ๋งํ•ด์„œ, ๋ทฐ์˜ position or layoutd์˜ ๋ณ€ํ™”๋ฅผ ๊ฐฑ์‹ ํ•˜๋Š” ๊ฒƒ์€ ์‹œ๊ฐ„์ฐจ๊ฐ€ ์กด์žฌํ•œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ๊ฐœ๋ฐœํ•  ๋•Œ๋Š” ์ด๋Ÿฐ ์‹œ๊ฐ„์ฐจ๋ฅผ ํ•ญ์ƒ ๊ณ ๋ คํ•ด์•ผ ํ•œ๋‹ค. ## layoutSubviews() > ์ด ๋ฉ”์„œ๋“œ๊ฐ€ ์‹คํ–‰๋˜๋Š” ์‹œ์ ์—์„œ ํ•˜์œ„ ๋ทฐ๋ฅผ ๋ฐฐ์น˜ํ•˜๊ฒŒ ๋œ๋‹ค. ํ˜ธ์ถœํ•˜๋ฉด ํ•ด๋‹น ๋ทฐ์˜ ๋ชจ๋“  Subview๋“ค์ด layoutSubviews๋ฅผ ์—ฐ๋‹ฌ์•„ ํ˜ธ์ถœํ•œ๋‹ค. ์‹œ์Šคํ…œ์— ์˜ํ•ด์„œ ๋ทฐ์˜ ๊ฐ’์ด ์žฌ๊ณ„์‚ฐ๋˜๋Š” ์‹œ์ ์— ์ž๋™์œผ๋กœ ํ˜ธ์ถœ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๊ฐœ๋ฐœ์ž๊ฐ€ ๋”ฐ๋กœ ํ˜ธ์ถœํ•  ๊ฒฝ์šฐ ๋น„์šฉ์ด ๋งŽ์ด ๋“œ๋Š” ๋ฉ”์„œ๋“œ์ด๋‹ค. ๊ฐœ๋ฐœ์ž๊ฐ€ ์„ค์ •ํ•œ Contraints๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•˜์œ„ ๋ทฐ์˜ size, position์„ ๊ฒฐ์ •ํ•œ๋‹ค. ์ด ๋ฉ”์„œ๋“œ๋Š” ํ•„์š”์— ๋”ฐ๋ผ ํ•˜์œ„ ๋ทฐ์˜ ๋ ˆ์ด์•„์›ƒ์„ ๋” ์ •ํ™•ํ•˜๊ฒŒ ์กฐ์ ˆํ•˜๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ ์„œ๋ธŒํด๋ž˜์Šค์—์„œ overrideํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด ๋ฉ”์„œ๋“œ๋ฅผ overrideํ•ด์•ผํ•˜๋Š” ์ด์œ ๋Š” ํ•˜์œ„ ๋ทฐ์˜ autoresizing ๋ฐ constraint-based ๋™์ž‘์„ ์ œ๊ณตํ•˜์ง€ ์•Š์„ ๋•Œ์ด๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์šฐ๋ฆฌ๋Š” ํ•˜์œ„ ๋ทฐ์˜ Frame ์‚ฌ๊ฐํ˜•์„ ์ง์ ‘ ์„ค์ •ํ•  ์ˆ˜๋„ ์žˆ๋‹ค. **ํ•˜์ง€๋งŒ** ์ด ๋ฉ”์„œ๋“œ๋ฅผ ์ง์ ‘ ํ˜ธ์ถœํ•ด์„œ๋Š” ์•ˆ๋œ๋‹ค. ๋ ˆ์ด์•„์›ƒ์„ ๊ฐ•์ œ์ ์œผ๋กœ ์—…๋ฐ์ดํŠธํ•˜๋ ค๋ฉด drawing์ด ์—…๋ฐ์ดํŠธ ๋˜๊ธฐ ์ „์— setNeedsLayout()๋ฅผ ํ˜ธ์ถœํ•ด์•ผ ํ•œ๋‹ค. ๋˜๋Š”, ๋ทฐ์˜ ๋ ˆ์ด์•„์›ƒ์„ ์ฆ‰์‹œ ์—…๋ฐ์ดํŠธํ•˜๋ ค๋ฉด layoutIfNeeded()๋ฅผ ํ˜ธ์ถœํ•˜๋ผ. **NOTE** > UIViewController ๋‚ด์˜ ๋ทฐ๊ฐ€ ์žฌ๊ณ„์‚ฐ๋˜์–ด ๋‹ค์‹œ ๊ทธ๋ ค์ง€๋Š” ํ–‰์œ„๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ณผ์ •์€ layoutSubviews๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ํ•˜์œ„ ๋ทฐ๊ฐ€ ๋ฐฐ์น˜๋˜๋ฉด ๊ทธ ๋‹ค์Œ์œผ๋กœ viewDidLayoutSubviews๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ๊ฐฑ์‹ ๋œ View ๊ฐ’์— ์˜์กดํ•˜๋Š” ํ–‰์œ„๋“ค์€ ์ด ๋ฉ”์„œ๋“œ์— ๋ช…์‹œํ•ด์•ผ ํ•œ๋‹ค. <br> EX) Layer ๊ฐ’์€ ์ž๋™์œผ๋กœ ์—…๋ฐ์ดํŠธ๋˜์ง€ ์•Š๋Š”๋‹ค. ๊ทธ๋ž˜์„œ ์†ํ•œ ๋ทฐ์˜ Frame์ด ๋ณ€๊ฒฝ๋˜๋ฉด, ์ด์— ๋Œ€์‘ํ•˜์—ฌ `viewDidLayoutSubviews` ์•ˆ์—์„œ ๋ ˆ์ด์–ด์˜ frame์„ ์ˆ˜๋™์œผ๋กœ ์กฐ์ •ํ•ด์•ผ ํ•œ๋‹ค. - View์˜ ํฌ๊ธฐ๋ฅผ ์กฐ์ ˆํ•  ๋•Œ - Subview๋ฅผ ์ถ”๊ฐ€ํ•  ๋•Œ - ์‚ฌ์šฉ์ž๊ฐ€ UIScrollView๋ฅผ ์Šคํฌ๋กคํ•  ๋•Œ - ๋””๋ฐ”์ด์Šค๋ฅผ ํšŒ์ „์‹œ์ผฐ์„ ๋•Œ (Orientation) - View์˜ AutoLayout ์ œ์•ฝ ์กฐ๊ฑด์„ ๋ณ€๊ฒฝ์‹œ์ผฐ์„ ๋•Œ ์œ„์— ์–ธ๊ธ‰๋œ ์‹œ์ ๋“ค์€ layoutSubviews๋ฅผ ์ž๋™์œผ๋กœ ํ˜ธ์ถœํ•˜๊ธฐ ์œ„ํ•œ update cycle์—์„œ์˜ ํŠน์ • ์ง€์ ๋“ค์„ ๋‚˜ํƒ€๋‚ธ๋‹ค. ์•„๋ž˜๋Š” ์ž๋™ ์˜ˆ์•ฝ์ด ์•„๋‹Œ ์ˆ˜๋™์œผ๋กœ ์—…๋ฐ์ดํŠธ ์ฃผ๊ธฐ๋ฅผ ์˜ˆ์•ฝํ•˜๋Š” ๋ฉ”์„œ๋“œ๋“ค์ด๋‹ค. ## setNeedsLayout() > Receiver์˜ ๋ทฐ๋ฅผ ๋ฌดํšจํ™”ํ•˜๊ณ  ๋‹ค์Œ update cycle๋™์•ˆ ๋ ˆ์ด์•„์›ƒ์„ ์—…๋ฐ์ดํŠธ ํ•˜๊ธฐ ์œ„ํ•ด ํŠธ๋ฆฌ๊ฑฐ ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ํ•˜์œ„ ๋ทฐ์˜ ๋ ˆ์ด์•„์›ƒ์„ ์กฐ์ ˆํ•˜๋ ค๋ฉด ์ด ๋ฉ”์„œ๋“œ๋ฅผ Main Thread์—์„œ ํ˜ธ์ถœํ•ด์•ผ ํ•œ๋‹ค. ์ด ๋ฉ”์„œ๋“œ๋Š” ์š”์ฒญํ•œ ๊ฒƒ์„ ๊ธฐ๋กํ•˜๊ณ  ์ฆ‰์‹œ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ํŠน์ง•์œผ๋กœ๋Š” ์ฆ‰์‹œ ๋ทฐ๋ฅผ ๊ฐฑ์‹ ํ•˜์ง€ ์•Š๊ณ  ๋‹ค์Œ Update cycle์„ ๊ธฐ๋‹ค๋ฆฌ๊ธฐ ๋•Œ๋ฌธ์— ์—…๋ฐ์ดํŠธ๋˜๊ธฐ ์ „์— setNeedsLayout์„ ์‚ฌ์šฉํ•˜์—ฌ ์—ฌ๋Ÿฌ ๋ทฐ์˜ ๋ ˆ์ด์•„์›ƒ์˜ ๋ฌดํšจํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค. ๋˜ํ•œ, ์ด ๋™์ž‘์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ชจ๋“  ๋ ˆ์ด์•„์›ƒ์˜ ์—…๋ฐ์ดํŠธ๋ฅผ ํ•˜๋‚˜์˜ update cycle๋กœ ํ†ตํ•ฉํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์ผ๋ฐ˜์ ์œผ๋กœ ์„ฑ๋Šฅ์— ๋” ์ข‹๋‹ค. ## layoutIfNeeded() > ๋ ˆ์ด์•„์›ƒ์˜ ์—…๋ฐ์ดํŠธ๊ฐ€ ๋ณด๋ฅ˜ ์ค‘์ธ ๊ฒฝ์šฐ, ํ•˜์œ„ ๋ทฐ๋ฅผ ์ฆ‰์‹œ ๊ฐฑ์‹ ํ•œ๋‹ค. ์ด ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋ทฐ์˜ ๋ ˆ์ด์•„์›ƒ์„ ์ฆ‰์‹œ ์—…๋ฐ์ดํŠธํ•  ์ˆ˜ ์žˆ๋‹ค. Auto layout์„ ์‚ฌ์šฉํ•  ๋•Œ, ๋ ˆ์ด์•„์›ƒ ์—”์ง„์€ ์ œ์•ฝ ์กฐ๊ฑด์˜ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์ถฉ์กฑํ•˜๊ธฐ ์œ„ํ•ด ํ•„์š”์— ๋”ฐ๋ผ ๋ทฐ์˜ ์œ„์น˜๋ฅผ ์—…๋ฐ์ดํŠธ ํ•œ๋‹ค. ๋ฉ”์„ธ์ง€๋ฅผ ๋ฐ›์€ ๋ทฐ๋ฅผ ๋ฃจํŠธ ๋ทฐ๋กœ ์‚ฌ์šฉํ•˜์—ฌ ๋ฃจํŠธ์—์„œ ์‹œ์ž‘ํ•˜๋Š” ๋ทฐ ํ•˜์œ„ ํŠธ๋ฆฌ๋ฅผ ๋ฐฐ์น˜ํ•œ๋‹ค. ๋ณด๋ฅ˜ ์ค‘์ธ ๋ ˆ์ด์•„์›ƒ ์—…๋ฐ์ดํŠธ๊ฐ€ ์—†์œผ๋ฉด, ์ด ๋ฉ”์„œ๋“œ๋Š” ๋ ˆ์ด์•„์›ƒ์„ ์ˆ˜์ •ํ•˜๊ฑฐ๋‚˜ ๋ ˆ์ด์•„์›ƒ ๊ด€๋ จ ์ฝœ๋ฐฑ์„ ํ˜ธ์ถœํ•˜์ง€ ์•Š๊ณ  ์ข…๋ฃŒ๋œ๋‹ค. ## ๋‘ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ ๊ฒฝ์šฐ Main Run Loop์—์„œ ํ•œ View๊ฐ€ `setNeedsLayout`์„ ํ˜ธ์ถœํ•˜๊ณ  ๋ฐ”๋กœ ๋‹ค์Œ์— `layoutIfNeeded`๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค๋ฉด, `layoutIfNeeded`๋Š” ์ฆ‰์‹œ View์˜ ๊ฐ’์„ ์žฌ๊ณ„์‚ฐํ•˜๊ณ  ๋ทฐ์— ๋ฐ˜์˜ํ•˜๊ฒŒ ๋œ๋‹ค. ์ด๋กœ ์ธํ•ด `setNeedsLayout`์ด ์˜ˆ์•ฝํ•œ `layoutSubviews` ๋ฉ”์„œ๋“œ๋Š” ํ•ด๋‹น update cycle์—์„œ ๋ณ€๊ฒฝ๋œ ๊ฐ’์ด ์—†์–ด ํ˜ธ์ถœ๋˜์ง€ ์•Š๊ฒŒ ๋œ๋‹ค. ์ด๋Ÿฐ ์ž‘๋™ ๋ฐฉ์‹์œผ๋กœ `layoutIfNeeded`๋Š” ์ฆ‰์‹œ ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜์–ด์•ผ ํ•˜๋Š” ์• ๋‹ˆ๋ฉ”์ด์…˜์—์„œ ๋„๋ฆฌ ์‚ฌ์šฉ๋œ๋‹ค. ๋ฐ˜๋ฉด์— `setNeedsLayout`์„ ์‚ฌ์šฉํ•˜๋ฉด ์• ๋‹ˆ๋ฉ”์ด์…˜ ๋ธ”๋ก์—์„œ ๊ฐ’์ด ์ฆ‰์‹œ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๊ณ  ๋‚˜์ค‘์˜ ์—…๋ฐ์ดํŠธ ์ฃผ๊ธฐ์—์„œ ๊ฐ’์ด ๋ฐ˜์˜๋˜๋ฏ€๋กœ ๋ณ€๊ฒฝ์€ ์ด๋ฃจ์–ด์ง€์ง€๋งŒ ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ๊ฐ€ ๋ˆˆ์— ๋„์ง€ ์•Š์Šต๋‹ˆ๋‹ค.