Weak self - ehrldyd15/Swift_Skills GitHub Wiki

[weak self]์˜ ํ™œ์šฉ ๋ฐ ํ•„์š”์„ฑ

Automatic Reference Counting

Swift์˜ ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ๋Š” ARC(Automatic Reference Counting)์— ์˜ํ•ด ์ฒ˜๋ฆฌ๋œ๋‹ค.

ARC๋Š” ๋” ์ด์ƒ ํ•„์š”ํ•˜์ง€ ์•Š์€ ํด๋ž˜์Šค ์ธ์Šคํ„ด์Šค์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ•ด์ œํ•˜๊ธฐ ์œ„ํ•ด ์ž‘๋™ํ•œ๋‹ค.

ARC๋Š” ๋Œ€๋ถ€๋ถ„ ์ž์ฒด์ ์œผ๋กœ ์ž‘๋™ํ•˜์ง€๋งŒ ๋•Œ๋กœ๋Š” ๊ฐ์ฒด ๊ฐ„์˜ ๊ด€๊ณ„๋ฅผ ๋ช…ํ™•ํžˆ ํ•˜๊ธฐ ์œ„ํ•ด ์ถ”๊ฐ€ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•ด์•ผ ํ•œ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, ์†์„ฑ(property)์— Parent Controller์— ๋Œ€ํ•œ ์ฐธ์กฐ(reference)๋ฅผ ์ €์žฅํ•˜๋Š” Child Controller๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ

์ˆœํ™˜ ์ฐธ์กฐ(Retain Cycle)๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ํ•ด๋‹น ์†์„ฑ(property)์„ weak ํ‚ค์›Œ๋“œ๋กœ ํ‘œ์‹œํ•ด์•ผ ํ•œ๋‹ค.

๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜(Memory Leak)๊ฐ€ ์˜์‹ฌ๋˜๋Š” ๊ฒฝ์šฐ ๋‹ค์Œ ์ž‘์—…์„ ์ˆ˜ํ–‰ ํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ๊ฐ์ฒด๊ฐ€ ํ•ด์ œ(dismissed)๋œ ํ›„ deinitializer callback ์ฐพ๊ธฐ.
  • Optional ๊ฐ์ฒด๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ํ•ด์ œ(dismissed) ํ›„ ๊ฐ์ฒด๊ฐ€ nil์ธ์ง€ ํ™•์ธ.
  • ์•ฑ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์„ ๊ด€์ฐฐํ•˜์—ฌ ๊พธ์ค€ํžˆ ์ฆ๊ฐ€ํ•˜๋Š”์ง€ ํ™•์ธ.
  • Leaks and Allocations Instruments ์‚ฌ์šฉ.

1. [unowned self]์™€ [weak self]์ค‘ ์–ด๋–ค๊ฒƒ์„ ์จ์•ผํ• ๊นŒ?

[unowned self]

ํด๋กœ์ €๋Š” ์ •์˜๋œ ์ปจํ…์ŠคํŠธ์—์„œ ๋ชจ๋“  ์ƒ์ˆ˜ ๋˜๋Š” ๋ณ€์ˆ˜๋ฅผ ๊ฐ•๋ ฅํ•˜๊ฒŒ ์บก์ณํ•  ์ˆ˜ ์žˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, ํด๋กœ์ € ๋‚ด์—์„œ self๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ํด๋กœ์ € ๋ฒ”์œ„(scope)์˜ ์ˆ˜๋ช… ๊ธฐ๊ฐ„ ๋™์•ˆ self์— ๋Œ€ํ•œ strong reference๋ฅผ ์œ ์ง€ํ•œ๋‹ค.

self๊ฐ€ ์ด ํด๋กœ์ €์— ๋Œ€ํ•œ ์ฐธ์กฐ๋ฅผ ์œ ์ง€ํ•˜๋Š” ๊ฒฝ์šฐ(๋ฏธ๋ž˜ ์–ด๋А ์‹œ์ ์— ํ˜ธ์ถœํ•˜๊ธฐ ์œ„ํ•ด) strong reference cycle์„ ๊ฐ–๊ฒŒ ๋œ๋‹ค.

unowned์€ ์œ„์™€ ๊ฐ™์€ ์ˆœํ™˜ ์ฐธ์กฐ๋ฅผ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜์ด๋‹ค.

