๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
iOS

UIViewController LifeCycle

by yangsubinn 2025. 11. 20.
โ“ init์„ ํ•˜๋ฉด loadView๊ฐ€ ๋ถˆ๋ฆด๊นŒ?

 

๋ผ๋Š” ์งˆ๋ฌธ์„ ์ตœ๊ทผ์— ๋ฐ›์€ ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

 

์ฒ˜์Œ์— ์งˆ๋ฌธ์„ ๋“ค์—ˆ์„๋•Œ๋Š” ๋‹น์—ฐํžˆ ๋ถˆ๋ฆฌ๊ฒ ์ง€...? ์•„๋‹Œ๊ฐ€ ..??? ํ•˜๋ฉด์„œ ์•ฝ๊ฐ„ ์–ด์•ˆ์ด ๋ฒ™๋ฒ™์ด ๋์—ˆ๋Š”๋ฐ..

์ƒ๊ฐํ•˜๋‹ค๋ณด๋‹ˆ ์‹ค์ œ๋กœ ๊ฐœ๋ฐœํ•˜๋ฉด์„œ ์ž์ฃผ ์“ฐ๋Š” viewDidLoad๋‚˜ viewWillAppear ๊ฐ™์€ ๋ฉ”์„œ๋“œ ๋ง๊ณ ๋Š” ํฌ๊ฒŒ ๊ด€์‹ฌ ๊ฐ–์ง€ ์•Š์•˜๋˜ ๊ฒƒ ๊ฐ™๊ณ  

๋‹น์—ฐํžˆ ์•ˆ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ๋˜ life cycle์— ๋Œ€ํ•ด ๋‚ด๊ฐ€ ์ž˜ ๋ชจ๋ฅด๊ณ  ์žˆ๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ค์—‡์Šต๋‹ˆ๋‹ค.

 

๊ธฐ์™• ์ด๋ ‡๊ฒŒ ๋œ ๊น€์— Life Cycle์— ๋Œ€ํ•ด ์ž์„ธํžˆ ์•Œ์•„๋ณด๋ฉด์„œ ์ € ์งˆ๋ฌธ์— ๋Œ€ํ•œ ์ •๋‹ต์„ ์ฐพ์•„๋ณด๋ ค๊ตฌ ํ•ฉ๋‹ˆ๋‹ค.

 


UIViewController / UIView์˜ ๊ด€๊ณ„

Life Cycle! ์ด๋ผ๊ณ  ํ•˜๋ฉด ํ‰์ƒ์‹œ View Life Cycle ์ด๋ผ๊ณ  ๋งŽ์ด ๋ถˆ๋ €๋˜ ๊ฒƒ ๊ฐ™์€๋ฐ 

๋จผ์ € ๋‚ด๊ฐ€ ์•Œ์•„๋ณด๋ ค๊ณ  ํ•˜๋Š” Life Cycle์ด ๋ˆ„๊ตฌ์˜ ์ƒ์• ์ฃผ๊ธฐ์ธ์ง€ ๋”ฑ ์ •๋ฆฌํ•˜๊ณ  ๋„˜์–ด๊ฐ€๊ฒ ์Šต๋‹ˆ๋‹ค.

 

์š”๋ ‡๊ฒŒ ๋ฒ„ํŠผ ๋‘๊ฐœ๊ฐ€ ์กด์žฌํ•˜๋Š” ํ™”๋ฉด์ด ์žˆ๋‹ค๊ณ  ํ–ˆ์„๋•Œ, Hierarchy๋ฅผ ์ฐ์–ด๋ณด๋ฉด ์˜ค๋ฅธ์ชฝ ์ฒ˜๋Ÿผ ๋‚˜์˜ค๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

ํฐ์ƒ‰ ํ™”๋ฉด ๋ถ€๋ถ„์„ ์žก์•„์„œ Debug Navigator๋กœ ๊ฐ€๋ณด๋ฉด UIView ๋ผ๊ณ  ๋‹น๋‹นํ•˜๊ฒŒ ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋˜ Constraints๋„ UIView์˜ ํ•˜์œ„์— ์กด์žฌํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

์ •๋ฆฌํ•ด๋ณด๋ฉด,

  • UIViewController : ํ™”๋ฉด ์ „์ฒด์˜ ํ๋ฆ„, ์ „ํ™˜, ์‚ฌ์šฉ์ž์™€์˜ ์ƒํ˜ธ์ž‘์šฉ ๊ด€๋ฆฌ (navigation, modal, gesture ๋“ฑ)
  • UIView : ํ™”๋ฉด ์•ˆ์— ๋ณด์—ฌ์ง€๋Š” UI ์š”์†Œ, ๋ ˆ์ด์•„์›ƒ(Constraints)๊ณผ ๊ทธ๋ฆฌ๊ธฐ(draw) ๋‹ด๋‹น

์š”๋ ‡๊ฒŒ ์ •๋ฆฌํ•  ์ˆ˜ ์žˆ๊ณ  - ์šฐ๋ฆฌ๊ฐ€ ํ‰์ƒ์‹œ์— ๋งํ•˜๋˜ Life Cycle์€ UIViewController์˜ Life Cycle์ด๋ผ๊ณ  ์ •๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

UIViewContoller์˜ Life Cycle

UIViewController Life Cycle

