티스토리 뷰

! 공식문서를 참고한 글입니다

 

캡쳐리스트 Capture Lists

기본적으로 클로저는 주변에서 클로저 안에서 사용할 때 필요한 상수와 변수를 캡쳐함

이때 어떻게 밸류를 캡쳐할 것인지 캡쳐리스트를 사용해서 컨트롤 할 수 있음

 

var a = 0
var b = 0
let closure = { [a] in
 print(a, b)
}

a = 10
b = 10
closure() // Prints "0 10"

캡처리스트는 대괄호를 사용하여 파라미터 앞에 명시함

클로저에서 매개변수 이름, 타입, 반환타입을 생략하더라도 캡처리스트를 사용하려면 in 키워드를 사용해야함

캡처리스트는 생성될 때 초기화 되기 때문에 a는 0으로 표시됨

 

만약 캡쳐한 변수가 참조타입이라면 원래의 인스턴스를 참조해서 캡쳐한다고 생각할 수 있음

class SimpleClass {
    var value: Int = 0
}
var x = SimpleClass() // 클래스는 참조타입
var y = 0 // 값타입
let closure = { [x, y] in
    print(x.value, y)
}

x.value = 10
y = 10
closure() // Prints "10 0"

 

클래스를 캡쳐하는 경우에는 weak나 unowned로 표시해서 강한 순환 참조를 해결하자

myFunction { print(self.title) }                    // implicit 강한 참조
myFunction { [self] in print(self.title) }          // explicit 강한 참조
myFunction { [weak self] in print(self!.title) }    // weak capture 사용
myFunction { [unowned self] in print(self.title) }  // unowned capture 사용

// Weak capture of "self.parent" as "parent"
// 지정된 이름으로 바인드 할 수 있음
myFunction { [weak parent = self.parent] in print(parent!.title) }

 

 

https://modelinspring.tistory.com/79 글의 탈출클로저에 이어서..

이스케이핑(탈출) 클로저 Escaping Closures

...

 

이스케이핑 클로저를 사용하고, self를 참조할 때에는 명시적으로 나타내주어야함

func 이스케이핑함수(closure: @escaping () -> Void) {
    closure()
}

func 논이스케이핑함수(closure: () -> Void) {
    closure()
}

class SomeClass {
    var x = 10
    func doSomething() {
        이스케이핑함수 {
            x = 100 // Reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit 에러 발생
        }
        논이스케이핑함수 {
            x = 200
        }
    }
}

 

논이스케이핑 함수에서는 self를 쓰지 않아도 암시적으로 캡쳐할 수 있지만,

이스케이핑 함수에서는 self를 써야함

class SomeClass {
    var x = 10
    func doSomething() {
        이스케이핑함수 {
            self.x = 100
        }
        논이스케이핑함수 {
            x = 200
        }
    }
}

let instance = SomeClass()
instance.doSomething()
print(instance.x) // Prints "200"

 

캡쳐리스트에 self를 넣어서 해결할 수도 있음

class SomeClass {
    var x = 10
    func doSomething() {
        이스케이핑함수 { [self] in
            x = 100
        }
        논이스케이핑함수 {
            x = 200
        }
    }
}

 

자동클로저 Autoclosures

인자 값이 없는 특정 구문을 자동으로 클로저로 감싸주는 것

함수의 인자로 클로저를 받는 경우 괄호 없이 그냥 구문으로 넘길 수 있게 함

func test(closure: () -> Void) {
    closure()
}
test {
    print("code")
}

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

test2(closure: print("code22"))

 

 

 

 

 

 

댓글