Study/ํ˜ผ๊ณต

[Swift] Escaping Closure

yeggrrr๐Ÿผ 2024. 4. 28. 20:41

 

Escaping Closure
(์ด์Šค์ผ€์ดํ•‘ ํด๋กœ์ €)




์ด์Šค์ผ€์ดํ•‘ ํด๋กœ์ €๋Š”
ํด๋กœ์ €๊ฐ€ ํ•จ์ˆ˜ ์ธ์ž๋กœ ์ „๋‹ฌ๋์„ ๋•Œ, ํ•จ์ˆ˜์˜ ์‹คํ–‰์ด ์ข…๋ฃŒ๋œ ํ›„์— ์‹คํ–‰๋˜๋Š” ํ•จ์ˆ˜์—์š”!


(์—์ž‡.. ํด๋กœ์ €๋„ ์–ด๋ ค์šด๋ฐ, ์ด์Šค์ผ€์ดํ•‘ ํด๋กœ์ €๋Š” ๋˜ ๋ชจ์•ผ??๐Ÿ˜ก
์‹ถ์—ˆ์Šต๋‹ˆ๋‹ค..ํ•˜ํ•˜ํ•˜)

 

๊ทธ๋ฆฌ๊ณ  ๋ฐ˜๋Œ€๋กœ Non-escaping Closure๋„ ์žˆ์–ด์š”.
์ด๋…€์„์€ ํ•จ์ˆ˜๊ฐ€ ์ข…๋ฃŒ๋˜๊ธฐ ์ „์— ์‹คํ–‰๋˜๋Š” ํด๋กœ์ €์ž…๋‹ˆ๋‹ค!



์ด์ œ ์ฐจ๊ทผ์ฐจ๊ทผ ์˜ˆ์‹œ๋ฅผ ๋“ค์–ด ์ •๋ฆฌํ•ด๋ณผ๊ฒŒ์š”!!




 

func escapingClosureEX(completion: () -> Void) {
    completion()
}


์ด์ œ ์ด๋Ÿฐ ํ˜•ํƒœ๋Š” ํด๋กœ์ €๋ผ๋Š” ๊ฑด ์•Œ ์ˆ˜ ์žˆ์ฃ ?
ํด๋กœ์ €์˜ ๊ฐœ๋…์„ ์•„์ง ๋ชจ๋ฅด์‹ ๋‹ค๋ฉด,

 

7์ฃผ์ฐจ_5์ผ์ฐจ_์•ฑ ๊ฐœ๋ฐœ ์ˆ™๋ จ_Closure(ํด๋กœ์ €)_๊ฐœ์ธ๊ณต๋ถ€_TIL

TIL>์˜ค๋Š˜์€ ํด๋กœ์ €์— ๋Œ€ํ•ด์„œ ๊ณต๋ถ€ํ•ด๋ดค๋‹ค.์ด์ „์— ๊ณต๋ถ€ํ–ˆ์—ˆ๋Š”๋ฐ, ํ™•์‹คํ•˜๊ฒŒ ์ดํ•ดํ•˜๊ณ  ๋„˜์–ด๊ฐ„๊ฒŒ ์•„๋‹ˆ๋ผ์„œ ๋ง‰์ƒ ํด๋กœ์ €์— ๋Œ€ํ•ด์„œ ๋ง๋กœ ์„ค๋ช…ํ•˜๋ ค๊ณ  ๋ณด๋‹ˆ๊นŒ๋จน์€ ๊ฒƒ ๊ฐ™์•˜๋‹ค.(๊ณผ๊ฑฐ ํด๋กœ์ € ์ •๋ฆฌํ–ˆ๋˜ ๋‚ด ์ž

yegenie-coding.tistory.com


์ด๊ฑฐ ๋จผ์ € ๋ณด๊ณ  ์˜ค์‹œ์ฃ !๐Ÿ˜†



์ž. ๋‹ค์‹œ ๋Œ์•„์™€๋ณผ๊ฒŒ์š”.

func escapingClosureEX(completion: () -> Void) {
    completion()
}


์œ„ ์ฝ”๋“œ์—์„œ completion์˜ ํƒ€์ž…์€ ๋งค๊ฐœ๋ณ€์ˆ˜๋„ ์—†๊ณ  ๋ฆฌํ„ด ํƒ€์ž…๋„ ์—†๋Š” ํ˜•ํƒœ์ž…๋‹ˆ๋‹ค.

๊ทธ์น˜๋งŒ, ํด๋กœ์ €๋Š” 1๊ธ‰ ๊ฐ์ฒด๋ผ์„œ ๋ณ€์ˆ˜๋‚˜ ์ƒ์ˆ˜์— ๋Œ€์ž…์ด ๊ฐ€๋Šฅํ•˜๊ณ , ํŒŒ๋ผ๋ฏธํ„ฐ ์ธ์ž๋กœ ๋„˜๊ฒจ์ค„ ์ˆ˜ ์žˆ์ฃ !

escapingClosureEX {
    print("์˜คํ˜ธ!")
} // ์˜คํ˜ธ!

์ด๋ ‡๊ฒŒ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ํ•จ์ˆ˜๋ฅผ ๋„˜๊ฒจ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค!




์ž ์ด์ œ ์—ฌ๊ธฐ์„œ completion์— ์ €์žฅ๋œ ํด๋กœ์ €๋ฅผ  5์ดˆ ๋’ค์— ์‹คํ–‰์‹œํ‚ค๊ณ  ์‹ถ๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ์š”?

func escapingClosureEX(completion: () -> Void) {
    DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
        completion()
    } // Error: Escaping closure captures non-escaping parameter 'completion'
}