unowned์€ ์ˆœํ™˜ ์ฐธ์กฐ๋ฅผ ํ”ผํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” ๊ณผ์ •์—์„œ self๋ฅผ ๊ฐ•์ œ๋กœ unwrappingํ•˜๊ณ  ํ• ๋‹น์ด ํ•ด์ œ๋œ ํ›„์—๋„ ๋‚ด์šฉ์— ์•ก์„ธ์Šคํ•˜๋ ค๊ณ  ์‹œ๋„ํ•œ๋‹ค.

๋”ฐ๋ผ์„œ ์•ˆ์ „ํ•˜์ง€ ์•Š์€ ๋ฐฉ๋ฒ•์ด๋‹ค.

[weak self]

weak๋Š” ์ˆœํ™˜ ์ฐธ์กฐ๋ฅผ ํ”ผํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” ๊ณผ์ •์—์„œ self๋ฅผ Optional๋กœ ๋งŒ๋“ ๋‹ค.

Optional Chaining(ex: self?.)์„ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ ๋” ๋„๋ฆฌ ์‚ฌ์šฉ๋˜๊ณ  ์žˆ๋Š” ๋ฐฉ์‹์€

guard let ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•ด ํด๋กœ์ € ์‹œ์ž‘ ์‹œ self์— ๋Œ€ํ•œ ์ž„์‹œ ๊ฐ•ํ•œ ์ฐธ์กฐ๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด๋‹ค.

    // Example
    guard let self = self else { return }
    // Swift 4.2๋ถ€ํ„ฐ, guard let self = self ๊ตฌ๋ฌธ์— ๋Œ€ํ•œ ๊ณต์‹ ์ง€์›์ด ์ถ”๊ฐ€๋˜์–ด ์ด๊ฒƒ์ด ๊ฐ€๋Šฅํ•ด์กŒ๋‹ค.

Optional ์ฒ˜๋ฆฌ๋ฅผ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด weak๋ณด๋‹ค unowned๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ํด๋กœ์ € ์‹คํ–‰ ์ค‘์— ์ฐธ์กฐ๊ฐ€ ์ ˆ๋Œ€ nil์ด ๋˜์ง€ ์•Š์„ ๊ฒƒ์ด๋ผ๊ณ  ํ™•์‹ ํ•  ๋•Œ๋งŒ unowned๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

unowned๋Š” optional์„ ๊ฐ•์ œ๋กœ unwrappingํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์œผ๋ฉฐ, nil์ด ๋˜๋ฉด ์ถฉ๋Œ์ด ๋ฐœ์ƒํ•œ๋‹ค.

๋”ฐ๋ผ์„œ [weak self]๊ฐ€ ํ›จ์”ฌ ๋” ์•ˆ์ „ํ•œ ๋Œ€์•ˆ์ด๋‹ค.

2. Non-escaping closure vs. Escaping closure

[weak self]๊ฐ€ ํ›จ์”ฌ ์•ˆ์ „ํ•˜๋‹ค๋Š” ์‚ฌ์‹ค์„ ํ™•์ธํ–ˆ์œผ๋‹ˆ ๋ชจ๋“  ํด๋กœ์ €์—์„œ [weak self]๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ• ๊นŒ?

[Non-escaping closure]

Non-escaping closure๋Š” ๋ฒ”์œ„(scope) ๋‚ด์—์„œ ์‹คํ–‰๋œ๋‹ค.

์ฆ‰, ์ฝ”๋“œ๋ฅผ ์ฆ‰์‹œ ์‹คํ–‰ํ•˜๊ณ  ๋‚˜์ค‘์— ์ €์žฅํ•˜๊ฑฐ๋‚˜ ์‹คํ–‰ํ•  ์ˆ˜ ์—†๋‹ค.

Non-escaping closure(์˜ˆ: compactMap๊ณผ ๊ฐ™์€ ๊ณ ์ฐจ ํ•จ์ˆ˜)๋Š” ๊ฐ•๋ ฅํ•œ ์ฐธ์กฐ ์ฃผ๊ธฐ๋ฅผ ๋„์ž…ํ•  ์œ„ํ—˜์ด ์—†์œผ๋ฏ€๋กœ

weak ๋˜๋Š” unowned๋ฅผ ์‚ฌ์šฉํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.

[Escaping closure]