์ผ๋‹จ Life Cycle์„ ํ•œ ๋ˆˆ์— ๋ณด๋ฉด ์š”๋ ‡๊ฒŒ ์ƒ๊ฒผ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์˜†์— ์žˆ๋Š” init / layoutSubviews / draw ๋Š” View์—์„œ ํ˜ธ์ถœ๋˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

 

let vc = DetailViewController()
navigationController?.pushViewControllers(vc, animated: true)

 

 

 

์œ„์™€ ๊ฐ™์ด ๋ทฐ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ํ•˜๋‚˜ ์ƒ์„ฑํ•ด์„œ push ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์‹คํ–‰์‹œ์ผฐ์„๋•Œ ํ˜ธ์ถœ๋˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์ˆœ์„œ๋Œ€๋กœ ๋”ฐ๋ผ๊ฐ€๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

init

๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ํ˜ธ์ถœํ•˜๋Š” ๋ฉ”์„œ๋“œ๋กœ,

์ด๋•Œ UIViewController์˜ ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋˜์–ด ๋ฉ”๋ชจ๋ฆฌ์— ํ•œ์ž๋ฆฌ ์ฐจ์ง€ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

init ์ „ / ํ›„

 

loadView

class DetailViewController: UIViewController {
	override func loadView() {
    	// super.loadView()
        view = MyCustomView()
    }
}
  • UIViewController๊ฐ€ ๋‚ด๋ถ€์—์„œ ๊ฐ–๋Š” view๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๋ฉ”๋ชจ๋ฆฌ์— ์˜ฌ๋ฆผ
  • UIViewController์˜ view๊ฐ€ nil์ธ ๊ฒฝ์šฐ loadView() ๋‚ด๋ถ€์ ์œผ๋กœ view์— ๊ธฐ๋ณธ์œผ๋กœ UIView() ์ƒ์„ฑํ•ด์„œ ํ• ๋‹น
  • ์ง์ ‘ root view๋ฅผ ์ปค์Šคํ…€ํ•œ view๋กœ ๋ณ€๊ฒฝํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ super.loadView()๋ฅผ ์‹คํ–‰์‹œํ‚ค์ง€ ์•Š๊ณ  ์ง์ ‘ ์ƒ์„ฑ ํ›„ ํ• ๋‹น
  • https://developer.apple.com/documentation/uikit/uiviewcontroller/loadview()

์š”๊ฑด ์•„๋ž˜์„œ ์ซŒ ๋” ์ž์„ธํžˆ ๋ณด๊ฒ ์Šด๋‹ˆ๋‹น

๊ธฐ๋ณธ UIView ์‚ฌ์šฉ / MyCustomView๋กœ ๋ณ€๊ฒฝ
์˜น์กธํ•œ ์ปค์Šคํ…€ ๋ทฐ ์ฃผ์ž…

๋ชป์ƒ๊ธฐ๊ธด ํ–ˆ์ง€๋งŒ Custom View์— ์‚ฌ์ด์ฆˆ ๊ณ ์ •ํ•ด๋ฒ„๋ฆฌ๋ฉด ์•„์˜ˆ ๋ทฐ์ปจ ์ž์ฒด๋„ ์š”๋ ‡๊ฒŒ ์ž‘์•„์ง‘๋‹ˆ๋‹ค !

 

viewDidLoad

  • ViewController ์•ˆ์— View๊ฐ€ ์ƒ์„ฑ๋˜์–ด ๋ฉ”๋ชจ๋ฆฌ์— ์™„์ „ํžˆ ์˜ฌ๋ผ์˜จ ๋’ค ํ•œ ๋ฒˆ ํ˜ธ์ถœ
  • ๋ทฐ๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ•ด์ œ๋œ ํ›„ ๋‹ค์‹œ ๋ฉ”๋ชจ๋ฆฌ์— ์˜ฌ๋ผ์˜ค๋ฉด ๋˜ ๋‹ค์‹œ ํ˜ธ์ถœ๋จ
  • ํ™”๋ฉด ์ตœ์ดˆ ์ง„์ž…์‹œ API ํ˜ธ์ถœ์ด๋‚˜ addSubview, UI ์ดˆ๊ธฐํ™” ์ž‘์—… ๋‹ด๋‹น
    • view๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ์— ๋กœ๋“œ๋œ ์งํ›„ ๋”ฑ ํ•œ ๋ฒˆ๋งŒ ํ˜ธ์ถœ๋จ
    • ์•„์ง ํ™”๋ฉด ์ƒ์— ๋ณด์—ฌ์ง€์ง„ ์•Š์ง€๋งŒ root view๋Š” ์กด์žฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— - ๋ณด์—ฌ์ง€๊ธฐ ์ „์— subview ์ถ”๊ฐ€ + ๋ ˆ์ด์•„์›ƒ ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅ
  • https://developer.apple.com/documentation/uikit/uiviewcontroller/viewdidload()

 

