글 작성자: 만렙개발자

1. 조건문

1) if 문

if condition {
    // 다를게
} else if condition {
    // 없는
} else {
    // if문
}

2) switch

switch value {
case pattern :
    // break를 슬 필요가 없다
default:
    // default는 무조건!
}
  • 다른 언어와 다른 점
    • case에 해당하는 값인 pattern은 정수 이외에도 가능하다.
    • break를 쓸 필요가 없다
    • 범위를 지정할 수 있다
switch value {
case 10..<100:
    // 10~99
case 100...Int.max:
    // 100~
default:
	//
}

 

2.  반복문

1) for

  • dictionary loop
let teacher = ["edison": 1931, "einstein": 1955, "Feynman": 1988]

for (name, year) in teacher {
    print("\(name) (\(year))")
}

 

for index in 1...5 {
    print("\(index) times 5 is \(index * 5)")
}

// #results
// 1 times 5 is 5
// 2 times 5 is 10
// 3 times 5 is 15
// 4 times 5 is 20
// 5 times 5 is 25
  • 1...5 == 1, 2, 3, 4, 5
for index in 0..<5 {
    print(index)
}
  • 0..<5 == 0, 1, 2, 3, 4
let minutes = 60
let minuteInterval = 5
for tickMark in stride(from: 0, to: minutes, by: minuteInterval) {
    // render the tick mark every 5 minutes (0, 5, 10, 15 ... 45, 50, 55)
}
  • == 0, 5, 10, 15 ... 45, 50, 55


2) while

while condition {
    // code
}

 

3) repeat-while (=do while)

repeat {
    // code
} while condition

 

3. 제어 전달문 / 제어 전송 명령문 (Control Transfer Statements)

1) continue, break, return

2) fallthrough

  • swift에서 switch문은 break를 사용하지 않습니다. 그 이유는 break가 case마다 기본적으로 작동하기 때문인데요, 그 자동적으로 작동하는 break를 수행하지 않고, 다음 case문까지 이동하여 실행할 수 있도록 하는게 fallthrough 입니다!

3) throw

  • error을 전달하기 위해서 throw 사용
  • return값을 명시하는 -> 전에 throw를 입력하여 사용합니다.
  • throw하지 않았을 때 발생한 오류는 무조건 함수 내에서 처리해야합니다.
func canThrowErrors() throws -> String

4. 클로저 (Closure) == 다른 언어의 람다(lambda)와 유사

1) 클로저

  • 정의된 컨텍스트에서 상수 및 변수에 대한 참조를 캡쳐하고 저장할 수 있습니다.
  • 스위프트의 클로저는 다음과 같은 최적화를 포함하고 있습니다.
    • 컨텍스트에서 매개변수 및 리턴 값 유형 유추
    • 단일 표현 클로저에서 암시적 반환
    • 속기(짧은) 인수 이름
    • 후행 폐쇄 구문
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]

func backward(_ s1: String, _ s2: String) -> Bool {
    return s1 > s2
}

var reversedNames = names.sorted(by: backward)

// reversedNames is equal to ["Ewa", "Daniella", "Chris", "Barry", "Alex"]
  • 문자열에서 비교연산자로 '크다'는 의미는 알파벳순으로 나중에 나타나는 것을 말합니다. 즉, "Barry"는 "Alex"보다 큰 것이죠.
  • backward라는 비교연산을 만들고, 그것을 sorted(by:) 함수에 입력합니다.

2) 클로저 표현 문법

  • inline으로 쓸 경우, 다음과 같이 중괄호가 추가된 형태인 Closure Expression Syntax를 사용하여야합니다.
reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in
    return s1 > s2
})

 

3) 캡처(Capture)

  • 클로저는 정의된 주변 컨텍스트에서 상수와 변수를 캡처할 수 있습니다. 상수 및 변수를 정의한 원래 범위가 더이상 존재하지 않더라도 클로저는 본문 내에서 해당 상수 및 변수의 값을 참조하고 수정할 수 있습니다.
  • 스위프트에서 값을 캡처할 수 있는 가장 간단한 클로저 형식은 다른 함수의 본문 내에 작성된 중첩 함수(nested function)입니다. 중첩 함수는 외부 함수의 인수를 캡처할 수 있으며, 외부 함수 내에 정의된 상수 및 변수도 캡처할 수 있습니다.
func makeIncrementer(forIncrement amount: Int) -> () -> Int {
    var runningTotal = 0
    func incrementer() -> Int {
        runningTotal += amount
        return runningTotal
    }
    return incrementer
}

let incrementByTen = makeIncrementer(forIncrement: 10)

incrementByTen()
// returns a value of 10
incrementByTen()
// returns a value of 20
incrementByTen()
// returns a value of 30
  • makeIncrementer 함수에서 () -> Int 의 의미는, 함수를 리턴한다는 것입니다.
  • makeIncrementer 함수는 runningTotal 이라는 내부 변수를 정의하고, 리턴할 incrementer 함수의 누적 합계를 저장합니다.
  • makeIncrementer 함수에는 인수 레이블이 forIncrement이고, 매개 변수 이름이 amount인 Int 형식의 매개변수가 있습니다. 이 매개변수에 전달된 인수값은 리턴된 incremeter 함수가 호출될 때마다 runningTotal을 증가시켜야하는 양을 지정합니다.

4) 이스케이핑 클로저 == 탈출 가능한 클로저 (Escaping Closure)

  • 클로저는 함수에 대한 인수로, 클로저가 전달될 때 함수를 이스케이프한다고 하지만, 함수가 반환된 후에 호출됩니다. 클로저를 매개변수 중 하나로 사용하는 함수를 선언하면, 매개변수유형 앞에 @escaping을 작성하여 클로저가 이스케이프될 수 있음을 나타낼 수 있습니다.
  • 클로저가 탈출할 수 있는 한 가지 방법은 함수 외부에 정의된 변수에 저장하는 것입니다. 예를들어, 비동기 작업을 시작하는 많은 함수는 클로저 인수를 완료 핸들러로 사용합니다. 함수는 작업을 시작한 후에 반환되지만, 작업이 완료될 때까지 클로저가 호출되지 않습니다. 클로저를 탈출해야 나중에 호출할 수 있습니다.
var completionHandlers: [() -> Void] = []
func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
    completionHandlers.append(completionHandler)
}
  • someFunctionWithEscapingClosure(_:) 함수는 클로저를 인수로 사용하여 함수 외부에서 선언된 배열에 추가합니다. 이 함수의 매개변수를 @escaping으로 표시하지 않으면 컴파일 타임 오류가 발생합니다.
  • @escaping으로 클로저를 표시한다는 것은 클로저 내에서 명시적으로 자신을 참조해야함을 의미합니다. 예를들어, 아래 코드에서 someFunctionWithEscapingClosure (_:)에 전달된 클로저는 이스케이핑 클로저입니다. 즉, 명시적으로 self를 참조해야합니다.
  • 반대로 someFunctionWithNonescapingClosure (_ :)에 전달 된 클로저는 nonescaping 클로저이므로 암시적으로(self를 안쓰고도) 자체를 참조 할 수 있습니다.
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"

5) 오토클로저 (autoclosures)

  • 오토클로저는 함수에 인수로 전달되는 표현을 래핑하기위해 자동으로 생성되는 클로저입니다. 인수를 취하지 않으며, 호출될 때 그 안에 싸인 표현식의 값을 리턴합니다. 이 구문상의 편의를 통해 명시적인 클로저 대신 정규 표현식을 작성하여 함수의 매개변수 주위에 중괄호를 생략할 수 있습니다.
  • 오토클로저를 사용하면 클로저를 호출할 때까지 내부 코드가 실행되지 않으므로 평가가 지연됩니다. 평가 지연은 부작용이 있거나 계산비용이 많이 드는 코드에 유용합니다. 코드를 평가할 때 제어할 수 있기 때문입니다.
var customersInLine = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
print(customersInLine.count)
// Prints "5"

let customerProvider = { customersInLine.remove(at: 0) }
print(customersInLine.count)
// Prints "5"

print("Now serving \(customerProvider())!")
// Prints "Now serving Chris!"
print(customersInLine.count)
// Prints "4"
// customersInLine is ["Ewa", "Barry", "Daniella"]
func serve(customer customerProvider: @autoclosure () -> String) {
    print("Now serving \(customerProvider())!")
}
serve(customer: customersInLine.remove(at: 0))
// Prints "Now serving Ewa!"
  • 오토클로저를 과도하게 사용하면 코드를 이해하기 어려울 수 있습니다. 컨텍스트와 함수 이름은 평가가 지연되고 있음을 분명히해야합니다.

5. Enumerations

  • enum 키워드로 열거를 소개하고, 전체 정의를 한 쌍의 중괄호 안에 넣습니다.
enum Planet {
    case mercury, venus, earth, mars, jupiter, saturn, uranus, neptune
}

 

  • switch문에서의 활용
directionToHead = .south
switch directionToHead {
case .north:
    print("Lots of planets have a north")
case .south:
    print("Watch out for penguins")
case .east:
    print("Where the sun rises")
case .west:
    print("Where the skies are blue")
}
// Prints "Watch out for penguins"