Published on

🍎 Swift - ν΄λ‘œμ €(Closure).03

Authors
  • avatar
    Name
    이창쀀
    Twitter

μ΄λ²ˆμ—λŠ” @autoclosure와 @escaping에 λŒ€ν•΄ μ•Œμ•„λ³΄κ² μŠ΅λ‹ˆλ‹€.

@autoclosure

autoclosure도 μš°μ„  μš©μ–΄ 자체λ₯Ό μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

μžλ™-ν΄λ‘œμ €?

이게 λŒ€μ²΄ λ­˜κΉŒμš”?

μ΄λ²ˆμ—λŠ” μ •μ˜λ₯Ό μ‚΄νŽ΄λ΄…μ‹œλ‹€.

μΈμžλ‘œμ„œ μ „λ‹¬λœ 일반ꡬ문/ν•¨μˆ˜λ₯Ό ν΄λ‘œμ €λ‘œμ„œ κ°μ‹ΈλŠ” 것

μ•„λ¬΄λž˜λ„ 일반ꡬ문/ν•¨μˆ˜λ₯Ό μžλ™μœΌλ‘œ ν΄λ‘œμ €λ‘œμ„œ μ·¨κΈ‰ν•œλ‹€.. λΌλŠ” 의미인 것 κ°™λ„€μš”.

아직도 이해가 잘 가지 μ•ŠμœΌλ‹ˆ 예제λ₯Ό μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

func foo(closure: @autoclosure () -> ()) {
  // Tasks
}

@autoclosureκ°€ μ‚¬μš©λ˜λŠ” μœ„μΉ˜λ„ 잘 κΈ°μ–΅ν•΄μ£Όμ„Έμš”. 인자λͺ… λ’€ νƒ€μž… μ •μ˜ λ°”λ‘œ μ•žμ— μœ„μΉ˜ν•΄μžˆμŠ΅λ‹ˆλ‹€!

자 κ·Έλž˜μ„œ λŒ€μ²΄ 이게 λ¬΄μŠ¨λ§μ΄λƒ..

@autoclosure λ₯Ό μ‚¬μš©ν•˜λ©΄ ν΄λ‘œμ € νƒ€μž…μ˜ 인자 closureλŠ” ν΄λ‘œμ €κ°€ μ•„λ‹Œ 일반ꡬ문/ν•¨μˆ˜λ₯Ό 받아도 ν΄λ‘œμ €λ‘œμ„œ μ²˜λ¦¬ν•΄μ€λ‹ˆλ‹€.

μš°μ„  @autoclosureλ₯Ό μ‚¬μš©ν•˜μ§€ μ•Šμ•˜μ„ λ•Œλ₯Ό λ΄…μ‹œλ‹€.

func foo(_ closure: () -> Void) {
  closure()
}

μœ„ ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•  λ•Œ μ–΄λ–»κ²Œ ν˜ΈμΆœν• κΉŒμš”? μ•„λž˜μ™€ 같이 ν˜ΈμΆœν•©λ‹ˆλ‹€.

foo({ 
  print("Hi! I'm Closure")
})

μ΄λ²ˆμ—” 같은 ν•¨μˆ˜μ— @autoclosureλ₯Ό μ‚¬μš©ν•΄λ΄…μ‹œλ‹€.

func foo(_ closure: @autoclosure () -> Void) {
  closure()
}

μœ„ ν•¨μˆ˜λŠ” μ•„λž˜μ²˜λŸΌ ν˜ΈμΆœλ©λ‹ˆλ‹€.

foo(print("Hi! I'm Closure"))

{ … } 이 μ€‘κ΄„ν˜Έκ°€ 없어진 것을 λ³Ό 수 있죠.

ν΄λ‘œμ €λŠ” 본인이 ν΄λ‘œμ €μž„μ„ μ•Œλ¦¬κΈ° μœ„ν•΄ μ€‘κ΄„ν˜Έκ°€ 무쑰건 ν•„μš”ν•©λ‹ˆλ‹€. @autoclosureλŠ” ν΄λ‘œμ €κ°€ μ•„λ‹Œ 일반ꡬ문/ν•¨μˆ˜λ₯Ό μ€‘κ΄„ν˜Έλ‘œ 감싼 역할을 ν•΄μ£ΌλŠ” 것이죠.

단 μœ μ˜ν•  점은 @autoclosureλ₯Ό μ‚¬μš©ν•˜κΈ° μœ„ν•΄μ„œλŠ” ν΄λ‘œμ €μ˜ μΈμžκ°€ μ—†μ–΄μ•Ό ν•©λ‹ˆλ‹€!