Escaping closure๋Š” ์ €์žฅ๋  ์ˆ˜ ์žˆ๊ณ  ๋‹ค๋ฅธ ํด๋กœ์ €๋กœ ์ „๋‹ฌ๋  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๋ฏธ๋ž˜์˜ ์–ด๋А ์‹œ์ ์— ์‹คํ–‰๋  ์ˆ˜ ์žˆ๋‹ค.

Escaping closure๋Š” ๋‹ค์Œ ๋‘ ์กฐ๊ฑด์ด ๋ชจ๋‘ ์ถฉ์กฑ๋˜๋Š” ๊ฒฝ์šฐ์— weak ๋˜๋Š” unowned๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

  • ํด๋กœ์ €๋Š” ์†์„ฑ์— ์ €์žฅ๋˜๊ฑฐ๋‚˜ ๋‹ค๋ฅธ ํด๋กœ์ €๋กœ ์ „๋‹ฌ๋œ๋‹ค.

  • ํด๋กœ์ € ๋‚ด๋ถ€์˜ ๊ฐ์ฒด(์˜ˆ: self)๋Š” ํด๋กœ์ €(๋˜๋Š” ์ „๋‹ฌ๋œ ๋‹ค๋ฅธ ํด๋กœ์ €)์— ๋Œ€ํ•œ ๊ฐ•๋ ฅํ•œ ์ฐธ์กฐ๋ฅผ ์œ ์ง€ํ•œ๋‹ค.

[Delayed Deallocation]

Delayed Deallocation๋Š” Escaping ๋ฐ Non-escaping ํด๋กœ์ €์—์„œ ๋‚˜ํƒ€๋‚˜๋Š” ๋ถ€์ž‘์šฉ์ด๋‹ค.

์ •ํ™•ํžˆ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋Š” ์•„๋‹ˆ์ง€๋งŒ ์›ํ•˜์ง€ ์•Š๋Š” ๋™์ž‘์œผ๋กœ ์ด์–ด์งˆ ์ˆ˜ ์žˆ๋‹ค.

(ex: Controller๋ฅผ ํ•ด์ฒดํ–ˆ์ง€๋งŒ ๋ณด๋ฅ˜ ์ค‘์ธ ๋ชจ๋“  ํด๋กœ์ € ์ž‘์—…์ด ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ํ•ด์ œ๋˜์ง€ ์•Š์Œ)

๊ธฐ๋ณธ์ ์œผ๋กœ ํด๋กœ์ €๋Š” ๋ณธ๋ฌธ์—์„œ ์ฐธ์กฐํ•˜๋Š” ๋ชจ๋“  ๊ฐ์ฒด๋ฅผ ๊ฐ•๋ ฅํ•˜๊ฒŒ ์บก์ฒ˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํด๋กœ์ € ๋ณธ๋ฌธ์ด๋‚˜ ๋ฒ”์œ„๊ฐ€ ์‚ด์•„์žˆ๋Š” ํ•œ ๊ฐ์ฒด๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ• ๋‹น ํ•ด์ œ๋˜๋Š” ๊ฒƒ์„ ๋ฐฉํ•ดํ•œ๋‹ค.

์ด ๊ฒฝ์šฐ Escaping ๋ฐ Non-escaping ํด๋กœ์ € ๋ชจ๋‘ [weak self]๋ฅผ ์‚ฌ์šฉํ•ด Delayed Deallocation๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค.

([weak unowned]๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ์ถฉ๋Œ์„ ์ผ์œผํ‚ค๊ฒŒ ๋  ๊ฒƒ์ด๋‹ค.)

3. โ€˜guard let self = selfโ€™ vs. Optional Chaining

[weak self]๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ Optional Chaining(ex: self?.)์„ ์‚ฌ์šฉํ•˜์—ฌ

self์— ์•ก์„ธ์Šคํ•˜๋Š” ๋Œ€์‹  guard let self = self๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฐœ์ƒํ•˜๋Š” ์ž ์žฌ์ ์ธ ๋ถ€์ž‘์šฉ์ด ์žˆ๋‹ค.

[โ€˜guard let self = self else { return }โ€™]

Delayed Deallocation๊ฐ€ ๋‚˜ํƒ€๋‚  ์ˆ˜ ์žˆ๋Š” ํด๋กœ์ €์—์„œ 'guard let self = self' ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด Delayed Deallocation๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์—†๋‹ค.

