함수 형식
함수 형식은 매개 변수 형식과 함수의 반환 형식으로 구성됩니다. 위의 예를 들어 함수 유형은 다음과 같습니다:(Int, Int) -> Int
“형식Int
의 두 매개 변수가 있고 형식Int
의 값을 반환하는 함수입니다.”함수 유형은 매개 변수 또는 함수 반환 유형으로 설정할 수 있습니다.
함수 유형은 다음과 같은 모든 변수에 할당 할 수 있습니다.:
var mathFunction: (Int, Int) -> Int = add
기능은 폐쇄의 특별한 경우입니다. 클로저는 세 가지 형태 중 하나를 취합니다:
전역 함수:이름이 있고 값을 캡처 할 수 없습니다.
중첩 함수:이름이 있으며 둘러싸는 함수에서 값을 캡처 할 수 있습니다.
폐쇄 식:이름이 없으며 주변 컨텍스트에서 값을 캡처 할 수 있습니다.
폐쇄 식:
스위프트 폐쇄 문서
폐쇄는 중괄호 안에 함수 유형을 넣고 반환 유형 뒤에in
키워드를 넣어 만들 수 있습니다.
속기 인수 이름
클로저 인수는 위치를 참조 할 수 있습니다.
,
,
,
그래서.
속기 이름을 지정한 후 클로저 인수를 지정할 필요가 없으며 키워드
클로저에서 암시 적 반환:
단일 표현식 클로저는 선언에서return
키워드를 생략하여 단일 표현식의 결과를 암시 적으로 반환 할 수 있습니다.
여러 줄 식 폐쇄의 경우return
키워드를 생략 할 수 없습니다.
후행 폐쇄:
함수의 마지막 인수로 클로저 식을 함수에 전달해야 하고 클로저 식이 너무 길면 후행 클로저로 쓸 수 있습니다. 후행 클로저는 함수 호출의 괄호()뒤에 작성됩니다. 후행 클로저 구문을 사용할 때 함수 호출의 일부로 클로저에 대한 인수 레이블을 작성하지 않습니다.
메서드 호출에 대한 인수로 클로저
후행 폐쇄(즉, 메소드 괄호 뒤의 폐쇄)
클로저가 메소드의 마지막 매개 변수 인 경우 스위프트는 다음과 같이 쓸 수 있습니다🖕
축소를 사용한 후행 클로저 예제()
후행 클로저 구문을 사용하면 클로저가 지원하는 함수 바로 뒤에 클로저의 기능을 깔끔하게 캡슐화하여reduce(_:)
메서드의 바깥쪽 괄호 안에 전체 클로저를 래핑할 필요가 없습니다.
값 캡처:
클로저는 정의된 주변 컨텍스트에서 상수 및 변수를 캡처할 수 있습니다. 그런 다음 클로저는 상수 및 변수를 정의한 원래 범위가 더 이상 존재하지 않더라도 본문 내에서 해당 상수 및 변수의 값을 참조하고 수정할 수 있습니다.
스위프트에서 값을 캡처 할 수있는 가장 간단한 형태의 클로저는 다른 함수의 본문 내에 작성된 중첩 함수입니다. 중첩 함수는 외부 함수의 인수를 캡처 할 수 있으며 외부 함수 내에 정의 된 상수 및 변수를 캡처 할 수도 있습니다.
스위프트 문서에 주어진 예
이makeIncrementer
함수는 하나의 인수를 입력으로 받아들이고 함수 유형(예:() -> Int
)을 반환합니다. 즉,단순한 값이 아닌 함수를 반환합니다. 반환하는 함수에는 매개 변수가 없으며 호출될 때마다Int
값이 반환됩니다.
여기서amount
는 인수이고runningTotal
는 변수로 선언되고 0 으로 초기화됩니다. 중첩 함수incrementer
은 주변 컨텍스트에서amount
및runningTotal
를 캡처합니다.
makeIncrementer
에서 보자.:
참고: 최적화로서,스위프트는 그 값이 클로저에 의해 변이되지 않고 클로저가 생성 된 후에 값이 변이되지 않는 경우 값의 복사본을 캡처하고 저장할 수 있습니다.
스위프트는 더 이상 필요하지 않을 때 변수를 폐기하는 데 관련된 모든 메모리 관리도 처리합니다.
함수 인수에서 긴 클로저 식을 제거하려면 타입알리아를 사용할 수 있습니다.
비 이스케이프 클로저:
클로저 매개 변수는 스위프트 3 이전에 기본적으로 이스케이프되었습니다. 클로저 매개 변수가 스위프트 3 에서 이스케이프 처리되지 않는
로 표시된 경우 클로저는 함수 본문을 이스케이프하지 않습니다. 함수 인수로 클로저를 전달하는 경우 클로저는 함수 본문으로 실행되고 컴파일러를 다시 반환합니다. 실행이 종료되면 전달된 클로저는 범위를 벗어나 메모리에 더 이상 존재하지 않습니다.
최소한 알아야 할
클로저 매개 변수는 기본적으로 이스케이프 처리되지 않습니다.
비 이스케이프 클로저의 수명주기: 1. 함수 호출 중에 클로저를 함수 인수로 전달합니다. 2. 함수에서 몇 가지 작업을 수행 한 다음 클로저를 실행하십시오. 3. 함수 반환.
더 나은 메모리 관리 및 최적화로 인해 스위프트는 기본적으로 이스케이프가 아닌 모든 클로저를 변경했습니다. CaptureList.swift
은 비 이스케이프 클로저의 예입니다.
참고:@이스케이프되지 않는 주석은 함수 유형
이스케이프 클로저에만 적용됩니다:
클로저는 클로저가 함수에 인수로 전달 될 때 함수를 이스케이프한다고 말하지만 함수가 반환 된 후에 호출됩니다. 클로저를@escaping
로 표시한다는 것은 클로저 내에서self
을 명시적으로 참조해야 함을 의미합니다.
@이스케이프 클로저의 수명주기: 1. 함수 호출 중에 함수 인수로 클로저를 전달합니다. 2. 기능에 몇 가지 추가 작업을 수행. 3. 함수는 비동기 또는 저장 클로저를 실행합니다. 4. 함수 반환.
클로저가 기본적으로 이스케이프되는 위치를 살펴 보겠습니다.:
함수 유형의 변수는 암시 적 이스케이프입니다
유형이제는 암시 적 이스케이프입니다
선택적 클로저는 암시 적 이스케이프입니다
일반적인 오류:
이스케이프 클로저에 이스케이프되지 않는 클로저를 할당합니다. 거기에는 2 가지 방법으로 이 문제를 해결하:
마감으로 탈출한
또는 기본@noescape 동 폐쇄를 선택
Autoclosures:
스@autoclosure
속성을 정의할 수 있는 인수해 자동으로 감싸서 마감. 그것은 어떤 인수도 취하지 않으며,호출 될 때 그 안에 래핑 된 식의 값을 반환합니다. 이 구문 편의를 통해 명시 적 폐쇄 대신 일반 식을 작성하여 함수의 매개 변수 주위에 중괄호를 생략 할 수 있습니다.condition
매개 변수는 디버그 빌드에서만 평가되고message
매개 변수는condition
가false
인 경우에만 평가됩니다.
func assert(_ expression: @autoclosure () -> Bool, _ message: @autoclosure () -> String) {}
@autoclosure
와@escaping
속성 구문을 사용하려면:
@autoclosure @escaping () -> Bool
클로저 대 블록:”스위프트 클로저 및 목표-씨 블록은 호환되므로 블록을 기대하는 목표-씨 메소드에 스위프트 클로저를 전달할 수 있습니다. 당신도 스위프트 함수의 이름을 전달할 수 있도록 스위프트 클로저 및 함수는 동일한 유형을 가지고있다. 클로저는 블록과 비슷한 캡처 의미를 갖지만 한 가지 주요 방법으로 다릅니다. 즉,목표-씨에서__블록의 동작은 스위프트의 변수에 대한 기본 동작입니다.”
클로저 대 대리자:
솔루션은 문제에 따라 다릅니다. 또한,애플은 패턴을 콜백에 초점을 이동한다. UIAlertAction
는 그 예입니다.
https://medium.com/@abhimuralidharan/functional-swift-all-about-closures-310bc8af31dd
https://medium.com/@kumarpramod017/what-do-mean-escaping-and-nonescaping-closures-in-swift-d404d721f39d
https://oleb.net/blog/2016/10/optional-non-escaping-closures/
https://swiftunboxed.com/lang/closures-escaping-noescape-swift3/
https://medium.com/@johnsundell/using-autoclosure-when-designing-swift-apis-67fe20a8b2e