func foo(closure: @autoclosure (Int) -> Void) {
  closure()
}

μœ„μ™€ 경우 (Int) -> Void 인자둜 Int νƒ€μž…μ΄ λ“€μ–΄κ°€μžˆμ£ ?

λ”°λΌμ„œ 였λ₯˜κ°€ λ‚©λ‹ˆλ‹€. κΌ­ μ£Όμ˜ν•΄μ£Όμ„Έμš”!

κ·Έλ ‡λ‹€λ©΄ μΌλ°˜κ΅¬λ¬Έμ— λΉ„ν•΄μ„œ @autoclosure을 μ‚¬μš©ν–ˆμ„ λ•Œμ˜ 차이점은 λ¬΄μ—‡μΌκΉŒμš”?

μΌλ°˜κ΅¬λ¬Έμ€ μ›λž˜ μ‹€ν–‰ μˆœμ„œκ°€ 되면 μ¦‰μ‹œ μ‹€ν–‰λ©λ‹ˆλ‹€.

지연을 μ€€λ‹€κ³  ν•˜λ”λΌλ„ 지연을 μ£ΌλŠ” ν•¨μˆ˜κ°€ μ¦‰μ‹œ μ‹€ν–‰λ˜μ—ˆκΈ° λ•Œλ¬Έμ— 뒀에 λ”°λΌμ˜€λŠ” λ‹€λ₯Έ ν•¨μˆ˜λ“€μ΄ μ§€μ—°λ˜λŠ” 것이죠.

그런데 ν΄λ‘œμ €λŠ” μ¦‰μ‹œ μ‹€ν–‰λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. ν•¨μˆ˜ μ•ˆμ—μ„œ ν•΄λ‹Ή μΈμžκ°€ μ‚¬μš©λ  λ•Œ μ‹€ν–‰λ˜μ£ .

결둠적으둜 @escaping은 μΌλ°˜κ΅¬λ¬Έμ„ ν΄λ‘œμ €μ²˜λŸΌ μ‚¬μš©ν•˜κ³  싢을 λ•Œ μœ μš©ν•œ κΈ°λŠ₯μž…λ‹ˆλ‹€.

@escaping

@escaping ν΄λ‘œμ €λž€ μš©μ–΄μ˜ μ΄λ¦„μ—μ„œ μœ μΆ”ν•  수 μžˆλ“―μ΄, ν•¨μˆ˜μ—μ„œ λ²—μ–΄λ‚˜μ„œλ„ 싀행될 수 μžˆλŠ” ν΄λ‘œμ €μž…λ‹ˆλ‹€.

@escaping ν΄λ‘œμ €λ₯Ό μ‚¬μš©ν•˜λ©΄ λ‹€μŒκ³Ό 같은 κΈ°λŠ₯을 μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

ν•¨μˆ˜κ°€ λλ‚œ 뒀에도 싀행될 수 μžˆλ‹€. μ€‘μ²©ν•¨μˆ˜μ—μ„œ μ€‘μ²©ν•¨μˆ˜λ₯Ό return ν•  수 μžˆλ‹€. λ³€μˆ˜/μƒμˆ˜μ— ν΄λ‘œμ €λ₯Ό λŒ€μž…ν•  수 μžˆλ‹€. 이 말은 μ§€κΈˆκΉŒμ§€ λ‹€λ€˜λ˜ ν΄λ‘œμ €λ“€μ€ μœ„μ˜ κ²½μš°λ“€μ΄ μ „λΆ€ λΆˆκ°€λŠ₯ν•˜λ‹€λŠ” μ†Œλ¦¬κ² μ£ ?

μ§€κΈˆκΉŒμ§€ λ‹€λ€„μ˜¨ ν΄λ‘œμ €λ“€ 같이 @escaping ꡬ문을 μ‚¬μš©ν•˜μ§€ μ•Šμ€ ν΄λ‘œμ €λ“€μ„ non-escaping closure라고 λΆ€λ¦…λ‹ˆλ‹€.

API 라이브러리인 Alamofire의 μ˜ˆμ‹œλ₯Ό λ³΄κ² μŠ΅λ‹ˆλ‹€.

func dataGET(from url: URL, completion: @escaping (AnyObject) -> ()) {
  DispatchQueue.global(qos: .background).async {
    Alamofire.request(url, method: .get).responseObject { (response: DataResponse<FilmResponse>) in 
    switch response.result {
    case .success(_):
      let res = response.result.value
      let resURL = res.results.imageID
      print(resURL ?? "No URL Found")
    case .failure(let error):
      print(error)
    }}
  }
}