์—ฌ๊ธฐ์„œ 'guard let' ๊ตฌ๋ฌธ์ด ํ•˜๋Š” ์ผ์€ self๊ฐ€ nil๊ณผ ๊ฐ™์€์ง€ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•˜๊ณ , ๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒฝ์šฐ ๋ฒ”์œ„ ๊ธฐ๊ฐ„ ๋™์•ˆ self์— ๋Œ€ํ•œ ์ผ์‹œ์ ์ธ ๊ฐ•๋ ฅํ•œ ์ฐธ์กฐ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

๋‹ค์‹œ ๋งํ•˜๋ฉด, 'guard let' ๊ตฌ๋ฌธ์€ ํด๋กœ์ €์˜ ์ˆ˜๋ช… ๋™์•ˆ self๊ฐ€ ํ• ๋‹น ํ•ด์ œ๋˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•ด self๊ฐ€ ์œ ์ง€๋˜๋„๋ก ๋ณด์žฅํ•œ๋‹ค.

['self?.']

'guard let' ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ๋Œ€์‹  Optional Chaining(ex: self?.)์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ

ํด๋กœ์ €๊ฐ€ ์‹œ์ž‘ํ•  ๋•Œ ๊ฐ•๋ ฅํ•œ ์ฐธ์กฐ๋ฅผ ๋งŒ๋“œ๋Š” ๋Œ€์‹  ๋ชจ๋“  ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ์—์„œ self์— ๋Œ€ํ•œ nil ๊ฒ€์‚ฌ๋ฅผ ์ง„ํ–‰ํ•œ๋‹ค.

์ฆ‰, ํด๋กœ์ € ์‹คํ–‰ ์ค‘ ์–ด๋А ์‹œ์ ์—์„œ self๊ฐ€ nil์ด ๋˜๋ฉด ์ž๋™์œผ๋กœ ํ•ด๋‹น ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ์„ ๊ฑด๋„ˆ๋›ฐ๊ณ  ๋‹ค์Œ ์ค„๋กœ ์ด๋™ํ•œ๋‹ค.

guard let' ๊ตฌ๋ฌธ์€ ๊ฒฝ์šฐ์— ๋”ฐ๋ผ Delayed Deallocation๋กœ ์ด์–ด์งˆ ์ˆ˜ ์žˆ๋‹ค.

๋•Œ๋ฌธ์— ๊ฒฝ์šฐ์— ๋”ฐ๋ผ 'guard let' ๋ฐ 'Optional Chaining' ์ค‘ ์–ด๋–ค ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•ด์•ผ ํ• ์ง€ ์ƒ๊ฐํ•  ํ•„์š”๊ฐ€ ์žˆ๋‹ค.

  • ViewController๊ฐ€ ํ•ด์ œ(dismiss)๋œ ํ›„ ๋ถˆํ•„์š”ํ•œ ์ž‘์—…์„ ํ”ผํ•˜๋ ค๋Š” ๊ฒฝ์šฐ

  • ๊ฐ์ฒด๊ฐ€ ํ• ๋‹น ํ•ด์ œ ๋˜๊ธฐ ์ „ ๋ชจ๋“  ์ž‘์—…์ด ์™„๋ฃŒ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•˜๋ ค๋Š” ๊ฒฝ์šฐ(์˜ˆ: ๋ฐ์ดํ„ฐ ์†์ƒ ๋ฐฉ์ง€๋ฅผ ์œ„ํ•ด)

4. Common situations where [weak self] may or may not be needed.

[weak self]๊ฐ€ ํ•„์š”ํ•  ์ˆ˜๋„ ์žˆ๊ณ  ํ•„์š”ํ•˜์ง€ ์•Š์„ ์ˆ˜๋„ ์žˆ๋Š” ์ผ๋ฐ˜์ ์ธ ์ƒํ™ฉ ๋ช‡ ๊ฐ€์ง€๊ฐ€ ์žˆ๋‹ค.

[Grand Central Dispatch(GCD)]