์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋˜๊ฒ ์ฃ ?

๊ทผ๋ฐ.. 

์ด๋Ÿฐ error๊ฐ€ ๋œน๋‹ˆ๋‹ค..


์ด์œ ๊ฐ€ ๋ญ˜๊นŒ์š”??๐Ÿค”


ํ‚ค์›Œ๋“œ ์—†์ด ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›๋Š” ํด๋กœ์ €๋Š” ๋ชจ๋‘
์œ„์—์„œ ์–ธ๊ธ‰ํ–ˆ๋˜ Non-escaping closure ์ž…๋‹ˆ๋‹ค.

์ฆ‰, 5์ดˆ ๋’ค์— completion ํด๋กœ์ €๊ฐ€ ์‹คํ–‰๋˜๊ฒŒ ์ฝ”๋“œ๋ฅผ ์ผ์ง€๋งŒ,
ํ•จ์ˆ˜๊ฐ€ ์ข…๋ฃŒ๋จ๊ณผ ๋™์‹œ์— ํด๋กœ์ €๋„ ํ•จ๊ป˜ ์ข…๋ฃŒ๋œ ๊ฑฐ์ฃ ..

๊ทธ๋ž˜์„œ ํ•จ์ˆ˜์˜ ํ๋ฆ„์—์„œ ๋ฒ—์–ด๋‚˜ ํ˜ธ์ถœ๋˜์–ด์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์—
"completion์€ Non-escaping parameter์•ผ!!"๋ผ๊ณ  ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์•Œ๋ ค์ค€๊ฑฐ์—์š”.


์ž!! ๋‹ค์‹œ ์ •๋ฆฌํ•ด๋ณด์ž๋ฉด,

completion์€ Non-escaping Closure(๋ง ๊ทธ๋Œ€๋กœ ํƒˆ์ถœ์ด ๋ถˆ๊ฐ€๋Šฅํ•œ ํด๋กœ์ €)๋ผ์„œ
ํ•จ์ˆ˜๊ฐ€ ์ข…๋ฃŒ๋˜๊ณ  ๋‚œ ํ›„์— ํด๋กœ์ €๊ฐ€ ์‹คํ–‰๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
๊ทธ๋ž˜์„œ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” @escaping ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.


<Non-escaping Closure>
1. ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ ์ง์ ‘ ์‹คํ–‰ํ•  ๋•Œ๋งŒ ์‚ฌ์šฉ
2. ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›์€ ํด๋กœ์ €๋Š” ์ƒ์ˆ˜๋‚˜ ๋ณ€์ˆ˜์— ๋Œ€์ž…ํ•  ์ˆ˜ ์—†์Œ



