본문 바로가기

IT/Swift

[swift] Closure, Capture list

[swift 기초문법] - 클로저 (Closure), 획득목록 (Capture list)

클로저란

이름 없는 함수로 봐도 무방합니다.
in 으로 매개변수, 반환타입과 실제 클로저 의 코드를 분리한다는 점이 함수와 차이점입니다. 
클래스처럼 참조타입입니다.

 

표현방식

 

{
	(parameters) -> (return type) in
	//statements
}

 

함수전달과 클로저 전달방식 비교

 

let names:[String] = ["banana","apple","dark","iphone"]

//함수 전달 예
func backwards(first: String, second: String) -> Bool {
    print("\(first) \(second) comparing...")
    return first > second
}

let reversed:[String] = names.sorted(by:backwards)
print(reversed)



//클로저 전달 예
let reversed2:[String] = names.sorted(by: { (first:String,second:String) -> Bool in 
	return first>second 
})
print(reversed2)

 

 

 

후행 클로저(Trailing Closure)

Xcode에서 자동완성 기능을 사용하면 자동으로 후행 클로저로 유도합니다.

함수나 메서드의 마지막 전달인자로 전달되는 클로저에만 해당합니다.
전달인자가 하나이면 소괄호 생략 가능합니다.
소괄호를 닫은 후 작성할 수 있습니다.
매개변수의 타입과 반환 타입을 생략할 수 있습니다.

 

//메서드의 소괄호를 닫은 후 작성 예
let reversed3:[String] = names.sorted(){ (first:String,second:String) -> Bool in
    return first>second
}

//메서드의 소괄호 생략 예
let reversed4:[String] = names.sorted{ (first:String,second:String) -> Bool in
    return first>second
}

//타입 유추를 통한 반환타입, 매개변수 타입 생략 예
let reversed5:[String] = names.sorted { (first, second) in\
    return first > second
}

 

단축  인자 이름

첫 번째 전달인자 부터 $0, $1, $2, $3 ,,, 순서로 '$+숫자'로 표현합니다.
단축인자를 사용하면 in의 생략이 가능합니다.

 

let reversed6:[String] = names.sorted{
    return $0 > $1
}

 

return 키워드 생략

클로저가 반환값을 갖고 , 실행문이 한줄이면 return 키워드 생략이 가능합니다.

 

let reversed7:[String] = names.sorted{ $0 > $1 }

 

 

 

 

탈출 클로저(Escaping Closure)

@escaping 키워드 사용
함수가 종료되고 난 후 작업이 끝나고 호룰될 필요가 있는 클로저를 사용해야 할때 사용합니다.

 

var completions: [() -> Void] = []
func someFuncWithCompletion(completion: @escaping () -> Void ){
    return completions.append (completion)
}

 

자동 클로저(Auto Closure)

함수의 전달인자로 전달되는 표현을 자동으로 변환해주는 클로저입니다.
전달인자를 갖지 않습니다.
자동으로 @noescape 속성을 포함하므로 탈출 클로저로 사용 하고 싶으면 @escaping 을 붙여야합니다.

 

var customerInLine: [String] = ["A","B","C","D"]

let customerProvider: () -> String = {
    return customerInLine.removeFirst()
}

func serveCustomer(_ customerProvider: @autoclosure () -> String){
    print("Now serving \(customerProvider())")
}

serveCustomer(customerInLine.removeFirst())

 

 

획득목록이란(Capture list)

클로저 내부에서 참조 타입을 획득하는 규칙을 제시해줄 수 있는 기능입니다.

참조 방식과 참조할 대상을 대괄호 '[]'로 둘러싸인 목록 형식으로 작성하며 뒤에는 in 키워드를 써줍니다.

획득목록에 명시된 요소가 참조 타입이 아니라면 해당 요소들은 클로저가 생성될 때 초기화됩니다.

 

var x = 0
var y = 0
let block = { [x] in

}

 

x는 클로저가 생성됨과 동시에 획득목록 내에서 다시 x라는 이름의 상수로 초기화됩니다.

따라서 외부에서 x의 값을 변경하더라도 클로저의 획득목록의 x와는 별개가 됩니다.

그러나 y의 경우에는 클로저의 내부와 외부 상관없이 값이 변하는대로 반영됩니다.

 

 

 

 

참조타입의 획득목록

참조타입을 획득목록으로 사용할 경우 강한획득(Strong Capture), 약환획득(Weak Capture), 미소유획득(Unowned Capture) 할 것인지를 정해줄 수 있습니다.

약한 획득을 하게 되면 옵셔널 상수로 지정됩니다. 왜냐면 메모리에서 해제된 상태일 수 있기 때문입니다.\

 

획득목록 참조타입으로 약한 참조를 선택한 예

 

let clousure: () -> Void = { [weak self] in
  guard let 'self' = self else {
     return // 참조값이 사라짐!!!
  }
}

 

 

 

 

 

#swift 기초

#swift 강의

#ios programming

'IT > Swift' 카테고리의 다른 글

[swift] 스위프트의 특징  (0) 2019.08.21
[swift] ARC(Automatic Reference Counting)  (0) 2019.08.21
[swift] Mutating, Memberwise Initializers, Access Control  (0) 2018.03.13
[swift] Property  (0) 2018.03.12
[swift] Optional, Optional Chaining  (0) 2018.03.08