viewWillAppear

  • view๊ฐ€ View Hierarchy* ์ƒ์— ์˜ฌ๋ผ์˜ค๊ธฐ ์ง์ „์— ํ˜ธ์ถœ๋˜๋Š” ๋ฉ”์„œ๋“œ
    • *View Hierarchy์— ์˜ฌ๋ผ์˜จ๋‹ค๋Š” ๊ฒƒ์€ ๋ทฐ๋“ค์ด ์„œ๋กœ ๋ถ€๋ชจ-์ž์‹ ๊ด€๊ณ„๋กœ ์—ฐ๊ฒฐ๋˜์–ด ๊ณ„์ธต ๊ตฌ์กฐ๊ฐ€ ์žกํžŒ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.
    • ๊ณ„์ธต ๊ตฌ์กฐ๊ฐ€ ์žกํžˆ๋ฉด ํ™”๋ฉด ์ƒ์—์„œ ํ™•์ธ ๊ฐ€๋Šฅํ•ด์ง
  • ๋ฉ”๋ชจ๋ฆฌ์™€ ์ƒ๊ด€์—†์ด ํ™”๋ฉด ์ƒ์— ๋ณด์—ฌ์งˆ ๋•Œ๋งˆ๋‹ค ํ˜ธ์ถœ
    • ๋ฉ”๋ชจ๋ฆฌ์—๋Š” ์ด๋ฏธ ์˜ฌ๋ผ์™€์žˆ๋Š” ์ƒํƒœ์ด๊ณ , ํ•ด๋‹น ๋ทฐ์ปจ ์œ„๋กœ ๋‹ค๋ฅธ ๋ทฐ์ปจ์ด push๋˜๊ฑฐ๋‚˜ present๋˜๋”๋ผ๋„ ํ•ด๋‹น ๋ทฐ์ปจ์ด ๋ฉ”๋ชจ๋ฆฌ ํ•ด์ œ๋˜์ง„ ์•Š์Œ -> viewDidLoad๋Š” ๋ถˆ๋ฆฌ์ง€ ์•Š๊ณ  viewWillAppear๋งŒ ๋ฐ˜๋ณต ํ˜ธ์ถœ
  • ํ™”๋ฉด ์ „ํ™˜ ํ›„์— ๋ฐ”๋กœ UI๋‚˜ ๋ฐ์ดํ„ฐ ๊ฐฑ์‹ ์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ ํ•ด๋‹น ๋ฉ”์„œ๋“œ ๋‚ด๋ถ€์—์„œ ์ฒ˜๋ฆฌ
  • https://developer.apple.com/documentation/uikit/uiviewcontroller/viewwillappear(_:)

ํฐ ํ™”๋ฉด์˜ viewWillAppear, viewDidAppear

 

viewWillLayoutSubViews

  • ViewController์˜ root view๊ฐ€ ๋‚ด๋ถ€์ ์œผ๋กœ layoutSubviews๋ฅผ ํ•˜๊ธฐ ์ „์— ํ˜ธ์ถœ๋˜๋Š” ๋ฉ”์„œ๋“œ
  • view ๋‚ด๋ถ€์˜ subview๋“ค์ด View Hierarchy์— ์˜ฌ๋ผ์˜ค๊ธฐ ์ง์ „ ํ˜ธ์ถœ๋˜๋ฉฐ, ์•„์ง subview๋“ค์˜ frame๊ณผ bounds๊ฐ€ ํ™•์ •๋˜์ง€ ์•Š์€ ์ƒํƒœ

 

[UIView] layoutSubviews

  • view ๋‚ด๋ถ€์˜ subview๋“ค์˜ frame๊ณผ bounds๋ฅผ ๋ฐฐ์น˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ
  • UIKit์ด Auto Layout ์ œ์•ฝ ์กฐ๊ฑด์— ๋”ฐ๋ผ subview ์œ„์น˜์™€ ํฌ๊ธฐ๋ฅผ ๊ณ„์‚ฐํ•  ๋•Œ ํ˜ธ์ถœ๋จ
  • ํ˜ธ์ถœ ์‹œ์ 
    • view๊ฐ€ ๋กœ๋“œ๋  ๋•Œ (์ž๋™ ํ˜ธ์ถœ)
    • view ๋‚ด์—์„œ bounds๋‚˜ constraints๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ (์ž๋™ ํ˜ธ์ถœ)
    • setNeedsLayout() ๋˜๋Š” layoutIfNeeded() ํ˜ธ์ถœํ•  ๋•Œ (๊ฐ•์ œ ํ˜ธ์ถœ)
      • setNeedsLayout : ๋ทฐ์˜ ๋ ˆ์ด์•„์›ƒ ๊ฐฑ์‹ ์ด ํ•„์š”ํ•ด! ๋ผ๊ณ  ์•Œ๋ฆฌ๋Š” ์—ญํ• , ์ฆ‰์‹œ ๋ ˆ์ด์•„์›ƒ์„ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ  ๋‹ค์Œ ๊ฐฑ์‹ ์‹œ์— ์ž๋™์œผ๋กœ layoutSubviews๋ฅผ ํ˜ธ์ถœํ•˜๋„๋ก ์˜ˆ์•ฝ
      • layoutIfNeeded : ์ง€๊ธˆ ๋ฐ”๋กœ ๋ ˆ์ด์•„์›ƒ ๊ฐฑ์‹ ํ•ด! ๋ผ๊ณ  ํ•˜๋Š” ์—ญํ• , ์ฆ‰์‹œ layoutSubviews๊ฐ€ ํ˜ธ์ถœ๋จ

 

