티스토리 뷰
출처
클로저의 개념
클로저 표현식 (Closure Expressions)
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
func backward(_ s1: String, _ s2: String) -> Bool {
return s1 > s2
}
var reversedNames = names.sorted(by: backward)
{ (parameters) -> return type in
statements
}
reversedNames = names.sorted(by: { (s1 : String, s2 : String) -> Bool in
return s1 > s2
})
문맥으로부터 타입 추론
reversedNames = names.sorted(by: {
(s1, s2) in return s1 > s2
})
reversedNames = names.sorted(by: {
s1, s2 in return s1 > s2
})
단일 표현식 클로저로부터의 암시적인 반환
reversedNames = names.sorted(by: {
(s1, s2) in s1 > s2
})
축약된 인자 이름
reversedNames = names.sorted(by: {
$0 > $1
})
연산자 메소드
reversedNames = names.sorted(by: >)
후행 클로저
reversedNames = names.sorted() { $0 > $1 }
reversedNames = names.sorted { $0 > $1 }
후행 클로저는 클로저가 한줄에 들어가지 않을만큼 충분히 길 때
매우 유용하다.
map 메소드는 배열의 각각 아이템들에 대해 클로저 표현식을 한번 호출한다.
let digitNames = [
0: "Zero", 1: "One", 2: "Two", 3: "Three", 4: "Four",
5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine" ]
let numbers = [16, 58, 510]
let strings = numbers.map { (number) -> String in
var number = number
var output = ""
repeat {
output = digitNames[number % 10]! + output
number /= 10
} while number > 0
return output }
print(strings)
//["OneSix", "FiveEight", "FiveOneZero"]
값 캡쳐하기
func makeIncrementer(forIncrement amount: Int) -> () -> Int {
var runningTotal = 0
func incrementer() -> Int {
runningTotal += amount
return runningTotal
}
return incrementer
}
let incrementByTen = makeIncrementer(forIncrement: 10)
incrementByTen()
incrementByTen()
incrementByTen()
let incrementBySeven = makeIncrementer(forIncrement: 7)
incrementBySeven() // 7
incrementByTen() // 40
클로저는 참조타입이다 (reference type)
이는 두 개의 다른 상수나 변수에 클로저를 할당하는 경우
상수나 변수 둘 다 같은 클로저를 참조한다는 것을 의미한다.
let anotherIncrementByTen = incrementByTen
anotherIncrementByTen() //50
클로저 벗어나기
즉시 실행을 막고 추후에 실행할 수 있도록 막는 것을 뜻한다.
var completionHandlers: [() -> Void] = []
func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
completionHandlers.append(completionHandler)
}
func someFunctionWithNonescapingClosure(closure: () -> Void){
closure()
}
class SomeClass {
var x = 10
func doSomething() {
someFunctionWithEscapingClosure {
self.x = 100
}
someFunctionWithNonescapingClosure {
x = 200
}
}
}
let instance = SomeClass()
instance.doSomething()
print(instance.x) // Prints "200"
completionHandlers.first?()
print(instance.x) // Prints "100"
클로저를 @escaping 표시하는 것은
클로저가 self 을 명시적으로 참조하고 있다는 것을 의미한다.
위 예제에서는 someFunctionWithEscapingClosure(_:) 에 전달하여
명시적으로 self 를 참조할 필요가 있다는 의미이며, 클로저가 벗어난다.
클로저 내부에서 self 를 참조하고 있다면
해당 클로저를 파라미터로 받는 함수는 @escaping type 으로 선언해줘야한다.
반대로, someFunctionWithNonescapingClosure(_:) 는
암시적으로 self 를 참조할 수 있다는 의미이며 클로저가 벗어나지 못한다.
자동 클로저
var customersInLine = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
print(customersInLine.count)
// Prints "5" let
let customerProvider = {
customersInLine.remove(at: 0)
}
print(customersInLine.count)
// Prints "5"
print("Now serving \(customerProvider())!")
// Prints "Now serving Chris!"
print(customersInLine.count) // Prints "4"
배열의 요소는 클로저가 실제 호출될 때까지 제거하지 않는다. (remove)
클로저가 호출되지 않으면 클로저 내부의 표현식은 처리되지 않으며
배열의 요소가 제거되지 않는다.
// customersInLine is ["Alex", "Ewa", "Barry", "Daniella"]
func serve(customer customerProvider: () -> String) {
print("Now serving \(customerProvider())!")
}
serve(customer: { customersInLine.remove(at: 0) } )
// Prints "Now serving Alex!"
여기서 serve 함수는 customers 의 이름을 반환하는 명시적인 클로저를 가진다.
아래 예제의 경우 @autoclosure 속성을 가진 자동클로저를 가진다.
comtomerProvider 매개변수의 타입이 @autoclosure 속성으로 되어있기 때문에
그 인자는 자동으로 클로저로 변환된다.
즉, 중괄호를 생략할 수 있다.
// customersInLine is ["Alex", "Ewa", "Barry", "Daniella"]
func serve(customer customerProvider: @autoclosure () -> String) {
print("Now serving \(customerProvider())!")
}
serve(customer: customersInLine.remove(at: 0))
// Prints "Now serving Alex!"
자동 클로저를 남용하면 코드를 이해하기 어렵게 만들 수 있다.
context 와 함수 이름은 명확하게 만들고 처리가 지연되는 것을 확인해야한다.
'iOS 개발 > Swift' 카테고리의 다른 글
[Swift 3] 클래스와 구조체 (1) | 2017.04.14 |
---|---|
[Swift 3] 열거형 (Enumerations) (0) | 2017.04.14 |
[Swift 3] 함수 정의와 호출 및 함수 타입 (Function) (1) | 2017.04.14 |
[Swift 3] 흐름 제어 (Flow Control / for, while, if-else, switch, fallthrough, guard, label, available) (0) | 2017.04.13 |
[Swift 3] 컬렉션 타입 (Collection Types_Array, Set, Dictionary) (0) | 2017.04.13 |
- Total
- Today
- Yesterday
- dictionary
- AWS
- Block
- Swift
- NSManagedObjectModel
- 꺼내먹어요
- UIView
- 읽기 좋은 코드가 좋은 코드다
- thread
- CIImage
- CGImage
- NSManagedObjectContext
- HTTP
- coredata
- RunLoop
- string
- Swfit
- Swift 3
- delegate
- ios
- optional
- set
- applicationWillResignActive
- Swift3
- Swift 3.0
- NSManagedObject
- Arc
- workerThread
- EffectiveObjectiveC
- docker
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |