문법 최적화
- 문맥 상 parameter와 return value 타입 추론 (Type Inference)
- 한 줄인 경우, return을 적지 않아도 된다 (Implicit Return)
- argument 이름 축약 (Shorthand Arguments) $0, $1
- 함수의 마지막 아규먼트로 클로저가 전달되는 경우, 소괄호 생략 (Trailing Closure)
Trailing Closure (후행 클로저 문법)
func closureParamFunction(closure : () -> Void) {
print("프린트 시작")
closure()
}
closureParamFunction( closure: { print("프린트 종료") })
closureParamFunction(closure: ) {
print("프린트 종료")
}
closureParamFunction() {
print("프린트 종료")
}
closureParamFunction {
print("프린트 종료")
}
func closureCaseFunction(a: Int, b: Int, closure: (Int) -> Void) {
let c = a + b
closure(c)
}
closureCaseFunction(a: 5, b: 2) { number in
print("출력할까요? \(number)")
}
Example
func performClosure(param: (String) -> Int ) {
param("Swift")
}
performClosure(param: { (str: String) -> Int in
return str.count
})
performClosure(param: { str in
return str.count
})
performClosure(param: {str in
return str.count
})
performClosure(param: {str in
str.count
})
performClosure(param: {
$0.count
})
performClosure {
$0.count
}
performClosure { $0.count }
Example
let closureType1 = { (param) in
return param % 2 == 0
}
let closureType1 = { $0 % 2 == 0 }
let closureType3 = { (a: Int, b:Int) -> Int in
return a * b
}
let closureType3: (Int, Int) -> Int = { (a, b) in
return a * b
}
let closureType3: (Int, Int) -> Int = { $0 * $1 }
실제 사용 Example
URLSession(configuration: .default)
.dataTaks(with: URL, completionHandler: (Data?, URLResponse?, Error?) -> Void)
URLSeesion(configuration: .default)
.dataTaks(with: URL(string: "http://주소")!) { d, r, e in
}
Timer.scheduledTimer(withTimeInterval: 0.2, repeats: false, block: (Timer) -> Void)
Timer.scheduledTimer(withTimeInterval: 0.5, repeats: false) { (timer) in
print("0.5초 뒤에 출력하기")
}
class ViewController: UIViewCOntroller {
}
let vc = ViewController()
vc.dismiss(animated: true, completion: ( () -> Void)? )
vc.dismiss(animated: true) {
print("화면을 닫는 것을 완료했습니다")
}
@escaping
- 원칙적으로 함수의 실행이 종료되면 parameter로 쓰이는 클로저도 제거된다
- @escaping 키워드는 클로저를 제거하지 않고, 함수에서 탈출시킨다.
즉, 함수가 종료되어도 클로저가 존재한다
- 클로저가 함수의 실행흐름(stack frame)을 벗어날 수 있도록 한다
- @escaping 사용의 경우
- 어떤 함수의 내부에 존재하는 클로저(함수)를 외부 변수에 저장
- GCD (비동기 코드의 사용
func performEscaping1(closure: () -> ()) {
print("프린트 시작")
closure()
}
performEscaping1 {
print("프린트 중간")
print("프린트 종료")
}
var aSavedFunction: () -> () = { print("출력") }
aSavedFunction()
func performEscaping2(closure: @escaping () -> () ) {
aSavedFunction = closure
}
performEscaping2 {
print("다르게 출력")
}
aSavedFunction()
@autoclosure
- 일반적인 클로저 형태로 써도 되지만, 번거로울 때 사용
- 잘 사용하지는 않고, 읽기 위한 문법이다.
- 기본적으로 non-escaping 특성
func someFunction(closure: @autoclosure () -> Bool) {
if closure() {
print("참입니다.")
}
else {
print("거짓입니다.")
}
}
var num = 1
someFunction(closure: true)
someFunction(closure: num == 1)
클로저의 실제 사용
let emailTextField: UITextField = {
let tf = UITextField()
tf.placeholder = "Email"
tf.backgroundColor = UIColor(white: 0, alpha: 0.3)
tf.borderStyle = .roundedRect
tf.font = UIFont.systemFont(ofSize: 14)
tf.translatesAutoresizingMaskIntoConstraints = false
return tf
}()