viewDidLayoutSubviews

  • ViewController์˜ root view๊ฐ€ ๋‚ด๋ถ€์ ์œผ๋กœ layoutSubviews๋ฅผ ์™„๋ฃŒ ํ›„ ํ˜ธ์ถœ๋˜๋Š” ๋ฉ”์„œ๋“œ

  • view ๋‚ด๋ถ€์˜ subviews๋“ค์ด View Hierarchy์— ์˜ฌ๋ผ์™”๊ธฐ ๋•Œ๋ฌธ์—, subviews๋“ค์˜ frame๊ณผ bounds๊ฐ€ ํ™•์ •๋จ
    • ๊ทธ์น˜๋งŒ ์•„์ง ๋ˆˆ์— ๋ณด์—ฌ์ง€์ง„ ์•Š์Œ
    • view ๋‚ด๋ถ€ subviews๋“ค์ด ์„œ๋กœ์„œ๋กœ ๊ณ„์ธต์ด ์žกํžŒ๊ฑฐ๊ณ , root view๋Š” ์•„์ง View Hierarchy์— ์˜ฌ๋ผ์˜ค์ง€ ์•Š์Œ
  • ๋ ˆ์ด์•„์›ƒ ํ›„ ํ›„์ฒ˜๋ฆฌ๋‚˜, frame ๊ธฐ๋ฐ˜์˜ UI ์—…๋ฐ์ดํŠธ, animation ์ค€๋น„ ์ฒ˜๋ฆฌ
    • ex) width๊ฐ€ ๋™์ ์ธ ๋ทฐ์— radius๋ฅผ ๋น„์œจ์— ๋”ฐ๋ผ ์ ์šฉํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ, ๊ณ„์‚ฐ๋œ frame ๊ฐ’์„ ๊ธฐ์ค€์œผ๋กœ ์ ์šฉ
  • https://developer.apple.com/documentation/uikit/uiviewcontroller/viewdidlayoutsubviews()

 

viewDidAppear

  • UIViewController ๋‚ด์˜ root view์ธ view๊นŒ์ง€ View Hierarchy์— ์˜ฌ๋ผ์˜จ ํ›„ ํ˜ธ์ถœ๋˜๋Š” ๋ฉ”์„œ๋“œ
  • ๋ฉ”๋ชจ๋ฆฌ์—๋Š” ๋‹น์—ฐํžˆ ์ด๋ฏธ ์˜ฌ๋ผ๊ฐ€์žˆ๊ณ , ํ™”๋ฉด ์ƒ์—๋„ ๋ณด์—ฌ์ง€๋Š” ์ƒํƒœ

 

 

[UIView] draw(_:)

  • UIKit์—์„œ ์ œ๊ณตํ•˜๋Š” Core Graphics ๊ธฐ๋ฐ˜์˜ ๊ทธ๋ฆฌ๊ธฐ ํ•จ์ˆ˜๋กœ, ํ™”๋ฉด์— UIBezierPath, CGGradient ๊ฐ™์€ ์ปค์Šคํ…€ ๊ทธ๋ž˜ํ”ฝ์„ ๊ทธ๋ฆผ
  • ํ˜ธ์ถœ ์‹œ์ 
    • view๊ฐ€ ๋กœ๋“œ๋  ๋•Œ ์ปค์Šคํ…€ ๊ทธ๋ž˜ํ”ฝ์„ ๊ทธ๋ ค์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ viewDidAppear์—์„œ (ํ•ญ์ƒ ํ˜ธ์ถœ X, ํ•„์š”์— ๋”ฐ๋ผ)
    • setNeedsDisplay() ํ˜ธ์ถœ๋  ๋•Œ
  • https://developer.apple.com/documentation/uikit/uiview/draw(_:)

 

 

์—ฌ๊ธฐ๊นŒ์ง€ ํ•˜๋ฉด ํ™”๋ฉด์ด ๋ณด์—ฌ์ง€๊ธฐ ์œ„ํ•ด ์‹คํ–‰๋˜๋Š” ๋ฉ”์„œ๋“œ ๋ - ์ด์ œ ํ™”๋ฉด์—์„œ ์‚ฌ๋ผ์งˆ ์ฐจ๋ก€

// DetailViewController์—์„œ
navigationController?.popViewController(animated: true)

 

viewWillDisappear

  • ViewController๊ฐ€ ํ™”๋ฉด์—์„œ ์‚ฌ๋ผ์ง€๊ธฐ ์ง์ „์— ํ˜ธ์ถœ๋˜๋Š” ๋ฉ”์„œ๋“œ๋กœ, ํ™”๋ฉด ์ „ํ™˜ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์‹œ์ž‘ ์ „์— ํ˜ธ์ถœ
  • View Hierarchy์— ์กด์žฌํ•˜๊ณ , ๋ฉ”๋ชจ๋ฆฌ๋„ ์•„์ง ํ•ด์ œ๋˜์ง€ ์•Š์€ ์ƒํƒœ

  • ํƒ€์ด๋จธ, ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ค‘๋‹จ, ๋„คํŠธ์›Œํฌ ์š”์ฒญ ์ทจ์†Œ, ์ œ์Šค์ฒ˜ ์ •๋ฆฌ ๋“ฑ์˜ ์ž‘์—…์„ ์ˆ˜ํ–‰
  • swipe back ์ œ์Šค์ฒ˜๋ฅผ ์‹œ์ž‘ํ•˜๋ฉด ํ˜ธ์ถœ๋จ
    • ์ œ์Šค์ฒ˜๋ฅผ ์ค‘๊ฐ„์— ๋ฉˆ์ถฐ๋ฒ„๋ฆฌ๋ฉด ๋‹ค์‹œ viewWillAppear - viewDidAppear ์ˆœ์œผ๋กœ ํ˜ธ์ถœ๋จ
    • -> viewWillDisappear๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค๊ณ  ํ•ด์„œ ํ•ด๋‹น ๋ทฐ์ปจ์ด ํ•ด์ œ๋จ์€ ๋ณด์žฅํ•  ์ˆ˜ ์—†์Œ

 