GCD ํ˜ธ์ถœ์€ ๋‚˜์ค‘์— ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•ด ์ €์žฅํ•˜์ง€ ์•Š๋Š” ํ•œ ์ˆœํ™˜์ฐธ์กฐ์˜ ์œ„ํ—˜์ด ์—†๋‹ค.

    // ์˜ˆ๋ฅผ ๋“ค์–ด, ์ด๋Ÿฌํ•œ ํ˜ธ์ถœ์€ [weak self] ์—†์ด๋„ ์ฆ‰์‹œ ์‹คํ–‰๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋ฅผ ์ผ์œผํ‚ค์ง€ ์•Š๋Š”๋‹ค.
    func nonLeakyDispatchQueue() {
        DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
            self.view.backgroundColor = .red
        }

        DispatchQueue.main.async {
            self.view.backgroundColor = .red
        }

        DispatchQueue.global(qos: .background).async {
            print(self.navigationItem.description)
        }
    }

    // ๊ทธ๋Ÿฌ๋‚˜ ๋‹ค์Œ DispatchWorkItem์€ ์†์„ฑ(property)์— ์ €์žฅํ•˜๊ณ  [weak self] ํ‚ค์›Œ๋“œ ์—†์ด ํด๋กœ์ € ๋‚ด๋ถ€์—์„œ self๋ฅผ ์ฐธ์กฐํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
    func leakyDispatchQueue() {
        let workItem = DispatchWorkItem {
            self.view.backgroundColor = .red
        }

        DispatchQueue.main.asyncAfter(deadline: .now() + 1.0,
                          execute: workItem)

        self.workItem = workItem // stored in a property
    }

[UIView.Animate ๋ฐ UIViewPropertyAnimator]

GCD์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์• ๋‹ˆ๋ฉ”์ด์…˜ ํ˜ธ์ถœ๋„ ์†์„ฑ(property)์— UIViewPropertyAnimator๋ฅผ ์ €์žฅํ•˜์ง€ ์•Š๋Š” ํ•œ ์ˆœํ™˜์ฐธ์กฐ์˜ ์œ„ํ—˜์ด ์—†๋‹ค.

    // ์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค์Œ ํ˜ธ์ถœ์€ ์•ˆ์ „ํ•˜๋‹ค.
    func animteToRed() {
        UIView.animate(withDuration: 3.0) {
            self.view.backgroundColor = .red
        }
    }

    // ๋ฐ˜๋ฉด์— ๋‹ค์Œ ๋ฐฉ๋ฒ•์€ [weak self]๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ๋‚˜์ค‘์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์ €์žฅํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ˆœํ™˜์ฐธ์กฐ๋ฅผ ์œ ๋ฐœํ•œ๋‹ค.
    func setupAnimation() {
        let anim = UIViewPropertyAnimator(duration: 2.0,
                              curve: .linear) {
            self.view.backgroundColor = .red
        }
        
        anim.addCompletion { _ in
            self.view.backgroundColor = .white
        }
        
        self.animationStorage = anim
    }

[Storing a function in a property]

ํ•œ ๊ฐ์ฒด์˜ ํด๋กœ์ €๋‚˜ ํ•จ์ˆ˜๋ฅผ ๋‹ค๋ฅธ ๊ฐ์ฒด์— ์ „๋‹ฌํ•˜์—ฌ ์†์„ฑ์— ์ €์žฅํ•˜๋Š” ์ƒํ™ฉ์€ ๋ˆˆ์— ๋„์ง€ ์•Š๋Š” ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋ฅผ ์œ ๋ฐœํ•  ์ˆ˜ ์žˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, ์†์„ฑ(property)์— ํด๋กœ์ €๋ฅผ ์ €์žฅํ•˜๋Š” PresentedController๊ฐ€ ์žˆ๋‹ค.

    class PresentedController: UIViewController {
      var closure: (() -> Void)?
    }

๊ทธ๋ฆฌ๊ณ  PresentedController๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” MainViewController๊ฐ€ ์žˆ๊ณ ,

MainViewController์˜ printer() ๋ฉ”์†Œ๋“œ๋ฅผ PresentedController์˜ ํด๋กœ์ €์— ์ €์žฅํ•œ๋‹ค.

    class MainViewController: UIViewController {
      
      var presented = PresentedController()

      func setupClosure() {
        // ํ•จ์ˆ˜ ์ž์ฒด๋ฅผ ํ• ๋‹นํ•˜๊ธฐ ๋•Œ๋ฌธ์— ()๊ด„ํ˜ธ๋ฅผ ํฌํ•จํ•˜์ง€ ์•Š์Œ.
        presented.closure = printer
      }

      func printer() {
        print(self.view.description)
      }
    }

