post-custom-banner

참고1
참고2

What are closures?

Closures are self-contained blocks of functionality that can be passed around and used in your code.

Swift 1.x와 2.x 버전에서는, closure 파라미터는 @escaping이 default이었다고 하며, Closure는 function의 body execution이 진행될 때, 탈출할 수 있다는 의미이다. 만약, Closure의 탈출 기능을 포함하지 않으려고 한다면, @nonescaping을 명시해야 했따.

Swift 3.x으로 넘어오면서, Apple은 해당 Closure에 변화를 주었다. @nonescaping이 default로 변화되었으며, closure는 function의 body excution과 동시에 실행되며, clousre를 탈출시키기 위해서는 @escaping을 명시해야 한다. 왜 Apple은 해당 변화를 주었을까? 이것에 대해 마지막에 토론하고자 한다. 😀

@nonescaping clousures:

Function argument로 closure를 넘긴다고 할 때, closure는 function body와 동시에 실행되며, Compiler를 반환한다. Exction 말미에는, scope 범위에서 벗어나며, 더이상 메모리에 상주하지 않는다.

Lifecycle of the @nonescaping closures:

1. Pass the closure as function argument, during the function call.
2. Do some additional work with function.
3. Function runs the closure.
4. Function returns the compiler back.

Example:

func getSumOf(array:[Int], handler: ((Int)->Void)) {
        //step 2
        var sum: Int = 0
        for value in array {
            sum += value
        }
        
        //step 3
        handler(sum)
    }
    
    func doSomething() {
        //setp 1
        self.getSumOf(array: [16,756,442,6,23]) { [weak self](sum) in
            print(sum)
            //step 4, finishing the execution
        }
    }
//It will print the sumof all the given numbers.

@escaping clousures

Closure를 Function Argument로 전달하면 Closure는 나중에 실행될 수 있도록 보존되고, Function Body가 실행되면 컴파일러가 다시 반환된다. 실행이 종료되면 전달된 Closure의 범위는 클로저가 실행될 때까지 메모리에 존재한다. Clousre를 Escaping하는 방법은 아래와 같다.

  1. Stroage : Memory에 존재하는 Closure를 Storage에 저장이 필요한 경우, 과거에 호출된 Function은 실행되고, 컴파일러를 반환한다(?무슨말이지)
  2. Asynchronous Execution : Dispatch queue에서 Closure를 비동기적으로 실행하는 경우, Queue는 Memory에서 Closure를 Hold하며, 나중에 사용할 수 있다.

Lifecycle of the @escaping closure:

  1. Pass the closure as function argument, during the function call.
  2. Do some additional work in function.
  3. Function execute the closure asynchronously or stored.
  4. Function returns the compiler back.

Example1 (Storage):

var complitionHandler: ((Int)->Void)?
    func getSumOf(array:[Int], handler: @escaping ((Int)->Void)) {
        //step 2
       //here I'm taking for loop just for example, in real case it'll be something else like API call
       var sum: Int = 0
        for value in array {
            sum += value
        }
//step 3
        self.complitionHandler = handler
    }
    
    func doSomething() {
        //setp 1
        self.getSumOf(array: [16,756,442,6,23]) { [weak self](sum) in
            print(sum)
            //step 4, finishing the execution
        }
    }
//Here we are storing the closure for future use.
//It will print the sumof all the passed numbers.

Example2 (Asynchronous Execution):

func getSumOf(array:[Int], handler: @escaping ((Int)->Void)) {
        //step 2
        var sum: Int = 0
        for value in array {
            sum += value
        }
        //step 3
        Globals.delay(0.3, closure: {
            handler(sum)
        })
    }
    
    func doSomething() {
        //setp 1
        self.getSumOf(array: [16,756,442,6,23]) { [weak self](sum) in
            print(sum)
            //step 4, finishing the execution
        }
    }
//Here we are calling the closure with the delay of 0.3 seconds
//It will print the sumof all the passed numbers.
profile
RTFM
post-custom-banner

0개의 댓글