viewDidDisappear

  • ํ™”๋ฉด ์ƒ์—์„œ ์‚ฌ๋ผ์ง„ ํ›„์— ํ˜ธ์ถœ
  • View Hierarchy์—์„œ ์‚ฌ๋ผ์กŒ์ง€๋งŒ, ๋ฉ”๋ชจ๋ฆฌ๋Š” ํ•ด์ œ๋˜๊ธฐ ์ „์˜ ์ƒํƒœ

 

deinit

  • ViewController ๊ฐ์ฒด๊ฐ€ ARC์— ์˜ํ•ด ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ•ด์ œ๋  ๋•Œ ํ˜ธ์ถœ
  • ARC (Automatic Reference Counting)
    • Swift, Objective-C์—์„œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ž๋™์œผ๋กœ ๊ด€๋ฆฌํ•˜๋Š” ์‹œ์Šคํ…œ
    • ์ฐธ์กฐ ํƒ€์ž…์ธ Class์— ๋Œ€ํ•ด์„œ ์ž๋™์œผ๋กœ ์ฐธ์กฐ๊ฐ€ ๋ช‡๊ฐœ ์กด์žฌํ•˜๋Š”์ง€ ์นด์šดํŒ…ํ•˜๊ณ , ์นด์šดํŠธ๊ฐ€ 0์ด ๋˜๋Š” ์ˆœ๊ฐ„ ARC์—์„œ deinit ํ˜ธ์ถœ

loadView ์ง‘์ค‘ํ•ด์„œ ๋ณด๊ธฐ

init์„ ํ•˜๋ฉด loadView๊ฐ€ ๋ถˆ๋ฆฐ๋‹ค?

๋งจ ์ฒ˜์Œ ์‹œ์ž‘์ด์—ˆ๋˜ ์งˆ๋ฌธ์œผ๋กœ ๋Œ์•„๊ฐ€๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

โ“ init์„ ํ•˜๋ฉด loadView๊ฐ€ ๋ถˆ๋ฆด๊นŒ?

 

๊ฒฐ๋ก ๋ถ€ํ„ฐ ๋งํ•˜๋ฉด โŒ ์ž…๋‹ˆ๋‹ค.

 

UIViewController์˜ init๊ณผ loadView์˜ ์ •์˜๋ฅผ ๋‹ค์‹œ ๋ณด๋ฉด

init์€ UIViewController ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์ด๊ณ  loadView๋Š” UIViewController ์•ˆ์˜ root view๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

loadView๋Š” root view๊ฐ€ ์ง์ ‘์ ์œผ๋กœ ํ•„์š”ํ•ด์งˆ๋•Œ ํ˜ธ์ถœ๋˜๋Š” lazy ๋ฉ”์„œ๋“œ์ด๊ธฐ ๋•Œ๋ฌธ์— 

๋‹จ์ˆœํžˆ ์ƒ์œ„ ๊ฐ์ฒด์ธ UIViewController๋ฅผ ์ƒ์„ฑ๋งŒ ํ–ˆ์„๋•Œ์—๋Š” loadView๊ฐ€ ํ˜ธ์ถœ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

 

๊ทธ๋Ÿผ root view๊ฐ€ ํ•„์š”ํ•œ ๋•Œ๋Š” ์–ธ์ œ์ผ๊นŒ์—ฌ ?

vc.view ์™€ ๊ฐ™์ด ์ง์ ‘์ ์œผ๋กœ view๋ฅผ ํ˜ธ์ถœํ•˜๊ฑฐ๋‚˜, ํ™”๋ฉด ์ „ํ™˜์„ ํ†ตํ•ด view๊ฐ€ ๊ทธ๋ ค์ ธ์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ UIViewController์—์„œ๋Š” view๋ฅผ ํ•„์š”๋กœ ํ•ฉ๋‹ˆ๋‹ค.

// init ํ˜ธ์ถœ
let vc = ViewController()

// loadView ํ˜ธ์ถœ
view.addSubview(vc.view)

// init + loadview + viewDidLoad + ... ํ˜ธ์ถœ
let otherVC = OtherViewController()
navigationController?.pushViewController(otherVC, animated: true)

 

์ •๋ฆฌํ•ด๋ณด๋ฉด ์•„๋ž˜์™€ ๊ฐ™์€ ์ƒํ™ฉ์ผ๋•Œ init์€ ๋์ง€๋งŒ, loadView๋Š” ํ˜ธ์ถœ๋˜์ง€ ์•Š๋Š”๋‹ค๊ณ  ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค ๐Ÿฅฒ

 

  • view์— ํ•œ ๋ฒˆ๋„ ์ ‘๊ทผํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ
  • push / present / addSubview ๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ
  • addChild๋งŒ ํ•˜๊ณ  view๋ฅผ ๊ณ„์ธต์— ๋„ฃ์ง€ ์•Š์€ ๊ฒฝ์šฐ
  • init์—์„œ ์•„๋ฌด view ์ ‘๊ทผ ์ฝ”๋“œ๋ฅผ ์“ฐ์ง€ ์•Š์€ ๊ฒฝ์šฐ