์ด์ œ PresentedController์—์„œ ํด๋กœ์ €๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด MainViewController์˜ self.view.description๋ฅผ ํ”„๋ฆฐํŠธํ•  ์ˆ˜ ์žˆ๋‹ค.

ํ•˜์ง€๋งŒ ์ด ์ฝ”๋“œ๋Š” ๋ช…์‹œ์ ์œผ๋กœ self๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•˜์Œ์—๋„ ์ˆœํ™˜์ฐธ์กฐ๋ฅผ ์œ ๋ฐœํ•œ๋‹ค.

self๋Š” printer์— ์•”์‹œ๋˜์–ด ์žˆ๋‹ค.(printer == self.priner)

๋”ฐ๋ผ์„œ ํด๋กœ์ €๋Š” self.printer์— ๋Œ€ํ•œ ๊ฐ•๋ ฅํ•œ ์ฐธ์กฐ๋ฅผ ์œ ์ง€ํ•˜๋Š” ๋ฐ˜๋ฉด self๋Š” ํด๋กœ์ €๋ฅผ ์†Œ์œ ํ•˜๋Š” PresentedController๋ฅผ ์†Œ์œ ํ•œ๋‹ค.

๋•Œ๋ฌธ์— ์ˆœํ™˜์ฐธ์กฐ๋ฅผ ์ œ๊ฑฐํ•˜๊ธฐ ์œ„ํ•ด [weak self]๋ฅผ ํฌํ•จํ•˜๋„๋ก setupClosure๋ฅผ ์ˆ˜์ •ํ•ด์•ผ ํ•œ๋‹ค.

    func setupClosure() {
        presented.closure = { [weak self] in
            // ๋ฒ”์œ„(scope) ๋‚ด์—์„œ ํ•ด๋‹น ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๊ธฐ๋ฅผ ์›ํ•˜๊ธฐ ๋•Œ๋ฌธ์—
            // ์ด๋ฒˆ์—๋Š” ํ”„๋ฆฐํ„ฐ ๋‹ค์Œ์— ()๊ด„ํ˜ธ๋ฅผ ํฌํ•จ.
            self?.printer()
        }
    }

[Timer]

Timer๋Š” ์†์„ฑ(property)์— ์ €์žฅํ•˜์ง€ ์•Š๋”๋ผ๋„ ๋ฌธ์ œ๋ฅผ ์ผ์œผํ‚ฌ ์ˆ˜ ์žˆ๋‹ค.

  • Timer๊ฐ€ ๋ฐ˜๋ณต๋œ๋‹ค.

  • [weak self]๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ํด๋กœ์ €์—์„œ self๋ฅผ ์ฐธ์กฐํ•œ๋‹ค.

์ด ๋‘ ์กฐ๊ฑด์ด ์ถฉ์กฑ๋˜๋Š” ํ•œ ํƒ€์ด๋จธ๋Š” ์ฐธ์กฐ๋œ ์ปจํŠธ๋กค๋Ÿฌ ๋˜๋Š” ๊ฐ์ฒด์˜ ํ• ๋‹น ํ•ด์ œ๋ฅผ ๋ฐฉ์ง€ํ•ฉ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ๊ธฐ์ˆ ์ ์œผ๋กœ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋ณด๋‹ค๋Š” Delayed Deallocation์— ๊ฐ€๊น๋‹ค.

Delayed Deallocation๋Š” ๋ฌดํ•œ์ • ์ง€์†๋œ๋‹ค.

์ฐธ์กฐ๋œ ๊ฐ์ฒด๋ฅผ ๋ฌด๊ธฐํ•œ ํ™œ์„ฑ ์ƒํƒœ๋กœ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์„ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด

๋” ์ด์ƒ ํ•„์š”ํ•˜์ง€ ์•Š์„ ๋•Œ ํƒ€์ด๋จธ๋ฅผ ๋ฌดํšจํ™”ํ•˜๊ณ  ์ฐธ์กฐ๋œ ๊ฐ์ฒด๊ฐ€ ํƒ€์ด๋จธ์— ๋Œ€ํ•œ ๊ฐ•ํ•œ ์ฐธ์กฐ๋ฅผ ์œ ์ง€ํ•˜๋Š” ๊ฒฝ์šฐ [weak self]๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

์ž๋ฃŒ ์ถœ์ฒ˜

https://velog.io/@haanwave/Article-You-dont-always-need-weak-self