Escaping closure captures non-escaping parameter 'predicate'

니냐뇨·2022년 9월 18일
0
post-thumbnail

Escaping closure captures non-escaping parameter 'predicate'


이런 에러를 만난 적이 있나요?

이 에러가 발생하는 원인은 탈출 클로저가 있어야 할 자리에 비탈출 클로저가 있어서 입니다.

탈출 클로저와 비탈출 클로저에 대해선 다음 번에 다뤄볼게요!

이 문제를 해결하기 위해 한번 오류 상황을 만들어보겠습니다!


오류 상황 생성

let evenNumberPredicate = { (number: Int) -> Bool in
    return number % 2 == 0
}

func countEvenNumber(in array: [Int], predicate: (Int) -> Bool) -> Int {
    return array.lazy.filter { predicate($0) }.count
}

이 경우에 에러가 발생하는 이유는 lazy 컬렉션을 사용했기 때문입니다!
lazy 컬렉션은 비동기 작업을 할 때 사용되기 때문에 그 뒤에 나오는 filter 메소드는 탈출 클로저(escaping closure) 를 요구하게 됩니다.
그래서 위와 같이 탈출 클로저가 있어야 하는데 비탈출 클로저가 있잖아? 라는 오류를 만나게 되는 것이죠.

그렇다면 이를 어떻게 해결할 수 있을까요?


withoutActuallyEscaping

위 오류는 withoutActuallyEscaping(_:do:)이라는 함수를 통해 해결 할 수 있습니다.
이 함수를 통해 non-escaping closure를 escaping closure인 것 처럼 사용 할 수 있습니다.

그렇다면 위의 코드를 withoutActuallyEscaping(_:do:)를 이용하여 바꿔볼까요?

let evenNumberPredicate = { (number: Int) -> Bool in
    return number % 2 == 0
}

func countEvenNumber(in array: [Int], predicate: (Int) -> Bool) -> Int {
    return withoutActuallyEscaping(predicate, do: { escapablePredicate in
        return array.lazy.filter { escapablePredicate($0) }.count
    })
}

이렇게 withoutActuallyEscaping(_:do:) 함수의 첫번째 인자로 탈출 클로저인 척 해야하는 우리의 비탈출 클로저를 전달해주고, do에서는 비탈출 클로저를 매개변수로 받아 filter에서 작업을 실행하게 됩니다.


결론

withoutActuallyEscaping(_:do:)를 이용하여 비탈출 클로저(non-escaping closure)를 탈출 클로저(escaping closure)처럼 사용할 수 있다!

profile
열심히 살자.

0개의 댓글