ex) ๊ฐ์ฒด๋งŒ ์ƒ์„ฑํ•˜๊ณ  push๋ฅผ ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ -> init ํ›„์— ๋ฐ”๋กœ deinit๋จ

let vc = DetailViewController()
// navigationController?.pushViewController(vc, animated: true)

class DetailViewController: UIViewController {
    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        print("โœ… init")
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func loadView() {
        view = MyCustomView()
        print("loadView") // โŒ
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
		print("viewDidLoad") // โŒ
    }
    
    ...
    
    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        print("viewDidDisappear") // โŒ
    }
    
    deinit {
        print("โœ… deinit")
    }
}

/*
โœ… init
โœ… deinit
*/

์œ„์™€ ๊ฐ™์€ ์ฝ”๋“œ์—์„œ๋Š” root view๋ฅผ ์ƒ์„ฑํ•˜๋Š” loadView()๋ฅผ ์•„์˜ˆ ํƒ€์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— MyCustomView๋„ ๋‹น์—ฐํžˆ ์ƒ์„ฑ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

 

 

๊ทธ๋Ÿผ loadView๋Š” ์™œ lazy ์ผ๊นŒ์š” ?

1. ๋ถˆํ•„์š”ํ•œ view loading์„ ๋ง‰์•„์„œ ๋ฉ”๋ชจ๋ฆฌ ์ ˆ์•ฝ

 

UI ๊ฐ์ฒด๋Š” init๋งŒ ํ•˜๊ณ  ์ฆ‰์‹œ ๋ณด์—ฌ์ง€์ง€ ์•Š๋Š” ๊ฒฝ์šฐ๋„ ์กด์žฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— 

๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์•„๊ปด์•ผ ํ•˜๋Š” ๋ชจ๋ฐ”์ผ ํ™˜๊ฒฝ์—์„œ๋Š” ๊ตณ์ด ๋ณด์ด์ง€๋„ ์•Š๋Š”๋ฐ ๋จผ์ € ๋ฉ”๋ชจ๋ฆฌ์— ๋งŒ๋“ค ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‹ค๋ณด๋‹ˆ ์ง„์งœ๋กœ ํ•„์š”ํ•ด์งˆ ๋•Œ๊นŒ์ง€ view ์ƒ์„ฑ์„ ์ตœ๋Œ€ํ•œ ๋Šฆ์ถฐ ๋ถˆํ•„์š”ํ•œ view์˜ loading์„ ๋ง‰๋Š” ๊ฒƒ์ด์ฃต

 

2. ์Šคํ† ๋ฆฌ๋ณด๋“œ / ์ฝ”๋“œ๋ฒ ์ด์Šค ์—์„œ์˜ ๋ทฐ ๋กœ๋”ฉ ๋กœ์ง ํ†ตํ•ฉ

 

super.loadView()๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ view๊ฐ€ ์—†์„๋•Œ UIView()๋ฅผ ์ƒ์„ฑํ•ด์„œ ํ• ๋‹นํ•ด์ฃผ๋Š” ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค.

๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— loadView๋ฅผ override ํ–ˆ์„๋•Œ ์Šคํ† ๋ฆฌ๋ณด๋“œ ๋ฐฉ์‹๊ณผ ์ฝ”๋“œ๋ฒ ์ด์Šค ๋ฐฉ์‹์—์„œ์˜ ๋‚ด๋ถ€ ๋™์ž‘์ด ์•ฝ๊ฐ„ ๋‹ค๋ฆ…๋‹ˆ๋‹ค.

  • ์Šคํ† ๋ฆฌ๋ณด๋“œ ๋ฐฉ์‹ : ๊ตฌ์„ฑ๋˜์–ด์žˆ๋Š” nib ๊ฐ์ฒด๋ฅผ ๋กœ๋“œ
  • ์ฝ”๋“œ๋ฒ ์ด์Šค ๋ฐฉ์‹ : overrideํ•ด์„œ UIView ์ฃผ์ž… ๋˜๋Š” ์ปค์Šคํ…€ view ์ฃผ์ž…
// ์ฝ”๋“œ๋ฒ ์ด์Šค
override func loadView {
	super.loadView() // view๊ฐ€ ์—†์œผ๋‹ˆ๊นŒ UIView() ์ƒ์„ฑํ•ด์„œ ํ• ๋‹น
}

// ์ฝ”๋“œ๋ฒ ์ด์Šค (์ปค์Šคํ…€ ๋ทฐ, ๋ฉ”๋ชจ๋ฆฌ ๋‚ญ๋น„ ๋ฒ„์ „)
override func loadView {
	super.loadView() // view๊ฐ€ ์—†์œผ๋‹ˆ๊นŒ UIView() ์ƒ์„ฑํ•ด์„œ ํ• ๋‹น
	view = CustomView() // ์ปค์Šคํ…€ ๋ทฐ๋กœ ๋ฐ”๊ฟ”์น˜๊ธฐ
}