ꡉμž₯히 λ³΅μž‘ν•΄λ³΄μ΄μ£ ? 사싀 λ‹€λ₯Έκ±΄ λ‹€ ν•„μš”μ—†μŠ΅λ‹ˆλ‹€.

func dateGET(from url: URL, completion: @escaping (AnyObject) -> ()) {
  DispatchQueue.global(qos: .background).async {
    // Blah Blah
  }
}

μ΄λ ‡κ²Œλ§Œ 보면 λ©λ‹ˆλ‹€.

이제 μš°λ¦¬λŠ” μ € ν•¨μˆ˜λ₯Ό 뢄석할 수 μžˆμŠ΅λ‹ˆλ‹€!

λ§ˆμ§€λ§‰ 인자둜 closureλ₯Ό μ‚¬μš©ν•˜μ—¬ Trailing Closure 방식이 μ±„νƒλ˜μ—ˆλ„€μš”. 또, @escaping ν΄λ‘œμ €κ°€ μ‚¬μš©λœ 것도 λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€. μ™œ μ‚¬μš©ν–ˆμ„κΉŒμš”?

API ν˜ΈμΆœμ€ μƒλŒ€μ μœΌλ‘œ λ§Žμ€ μ‹œκ°„μ΄ μ†Œμš”λ©λ‹ˆλ‹€. κ·Έλž˜μ„œ 보톡 λΉ„λ™κΈ°μ„±μœΌλ‘œ μ‹€ν–‰ν•˜μ£ . μœ μ €κ°€ λ‘œλ”©μ΄ λ‹€ 될 λ•ŒκΉŒμ§€ 먹톡이 된 앱을 κ°€λ§Œνžˆ 보고 μžˆμ§„ μ•Šμ„ν…Œλ‹ˆκΉŒμš”.

λ”°λΌμ„œ μœ„ ν•¨μˆ˜κ°€ μ™„λ£Œλ˜κΈ° 전에 DispatchQueue둜 μ‹€ν–‰ν•œ ꡬ문듀은 μ™„λ£Œλ˜μ—ˆμ„ κ°€λŠ₯성이 거의 μ „λ¬΄ν•©λ‹ˆλ‹€. μ—¬κΈ°μ„œ @escaping ν΄λ‘œμ €κ°€ μ•„λ‹ˆλΌ non-escaping ν΄λ‘œμ €λ₯Ό μ‚¬μš©ν–ˆλ‹€λ©΄..? ν•¨μˆ˜κ°€ μ’…λ£Œλ¨κ³Ό λ™μ‹œμ— ν•¨μˆ˜ μ•ˆμ—μ„œ μ‹€ν–‰λœ ν΄λ‘œμ €κΉŒμ§€ μ „λΆ€ μ’…λ£Œλ˜μ–΄ λ²„λ¦½λ‹ˆλ‹€. 저희가 μ›ν•˜λŠ” κ²°κ³ΌλŠ” μ ˆλŒ€ μ•„λ‹ˆμ£ .

그리고 μ• μ΄ˆμ— XCodeμ—μ„œ 이λ₯Ό ν—ˆμš©ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

Warning: Escaping closure captures non-escaping parameter

λΌλŠ” μ—λŸ¬ λ©”μ‹œμ§€λ₯Ό 좜λ ₯ν•˜λ©° λΉŒλ“œ μ—λŸ¬κ°€ λ‚˜μ£ .

μ΄λ ‡κ²Œ @autoclosure와 @escaping ν΄λ‘œμ €κΉŒμ§€ μ•Œμ•„λ΄€μŠ΅λ‹ˆλ‹€. @escaping ν΄λ‘œμ €λŠ” 온라인으둜 ν†΅μ‹ ν•˜λŠ” μ•±μ—μ„œλŠ” 거의 ν•„μˆ˜μ μœΌλ‘œ μ‚¬μš©λ²•μ„ μ•Œμ•„λ‘¬μ•Ό ν•˜λ‹ˆ κΌΌκΌΌν•˜κ²Œ κΈ°μ–΅ν•΄λ‘˜ ν•„μš”κ°€ μžˆμŠ΅λ‹ˆλ‹€. μ €μ²˜λŸΌ 헀맀지 μ•ŠμœΌλ €λ©΄ 말이죠 γ…œγ…œ