πŸ‘©πŸ»‍πŸ’»/혼곡

[Swift] Escaping Closure

yeggrrr🐼 2024. 4. 28. 20:41
728x90

 

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