// ์ฝ”๋“œ๋ฒ ์ด์Šค (์ปค์Šคํ…€ ๋ทฐ, ๋ฉ”๋ชจ๋ฆฌ ์ ˆ์•ฝ ๋ฒ„์ „)
override func loadView {
	view = CustomView() // ๋น„์–ด์žˆ๋Š” view์— ์ปค์Šคํ…€ ๋ทฐ ์ƒ์„ฑํ•ด์„œ ํ• ๋‹น
}

// ์Šคํ† ๋ฆฌ๋ณด๋“œ
override func loadView {
	super.loadView() // ์Šคํ† ๋ฆฌ๋ณด๋“œ์—์„œ ์ƒ์„ฑํ•œ view(nib)๋ฅผ ๋กœ๋“œํ•ด์˜ค๊ธฐ ๋•Œ๋ฌธ์— view๊ฐ€ ์žˆ์Œ -> UIView() ์ƒ์„ฑํ•ด์„œ ํ• ๋‹นํ•˜์ง€ ์•Š์Œ
}

// ์Šคํ† ๋ฆฌ๋ณด๋“œ (๋ฎ์–ด์“ฐ๊ธฐ)
override func loadView {
	view = CustomView() // ์Šคํ† ๋ฆฌ๋ณด๋“œ์—์„œ ์ƒ์„ฑํ•œ view๋ฅผ ๋ฎ์–ด์“ฐ๊ธฐํ•จ
}

 

*์Šคํ† ๋ฆฌ๋ณด๋“œ์—์„œ๋Š” override๋ฅผ ๊ถŒ์žฅํ•˜์ง€ ์•Š์Œ.

loadView์—์„œ override ํ•ด์„œ ์ƒˆ๋กœ์šด ์ปค์Šคํ…€ view๋ฅผ ํ• ๋‹นํ•ด๋ฒ„๋ฆฌ๋ฉด, ์Šคํ† ๋ฆฌ๋ณด๋“œ์—์„œ ๋งŒ๋“ค์–ด๋‘” UI๋ฅผ ๋ฎ์–ด๋ฒ„๋ฆผ

์š”๋ ‡๊ฒŒ ๋‹ค ๋งŒ๋“ค์–ด๋’€๋”๋‹ˆ ๋ฎ์–ด๋ฒ„๋ฆผ..

 

์•„๋ฌดํŠผ ๊ทธ๋ž˜์„œ 

์Šคํ† ๋ฆฌ๋ณด๋“œ ๋ฐฉ์‹์ผ๋•Œ๋ž‘ ์ฝ”๋“œ๋ฒ ์ด์Šค ๋ฐฉ์‹์ผ๋•Œ์˜ view ์ดˆ๊ธฐํ™” ํ๋ฆ„์„ ํ†ต์ผํ•˜๊ธฐ ์œ„ํ•ด

loadView()๋Š” lazyํ•˜๊ฒŒ ํ˜ธ์ถœ๋˜๋„๋ก ์„ค๊ณ„๋˜์–ด์žˆ์Šต๋‹ˆ๋‹ค.

 

loadView ์‚ฌ์šฉ์‹œ ์ฃผ์˜์‚ฌํ•ญ

 

1. ์ง์ ‘ ์ปค์Šคํ…€ view๋ฅผ ๋„ฃ์–ด์ฃผ๋Š” ๊ฒฝ์šฐ super.loadView() ํ˜ธ์ถœ์„ ๊ถŒ์žฅํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

 

์•ˆ๋˜๋Š”๊ฑด ์•„๋‹˜. ๊ทธ์น˜๋งŒ ๋น„ํšจ์œจ์ ์ธ ๋А๋‚Œ

override func loadView() {
	super.loadView() // view = UIView() ์ƒ์„ฑ๋œ ์ƒํƒœ
    // โžก๏ธ OS์—์„œ ์ž์ฒด ์ƒ์„ฑํ•œ UIView ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ: ObjectIdentifier(0x0000000102709990)
		
    view = MyCustomView()
    // โžก๏ธ ์ฝ”๋“œ๋กœ ์ง์ ‘ ๋„ฃ์–ด์ค€ MyCustomView ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ : ObjectIdentifier(0x0000000102604b10)
}

 

 

์ฝ”๋“œ๋ฒ ์ด์Šค๋ฅผ ๊ธฐ์ค€์œผ๋กœ super.loadView() ํ•˜๋Š” ์‹œ์ ์— ๋‚ด๋ถ€์ ์œผ๋กœ UIView()๋ฅผ ์ƒ์„ฑํ•ด์„œ self.view์— ํ• ๋‹น์„ ํ•ด์ฃผ๋Š”๋ฐ

์ดํ›„์— ๋ฐ”๋กœ ์ƒˆ๋กœ์šด ์ปค์Šคํ…€ ๋ทฐ๋ฅผ ์ƒ์„ฑํ•ด์„œ ๋„ฃ์–ด์ฃผ๋ฉด, ๊ธฐ์กด์— ์ƒ์„ฑํ–ˆ๋˜ ๋ทฐ๋Š” ๋ฉ”๋ชจ๋ฆฌ์— ๋‚จ์•„์žˆ๋‹ค๊ฐ€ ๋ฐ”๋กœ ๋ฒ„๋ ค์ง€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

