7-1. 클로저의 개념

🌈 devleeky16498·2022년 4월 13일
0

클로저는 코드에서 주변에 전달과 함께 사용할 수 있는 자체 포함형 기능 블럭이다. 클로저는 정의된 컨텍스트에서 모든 상수와 변수에 대한 참조를 캡처 및 저장 가능하다. 이러한 상수와 변수를 폐쇄(closing over)라고 한다.

  1. 함수의 종류인 전역함수와 중첩함수는 클로저의 특별 케이스이다. 클로저는 3개 중 하나의 형태를 취한다.
  • 전역 함수는 이름을 가지고 어떠한 값도 캡쳐하지 않는 클로저이다.
  • 중첩 함수는 이름을 가지고 둘러싼 함수로부터 값을 캡처하는 클로저이다.
  • 클로저의 표현식은 주변 컨텍스트에서 값을 캡처 가능한 경량 구문으로 작성된 무명 클로저이다.

클로저의 표현

  1. 클로저의 표현구는 다음과 같은 일반적인 형태를 가진다. 클로저 표현구의 파라미터는 inout일 수 있지만 기본값 또한 가질 수 있다. 튜플은 파라미터 타입과 반환타입으로도 사용이 가능하다. 아래 예시에서 보듯이, 클로저의 바디는 in 키워드와 함께 시작한다. 이 는 클로저의 파라미터와 리턴 타입의 정의가 끝났음을 나타내고 클로저의 바디가 시작함을 알려준다.
{ (Parameters) -> return type in
	statements
}
  1. 함수나 메서드에 클로저를 인라인 클로저 표현식으로 전달 시 항상 파라미터 타입과 반환타입 유추가 가능하다. 결론적으로 클로저가 함수 또는 메서드 인자로 사용되는 경우 완전한 형태로 인라인 클로저를 작성할 필요가 없다. 다음 예시에서는 배열을 정렬하는 정렬 클로저에 대한 예시로 클로저를 연구해본다.
func backword(_ s1 : String, _ s2 : String) {
	return s1 > s2
}

var reversedName = name.sorted(by: backward)
//다음과 같을 경우 정상적으로 재배열이 일어난다. 
//다음 예시는 sorted(by:) 메서드 파라미터에 필요한 함수타입을 만족하는 함수를 정의하고 이를 대입시켜준 것이다

reversedName = names.sorted(by: {(s1 : String, s2 : String) -> Bool in 
	return s1 > s2
})
//다음은 위 함수의 클로저 표현이다.

reversedName = names.sorted(by: {s1, s2 in return s1 > s2})
//다음과 같은 경우 타입 유추가 일어나며 별도의 파라미터에 대한 타입을 명시하지 않아도 코드가 실행된다.

reversedName = names.sorted(by: { s1, s2 in s1 > s2 } )
//단일 표현 클로저에 대한 암시적 반환의 예시이다.
//sorted메서드의 인자 함수타입은 클로저에서 Bool 값을 반환해야 하므로 명확하다. 
//따라서 모호하지 않으므로 return 또한 생략 가능하다.

짧은 인자 이름 사용

  1. 스위프트는 인라인 클로저에 $0, $1, $2등 클로저의 인자값으로 참조하는데 사용가능한 짧은 인자 이름을 제공해준다.위의 sorted(by:)정렬 클로저에서도 이와같이 짧은 인자 이름의 사용이 가능하다. 짧은 인자 이름을 사용하게 되면 클로저 인자 목록을 생략하고 이는 함수타입에서 유추된다.
reversedName = names.sorted(by: {$0 > $1})
//여기에서 $0, $1은 클로저의 첫째 둘째 String 인자를 참조한다. 
//$1이 짧은 인자에서 가장 높은 숫자이기 때문에 클로저는 2개의 인자가 있다고 이해한다. 
//sorted(by:) 함수는 인자가 모두 문자열인 클로저를 기대하기 때문에 자동으로 String타입으로 유추를 한다.

후행 클로저

가장 핵심이 되는 개념 분야이다. 후행 클로저는 함수의 마지막 인자로 함수에 클로저 표현식을 전달해야 하고 클로저 표현식이 긴 경우 사용한다. 후행 클로저는 함수의 인자지만 함수 호출의 소괄호 다음에 작성한다. 후행 클로저 구문을 사용할 때는 함수 호출의 일부로 첫 클로저 인자 라벨을 작성하지 않아도 된다.

func someFunction(closure : () -> Void) {
	print("a")
    closure()
}
//다음과 같은 경우 a 출력 후 클로저가 실행된다.

someFunction(closure: {
	//여기에 클로저를 통해 수행할 함수의 바디가 들어간다.
})

someFunction() {
	print("b)
}

//다음과 같이 클로저 표현구와 더불어 함수를 호출하게 되면,
//1차적으로 someFunction이 호출되면서 a를 출력하고, 그 후 후행클로저 실행으로 b가 출력된다.


reversedName = names.sorted() { $0 > $1 }
//다음과 같은 경우 후행 클로저로 표현식이 함수와 메서드의 유일한 인자인 경우 뒤에 소괄호를 생략하고 
//아래 예시와 같이 작성이 가능하다.

reversedName = names.sorted {$0 > $1}
//다음과 같이 간단하게 작성 가능하다.
  1. 만약 함수가 여러개의 클로저를 가지고 있다면 첫째 후행 클로저의 인자라벨을 생략하고, 남은 후행 클로저의 라벨은 정상적으로 표기한다.
func loadPicture(from server : Server, completion: (Picture) -> Void, onFailure : () -> Void) {
	if let picture. = download("photo.jpg", from : server) {
    	completion(picture)
    } else {
    	onFailure()
    }
}
//다음의 함수는 2개의 클로저를 제공한다. 첫째는 사진 다운로드 후 완료처리 클로저이며, 
//둘째는 오류를 표시하는 오류처리 클로저이다.

loadPicture(from : someServer) { picture in 
	someView.currentPicture = picture // 1차 후행클로저 수행
} onFailure: {
	print("Failed to save image")
} // 2차 후행 클로저를 수행
profile
Welcome to Growing iOS developer's Blog! Enjoy!🔥

0개의 댓글

관련 채용 정보