error๊ฐ€ ๋ฐœ์ƒํ•˜๋‹ˆ๊นŒ!
completion()์€ ์ง€์šฐ๊ณ , print๋ฌธ์„ ๋„ฃ์–ด์„œ ํ๋ฆ„์„ ํ•œ ๋ฒˆ ์‚ดํŽด๋ด…์‹œ๋‹ค.

func escapingClosureEX(completion: () -> Void) {
    print("1")
    DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
        print("2")
    }
    print("3")
}

escapingClosureEX {
}
print("4")

/*
 1
 3
 4
 2
*/


์œ„ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ด๋ณด๋ฉด,
์ด๋ ‡๊ฒŒ 1, 3, 4๊ฐ€ ๋จผ์ € print ๋˜๊ณ , 2๊ฐ€ print ๋˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

@escaping ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•˜์ง€๋งŒ,
ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ 5์ดˆ ๋’ค์— ์‹คํ–‰๋˜๋Š” asyncAfter๋ฅผ ์‚ฌ์šฉํ–ˆ๊ธฐ ๋•Œ๋ฌธ์—
ํ•จ์ˆ˜์˜ ์ƒ๋ช…์ฃผ๊ธฐ๊ฐ€ ๋๋‚œ ํ›„์—๋„ ์‹คํ–‰๋œ ๊ฒ๋‹ˆ๋‹ค.




๊ทธ๋Ÿผ..
ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›์€ ํด๋กœ์ €๋ฅผ ๋น„๋™๊ธฐ๋กœ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์„ ๋•Œ & ํ•จ์ˆ˜์˜ ํ๋ฆ„์—์„œ ํƒˆ์ถœํ•˜๊ณ  ์‹ถ์„ ๋•Œ

์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ์š”?๐Ÿค”


๋ฐ”๋กœ ์œ„์—์„œ ์–ธ๊ธ‰ํ–ˆ๋˜ @escaping ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค!!


๊ณต๋ถ€ํ•˜๋ฉด์„œ, (completion: @escaping ~~) ์ด๋ ‡๊ฒŒ ์ƒ๊ธด ๊ฑฐ ๋ณธ ์  ์žˆ์œผ์‹ ๊ฐ€์š”?

์ด๊ฒŒ ๋ฐ”๋กœ Escaping Closure ์ž…๋‹ˆ๋‹ค!
completion์˜ ํƒ€์ž…์— @escaping์„ ๋ถ™์—ฌ์„œ Escaping Closure(์ด์Šค์ผ€์ดํ•‘ ํด๋กœ์ €)๋ผ๋Š” ๊ฒƒ์„ ๋ช…์‹œํ•ด ์ฃผ๋Š” ๊ฒ๋‹ˆ๋‹ค.

๋ถ™์ด๋Š” ์ˆœ๊ฐ„
'์ด ํด๋กœ์ €๋Š” ํ•จ์ˆ˜ ์‹คํ–‰์˜ ํ๋ฆ„๊ณผ ์ƒ๊ด€์—†์ด ์ข…๋ฃŒ๋œ ์ดํ›„์—๋„ ์‹คํ–‰๋˜๋Š” ๋…€์„์ด์•ผ!'๋ผ๊ณ  ๋งํ•ด์ฃผ๋Š” ๊ฑฐ์ฃ ใ…Žใ…Ž

func escapingClosureEX(completion: @escaping () -> Void) {
    DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
        completion()
    }
}


์ž! ์•„๊นŒ ์—๋Ÿฌ ๋ฐœ์ƒํ–ˆ๋˜ ์ฝ”๋“œ์—์„œ @escaping ํ‚ค์›Œ๋“œ๋ฅผ ๋„ฃ์–ด์คฌ๋”๋‹ˆ
์ด์ œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์ฃ ?

@escaping ํ‚ค์›Œ๋“œ๋Š” ์ฃผ๋กœ ์ฝœ๋ฐฑ ํŒจํ„ด์— ์‚ฌ์šฉ๋˜๊ณ ,
๋น„๋™๊ธฐ ์ž‘์—…์ด ์™„๋ฃŒ๋œ ์ดํ›„์˜ ๊ฒฐ๊ณผ๋ฅผ ํด๋กœ์ €๋ฅผ ํ†ตํ•ด ๋ฐ˜ํ™˜ํ•ด ์ค๋‹ˆ๋‹ค.

 escapingClosureEX {
     print("(5์ดˆ ๋’ค) ์ง !")
 }
 print("ํ•จ์ˆ˜ ๋!")

