- Swift Document - Closure
https://docs.swift.org/swift-book/LanguageGuide/Closures.html
A closure is said to escape a function when the closure is passed as an argument to the function, but is called after the function returns.
- ν΄λ‘μ κ° ν¨μμ μΈμλ‘ μ λ¬λμ§λ§ ν¨μκ° μ’ λ£λ λ€ μ€νλλ κ²μ escape - νμΆ νλ€κ³ νλ€.
π μΈμλ‘ μ λ¬λ ν΄λ‘μ κ° ν¨μμ λ°μ λ³μμ μ μ₯λκ±°λ ν¨μκ° μ’ λ£λ λ€ μ€νλλ ν΄λ‘μ λ₯Ό escaping ν΄λ‘μ λΌκ³ ν©λλ€.
νκ°μ§ μμλ‘ νλΌλ―Έν°λ‘ μ λ¬λ ν΄λ‘μ κ° ν¨μ λ°μ λ³μμ μ μ₯λλ κ²½μ°κ° μμ΅λλ€.
class testClass {
var property : (() -> Void)?
func closureFunc(_ closure : () -> Void ) {
self.property = closure // Error
}
}
μμ ν΄λ‘μ λ non-escaping ν΄λ‘μ
λΌκ³ λΆλ₯΄κ³ , ν¨μ λ°μ λ³μμ μΈμλ‘ μ λ¬λ ν΄λ‘μ λμ
μ μλνλ©΄ μ»΄νμΌ νμ μλ¬κ° λ°μν©λλ€.
ν¨μ λ°μμ μΈμλ‘ μ λ¬λ ν΄λ‘μ λ₯Ό μ¬μ©νκ³ μΆλ€λ©΄ @escaping
ν€μλλ₯Ό μ¬μ©ν©λλ€.
class testClass {
var property : (() -> Void)?
func closureFunc(_ closure : @escaping () -> Void ) {
self.property = closure
}
}
@escaping
ν€μλκ° λΆμ νλΌλ―Έν°μnon-escaping
ν΄λ‘μ λ₯Ό μ λ¬ν μ μμ§λ§
@escaping
ν€μλκ° λΆμ§ μμ νλΌλ―Έν°μescaping
ν΄λ‘μ λ₯Ό μ λ¬ν μλ μμ΅λλ€.
As an example, many functions that start an asynchronous operation take a closure argument as a completion handler. The function returns after it starts the operation, but the closure isnβt called until the operation is completed the closure needs to escape, to be called later.
- escaping ν΄λ‘μ λ completion handler, μ¦ ν¨μμ κ²°κ³Όμ λ°λΌ λ€λ₯΄κ² λμνλλ‘ λΉλκΈ°μ μ²λ¦¬λ₯Ό μꡬνλ ν¨μμμ νμ©ν μ μμ΅λλ€.
νν λΉλκΈ°λ‘ μ€νλλ Http requestμ completion hanlderμ μ¬μ©ν μ μμ΅λλ€. μλ²μ μμ²μ 보λ΄κ³ μλ΅μ λ°λΌ λ€λ₯Έ νλμ΄ νμν κ²½μ° μ¬μ©ν©λλ€.
func refrshToken(completion : @escaping (Result<Bool, Error>) -> ()) {
let url = baseURL + "/token"
AF.request(url,
method: .get,
interceptor: authorizationInterceptor()
).responseJSON { response in
guard let statusCode = response.response?.statusCode else { return }
switch statusCode {
case 200 :
print("Refresh token success (\(statusCode))")
completion(.success(true)) // β
default :
completion(.success(false)) // β
}
print(response)
}
...
}
////////
...
refrshToken { result in
switch result {
case .success(true) : // β
completion(.retryWithDelay(TimeInterval(1.0)))
case .success(false) : // β
print("Token refresh error - Expired refresh token error")
userInfo = nil
loginType = nil
case let .failure(error) :
print("Retry error : " + error.localizedDescription)
}
}
- (2022-07-24) κ°ν μν μ°Έμ‘°μ λν΄ μ‘°κΈ λ μμΈνκ² ν¬μ€ν νμ΅λλ€!!
π [Swift] κ°ν μν μ°Έμ‘°μ ν΄κ²° λ°©λ² (weak, unowned)
An escaping closure that refers to self needs special consideration if self refers to an instance of a class. Capturing self in an escaping closure makes it easy to accidentally create a strong reference cycle.
- escaping ν΄λ‘μ κ° ν΄λμ€ λ΄λΆμ μΈμ€ν΄μ€λ₯Ό μ°Έμ‘°ν λλ κ°ν μν μ°Έμ‘°λ₯Ό μΌμΌν¬ μ μκΈ° λλ¬Έμ νΉλ³ν μ£Όμκ° νμν©λλ€!
ν΄λ‘μ μ 컨νμ€νΈ μΊ‘μ² (Context caputre) λΌλ νΉμ±λλ¬Έμ ν΄λ‘μ μμ ν΄λμ€ λ΄λΆμ μΈμ€ν΄μ€λ₯Ό μ°Έμ‘°ν λλ κ°ν μν μ°Έμ‘° λ₯Ό μΌμΌμΌ λ©λͺ¨λ¦¬ λμλ₯Ό λ°μμν¬ μ μμ΅λλ€.
κ·Έλ κΈ° λλ¬Έμ ν΄λ‘μ λ΄λΆμμλ μν μ°Έμ‘°λ₯Ό λ°©μ§νκΈ°μν΄ [weak self] ν€μλλ₯Ό μ¬μ©ν©λλ€.
var userInfo : UserInfo? // β
var loginType : LoginType? // β
...
refrshToken { [weak self] result in
switch result {
case .success(true) :
completion(.retryWithDelay(TimeInterval(1.0)))
case .success(false) :
print("Token refresh error - Expired refresh token error")
self?.userInfo = nil // β
self?.loginType = nil // β
case let .failure(error) :
print("Retry error : " + error.localizedDescription)
}
}
μ€λμ μ€μννΈλ₯Ό λμ± νμ©μ μΌλ‘ λ§λ€μ΄μ£Όλ escaping ν΄λ‘μ μ λν΄ μμ보μμ΅λλ€.
νλ¦° μ 보 λλ κΆκΈν μ μ΄ μλ€λ©΄ λκΈ λΆνλ립λλ€! μ½μ΄μ£Όμ μ κ°μ¬ν©λλ€βΌοΈ
κΉλν μ 리 κ°μ¬ν©λλ€:)