์ฆ‰, ์•ˆ๋˜๋Š”๊ฑด ์•„๋‹ˆ์ง€๋งŒ ๋ถˆํ•„์š”ํ•œ ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น์ด ์ƒ๊ธฐ๊ธฐ ๋•Œ๋ฌธ์— ๊ถŒ์žฅํ•˜์ง€ ์•Š๋Š”๋‹ค~ ์ด๋Ÿฐ ๋А๋‚Œ์ž…๋‹ˆ๋‹ค.

 

2. loadView๋ฅผ override๋งŒ ํ•˜๋ฉด ์•ˆ๋ฉ๋‹ˆ๋‹ค.

 

์™œ๋ƒํ•˜๋ฉด ํฌ๋ž˜์‹œ ๋‚˜๋ฒ„๋ฆผ !

class ViewController: UIViewController {
    override func loadView() {
//        super.loadView()
//        view = MyCustomView()
        os_signpost(.event, log: log, name: "#0 loadView")
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        os_signpost(.event, log: log, name: "#1 viewDidLoad")
        setUI()
        getCurrentWeather()
    }
}

 

์™œ ํฌ๋ž˜์‹œ๊ฐ€ ๋‚˜๋ƒ๋ฉฐ๋Š” 

loadView๋Š” view๊ฐ€ nil์ผ๋•Œ ํ˜ธ์ถœ๋˜์–ด์„œ view์— ๊ฐ์ฒด๋ฅผ ํ• ๋‹นํ•ด์ฃผ๋Š” ์—ญํ• ์˜ ๋ฉ”์„œ๋“œ์ธ๋ฐ

 

์œ„ ์ฝ”๋“œ์ฒ˜๋Ÿผ ๋‚ด๋ถ€์—์„œ super.loadView()๋„ ์•ˆํ•˜๊ณ  ์ง์ ‘ view๋ฅผ ๋„ฃ์–ด์ฃผ์ง€๋„ ์•Š์•„๋ฒ„๋ฆฌ๋ฉด

viewDidLoad์— ๋„˜์–ด๊ฐ”๋‹ค๊ฐ€ view๊ฐ€ ๋น„์–ด์žˆ์œผ๋‹ˆ ๋‹ค์‹œ loadView๊ฐ€ ํ˜ธ์ถœ๋˜๊ณ  ๋˜ ๋‹ค์Œ์— viewDidLoad๊ฐ€ ํ˜ธ์ถœ๋๋Š”๋ฐ ๋˜ view๊ฐ€ ๋น„์–ด์žˆ์œผ๋‹ˆ๊นŒ ๋˜ ๋‹ค์‹œ loadView๊ฐ€ ํ˜ธ์ถœ๋˜๊ณ  .. 

๋‚œ๋ฆฌ๋‚œ๋ฆฌ ๋‚˜๋‹ค๊ฐ€ ๊ฒฐ๊ตญ ํ„ฐ์ ธ๋ฒ„๋ฆฌ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

๋‹น์—ฐํžˆ ๋ฉ”๋ชจ๋ฆฌ ์ƒ์— view๋„ ์—†์Œ

 

์‚ฌ์‹ค loadView๋ฅผ overrideํ•ด์„œ ์“ธ ์ผ์ด ๊ทธ๋‹ค์ง€ ๋งŽ์ง€ ์•Š์€ ๊ฒƒ ๊ฐ™์•„์„œ ๋ชฐ๋ผ๋„ ํฐ ๋ฌธ์ œ๋Š” ์—†๊ฒ ์ง€๋งŒ

ํ˜ธ์˜ฅ์‹œ๋‚˜ ์ง์ ‘ ์ปค์Šคํ…€ํ•œ ๋ทฐ๋ฅผ ๋„ฃ์–ด์ค˜์•ผ ํ•  ์ผ์ด ์ƒ๊ธด๋‹ค๋ฉด ๊ผฌ์˜ฅ ์ฃผ์˜ํ•˜์‹œ๊ธธ ๋ฐ”๋ž๋‹ˆ๋‹น

 


๊ฒฐ๋ก ์€ init ํ•œ๋‹ค๊ณ  ํ•ด์„œ loadView๊ฐ€ ๋ถˆ๋ฆฌ์ง„ ์•Š๋Š”๋‹ค

์ž…๋‹ˆ๋‹น

 

์ด์ œ์„œ์•ผ loadView๊ฐ€ ๋ญํ•˜๋Š” ๋…€์„์ธ์ง€ ์ •ํ™•ํ•˜๊ฒŒ ์•Œ๊ฒŒ ๋œ ๊ฒƒ ๊ฐ™์Šด๋‹ค ๐Ÿฅน

 

๋งˆ์ง€๋ง‰์œผ๋กœ UIViewController ๋ฉ”๋ชจ๋ฆฌ๋ž‘ ๋ทฐ ๊ณ„์ธต ๊ด€์ ์—์„œ ๋ณด๋Š” Life Cycle ๋ณด๋ฉด์„œ ๋งˆ๋ฌด๋ฆฌ

 

[โœ…  ๋ฉ”๋ชจ๋ฆฌ ๊ด€์  / ๐ŸŸ   ๋ทฐ ๊ณ„์ธต ๊ด€์ ]์—์„œ ์™„๋ฃŒ ์‹œ์ 