/*
 ํ•จ์ˆ˜ ๋!
 (5์ดˆ ๋’ค) ์ง !
*/

์‹คํ–‰ํ•ด๋ณด๋ฉด,
completion์ด ์ž˜ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค!!



๊ทธ๋Ÿผ ์ด Escaping Closure๋Š” ์–ธ์ œ ํ™œ์šฉํ•˜๊ฒŒ ๋ ๊นŒ์š”?
์ €๋Š” ์ด๋ฒˆ ํŒ€ ํ”„๋กœ์ ํŠธ๋ฅผ ํ•˜๋ฉด์„œ ๋งŒ๋‚˜๊ฒŒ ๋์Šต๋‹ˆ๋‹ค..ใ…Ž

์˜ํ™” ๊ฒ€์ƒ‰ ํŽ˜์ด์ง€๋ฅผ ๋‹ด๋‹นํ–ˆ์—ˆ๋Š”๋ฐ,

1. ๊ฒ€์ƒ‰์–ด๋ฅผ ์ž…๋ ฅํ•˜์ง€ ์•Š์•˜์„ ๊ฒฝ์šฐ
2. ๊ฒ€์ƒ‰์–ด์— ํ•ด๋‹นํ•˜๋Š” ์˜ํ™”๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ

์ด ๋‘ ๊ฐ€์ง€ ๊ฒฝ์šฐ์— Label๋กœ ๋ฌธ๊ตฌ๋ฅผ ๋„ฃ์–ด์ฃผ๊ณ  ์‹ถ์—ˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ URLSession์œผ๋กœ data๋ฅผ ๋ฐ›์•„์˜ค๋Š” ํ•จ์ˆ˜์—์„œ
if ๋ฌธ์„ ํ™œ์šฉํ•ด์„œ
'๊ฒ€์ƒ‰์–ด ์—†์Œ' & '์ด๋Ÿฐ! ์ฐพ์œผ์‹œ๋Š” ์ž‘ํ’ˆ์ด ์—†์Šต๋‹ˆ๋‹ค.'
๋ผ๋Š” ๋ฌธ๊ตฌ๊ฐ€ ๋‚˜์˜ค๋„๋ก ์ฝ”๋“œ๋ฅผ ์งฐ์—ˆ์–ด์š”!



๊ทธ๋Ÿฐ๋ฐ.. ์–ด๋–ค ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋Š๋ƒ!!๐Ÿคฏ๐Ÿ˜ฑ๐Ÿคฏ๐Ÿ˜ฑ


๋ฐ์ดํ„ฐ๊ฐ€ ๋„˜์–ด์˜จ ์ดํ›„์— ํ•ด๋‹น ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋˜์–ด์•ผ ํ•˜๋Š”๋ฐ,
๋ฐ์ดํ„ฐ๊ฐ€ ๋„˜์–ด์˜ค๊ธฐ ์ „, ๋„˜์–ด์˜จ ํ›„.. 

์‹คํ–‰ ์ˆœ์„œ๊ฐ€ ๋งž์ง€ ์•Š์•„์„œ

๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ๋Š”๋ฐ๋„ ๋ถˆ๊ตฌํ•˜๊ณ ,
'์ด๋Ÿฐ! ์ฐพ์œผ์‹œ๋Š” ์ž‘ํ’ˆ์ด ์—†์Šต๋‹ˆ๋‹ค.'๋ผ๋Š” ๋ฌธ๊ตฌ๊ฐ€
์˜ํ™” ๋ชฉ๋ก๋“ค ๋’ค์— ํ•จ๊ป˜ ๋‚˜์˜ค๋Š”๊ฑฐ์—์š”..

์ด๋Ÿด ๋•Œ!! ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋ฐ”๋กœ Escaping Closure(์ด์Šค์ผ€์ดํ•‘ ํด๋กœ์ €)์ž…๋‹ˆ๋‹ค!!




์ด๋ ‡๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์˜ค๋Š” ํ•จ์ˆ˜์—
@escaping ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์ฃผ๊ณ , ๋ฆฌํ„ด๊ฐ’์„ ๋น„์›Œ๋’€์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ ๋‹ค์Œ

if ๋ฌธ์œผ๋กœ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ–‡๋˜ ๋ถ€๋ถ„์—์„œ!

escaping ํด๋กœ์ € ์•ˆ์— ์กฐ๊ฑด๋ฌธ์„ ๋„ฃ์–ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด!!

getData()๋ผ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์˜ค๋Š” ํ•จ์ˆ˜๊ฐ€ ๋ชจ๋‘ ์™„๋ฃŒ๋œ ํ›„์—
์ด ์กฐ๊ฑด๋ฌธ์„ ์‹คํ–‰๋˜๋„๋ก ์ฝ”๋“œ๋ฅผ ๋ฐ”๊พผ๊ฑฐ์—์š”.


์—ฌ๊ธฐ์„œ UI์— ๊ด€๋ จ๋œ ๊ฑด main thread๊ฐ€ ๋‹ด๋‹นํ•ด์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์—
์œ„์™€ ๊ฐ™์€ ์•Œ๋ฆผ์ด ๋œฐ๊ฒ๋‹ˆ๋‹ค.
์ด๊ฑด DispatchQueue.main.async{} ์•ˆ์— ๋„ฃ์–ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค. 
('mainํ•œํ…Œ ์ผ์„ ์‹œํ‚ค๋Š” ๋ช…๋ น์–ด'๋ผ๊ณ  ์ƒ๊ฐํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.)


 

0


@escaping ํ‚ค์›Œ๋“œ ํ•˜๋‚˜๋กœ..
์ œ๋Œ€๋กœ ์ž‘๋™ํ•˜๋Š” ๊ฑธ ๋ณด๊ณ .. ๊ฒฝ์•…ํ–ˆ์Šต๋‹ˆ๋‹ค..

๊ณต๋ถ€ํ• ๊ฒŒ ์‚ฐ๋”๋ฏธ๊ตฌ๋‚˜.. ์‹ถ์—ˆ์–ด์š”..ใ…Žใ…Ž๐Ÿ˜ฉ





escaping ํด๋กœ์ €๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด, ์ด๋Ÿฐ ๋ถ€๋ถ„๋“ค์„ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์ง€๋งŒ!!
๋ฌธ์ œ์ ๋“ค๋„ ์žˆ๋‹ค๊ณ  ํ•ด์š”.


1. ์ฝœ๋ฐฑ ์ค‘์ฒฉ์œผ๋กœ ์ธํ•ด ์ฝ”๋“œ๊ฐ€ ๋ณต์žกํ•ด์งˆ ๊ฐ€๋Šฅ์„ฑ ์žˆ์Œ
2. ์—๋Ÿฌ ์ฒ˜๋ฆฌ๊ฐ€ ์–ด๋ ค์›Œ์งˆ ์ˆ˜ ์žˆ์–ด ์ฝœ๋ฐฑ ๋‚ด์—์„œ ๋ฐœ์ƒํ•˜๋Š” ๊ฐ•ํ•œ ์ฐธ์กฐ ์ˆœํ™˜์„ ์ฃผ์˜ํ•ด์•ผํ•จ


์Œ.. ๊ฐ•ํ•œ ์ฐธ์กฐ ์ˆœํ™˜์€ ๋˜ ๋ญ์•ผ..???

๋„ค.. ๋‹ค์Œ ๊ฒŒ์‹œ๋ฌผ ์Šคํฌ๋ฅผ ์œ„ํ•œ ๋–ก๋ฐฅ์ด์—ˆ์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ ๊ฒŒ์‹œ๋ฌผ ์ฃผ์ œ๋Š” ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌํ•ด์ฃผ๋Š” ์นœ๊ตฌ ARC ์ž…๋‹ˆ๋‹ค!!

์•„๋งˆ.. ๋‹ค์Œ ์ฃผ์— ์ •๋ฆฌํ•  ๊ฒƒ ๊ฐ™์•„์š”..ใ…Ž
(์ด๋ ‡๊ฒŒ ๋˜ ํ•œ ์ฃผ ๋ฐ€๋ฆฌ๋Š” ARC..)


To be continue...โ›ง






728x90