Swift - 제어문

임성빈·2022년 3월 7일
0

Swift

목록 보기
5/26
post-thumbnail
post-custom-banner

Swift에서는 while loop, if guard, switch, for-in 문 등 많은 제어문을 제공한다.


For-In 문

for-in 문은 배열, 숫자, 문자열을 순서대로 순회하기 위해 사용한다.

let names = [ "짱구", "철수", "맹구", "이슬" ]
for name in names {
	print("Hello \(name)!")
}
// Hello 짱구!
// Hello 철수!
// Hello 맹구!
// Hello 이슬!

Dictionary에서 반환된 key-value 쌍으로 구성된 튜플을 순회하며 제어할 수도 있다.
단, Dictionary에 담긴 콘텐츠는 정렬이 되지 않은 상태이기 때문에 넣었던 순서대로 순회되지 않는다.

let numberOfLegs = ["spider": 8, "human": 2, "cat": 4 ]

for (animalName, legCount) in numberOfLegs {
	print("\(animalName)s have \(legCount) legs")
}
//  human have 2 legs
//  spiders have 8 legs
//  cat have 4 legs

for-in 문을 통해 숫자 범위를 지정해 순회할 수 있다.

for index in 1...5 {
	print("\(index) times 5 is \(index * 5)")
}
// 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

for-in 문을 순서대로 제어할 필요가 없다면, 변수자리 _ 키워드를 사용하면 성능을 높일 수 있다.

let base = 2
let power = 10
var answer = 1

for _ in 1...power {
	answer *= base
}

print("\(base) to the power of \(power) is \(answer)")
// Prints "2 to the power of 10 is 1024" 

범위 연산자와 함께 사용할 수 있다.

let minutes = 60
for tickMark in 0..<minutes {
	//	render the tick mark each minute (60 times)
}

stride(form:to:by:) 함수와 함께 사용할 수 있다.

let minuteInterval = 5

for tickMark in stride(from: 0, to: minutes, by:minuteInterval) {
	// render the tick mark every 5 minutes (0, 5, 10 ... 50, 55)
}

While 문

Swift에서는 whilerepeat-while 두 가지 종류의 while 문을 지원한다.

While

조건이 거짓일때까지 구문을 반복

while condition {
	statement
}

while 문의 예시

var countDown = 5
let endTime = 0

while countDown > endTime {
	print(countDown)
	countDown -= 1
}
// 5
// 4
// 3
// 2
// 1

Repaet-While 문

repeat-while 문은 다른 언어의 do-while 문과 유사한 while 문이다.

구문을 최소 한번 이상 실행하고 while 조건이 거짓일 때까지 반복한다.

repeat {
	statement
} while condition

repeat-while 문의 예시

repeat {
	print(countDown)
	countDown -= 1
} while countDown > endTime 
// 5
// 4
// 3
// 2
// 1

조건적 구문

Swift에서는 ifswitch 문 두 가지의 조건 구문을 제공한다.

If 문

var score = 85
if score >= 90 {
	print("A")
} if else score >= 80 {
	print("B")
} if else score >= 70 {
	print("C")
} else {
	print("F")
}
// B

Switch 문

Switch문의 기본 형태

switch some value to consider {
case value 1:
	respond to value 1
case value 2,
	 value 3:
     respond to value 2 or 3
default:
     otherwise, do something else
}

문자를 비교해 처리하는 경우

let someCharacter: Character = "z"
switch someCharacter {
case "a":
	print("The first letter of the alphabet")
case "z":
	print("The last letter of the alphabet")
default:
	print("Some other character")
}
// Prints "The last letter of the alphabet"

암시적인 진행을 사용하지 않음

C와 Objective-C의 switch 구문과는 달리 Swift의 switch구문은 암시적인 진행을 하지 않는다. C나 Objective-C에서는 switch 구문이 기본적으로 모든 case를 순회하여 default를 만날 때까지 진행된다. 그래서 불필요한 진행을 하지 않기 위해 break라는 문구를 명시적으로 적어야 했는데 Swift에서는 break를 적지 않아도 특정 case가 완료되면 자동으로 switch 구문을 빠져 나가게 된다. 이런 사용법으로 인해 실수로 break를 적지않아 의도하지 않은 case문이 실행되는 것을 방지해 준다.

case 안에는 최소 하나의 실행 구문이 반드시 있어야 한다.

let someCharacter: Character = "z"
switch someCharacter {
case "a":
case "z":
	print("The last letter of the alphabet")
default:
	print("Some other character")
}
// 컴파일 에러 발생!

case 안에 콤마(,)로 구분해서 복수의 case 조건을 혼합해 사용할 수 있다.

let anotherCharacter: Character = "a"
switch anotherCharacter {
case "a", "A":
	print("The letter A")
default:
	print("Not the letter A")
}
// Prints "The letter A"

가독성 때문에 혼합해 사용하는 경우를 여러 코드라인에 나워서 적을 수 있다.

인터벌 매칭

숫자의 특정 범위를 조건으로 사용할 수 있다.

let approximateCount = 62
let conutedThings = "moon orbiting Saturn"
let naturalCount: String
switch approximateCount {
case 0:
	naturalCount = "no"
case 1..<5:
	naturalCount = "a few"
case 5..<15:
	naturalCount = "several"
case 15..<100:
	naturalCount = "dozens of"
case 100..<1000:
	naturalCount = "hundreds of"
default:
	naturalCount = "many"
}
print("There are \(naturalCount) \(countedThings).")
// Prints "There are dozens of moon orbiting Saturn."

튜플

튜플을 조건으로 사용할 수 있다.

let somePoint = (1, 1)
switch somePoint {
case (0, 0):
	print("\(somePoint) is at the origin")
case (_, 0):
	print("\(somePoint) is on the x-axis")
case (0, _):
	print("\(somePoint) is on the y-axis")
case (-2...2, -2...2):
	print("\(somePoint) is inside the box")
default:
	print("\(somePoint) is outside of the box")
}
// Prints "(1, 1) is inside the box"

값 바인딩

특정 x, y 값을 각각 다른 case에 정의하고 그 정의된 상수를 또다른 case에 사용할 수 있다.

이런 기법을 바인딩이라고 한다.

let anotherPoint = (2, 0)
switch anotherPoint {
case (let x, 0):
	print("on the x-axis with an x vaule of \(x)")
case (0, let y):
	print("on the y-axis with an y vaule of \(y)")
case (x, y):
	print("some where else at (\(x), \(y))")
}
//  Prints "on the y-axis with an y vaule of 2"

Where 문

casewhere 조건을 사용할 수 있다.

let alseAnotherPoint = (1, -1)
switch alsoAnotherPoint {
case let (x, y) where x == y:
	print("(\(x),\(y)) is on the line x == y")
case let (x, y) where x == -y:
	print("(\(x),\(y)) is on the line x == -y")
case let (x, y):
	print("(\(x),\(y)) is just some arbitrary point")
}
// Prints "(1, -1) is on the line x == -y"

혼합 케이스

case에 콤마(,)로 구분해 여러 조건을 혼합해 사용할 수 있다.

let someCharacter: Character = "e"
switch someCharacter {
case "a", "e", "i", "o", "u":
	print("\(someCharacter) is a vowel")
case "b", "c", "d", "f", "g", "h", "j", "k", "l", "m", "n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z":
	print("\(someCharacter) is a consonant")
default:
	print("\(someCharacter) is not a vowel or consonant")
}
// Prints "e is a vowel"

혼합 케이스에서도 값 바인딩을 사용할 수 있다.

let stillAnotherPoint = (9, 0)
switch stillAnotherPoint {
case (let distance, 0), (0, let distance):
	print("On an axis, \(distance) from the origin")
default:
	print("Not on an axis")
}
// Prints "On an axis, 9 from the origin"

제어 전송 구문

제어 전송 구문은 코드의 진행을 계속 할지 말지를 결정하거나, 실해오디는 코드의 흐름을 바꾸기 위해 사용한다.

Swift는 다섯 가지의 제어 전송 구문을 제공한다.

  • continue
  • break
  • fallthrough
  • return
  • throw

continue

cuntinue문은 현재 loop를 중지하고 다음 loop를 수행하도록 한다.

let puzzleInput = "great minds think alike"
var puzzleOutput = ""
let charactersToRemove: [Character] = ["a", "e", "i", "o", "u", " "]

for character in puzzleInput {
	if characterToRemove.contains(character) {
    	continue
    } else {
    	puzzleOutput.append(character)
    }
}
print(puzzleOutput)
// Prints "grtmndthnklk"

Break 문

break문은 전체 제어문의 실행을 즉각 중지 시킨다. break문은 loopswitch문에서 사용할 수 있다.

let numberSymbol: Character = "三"  // 한자 3
var possibleIntegerValue: Int?
switch numberSymbol {
case "1", "١", "一", "๑":
    possibleIntegerValue = 1
case "2", "٢", "二", "๒":
    possibleIntegerValue = 2
case "3", "٣", "三", "๓":
    possibleIntegerValue = 3
case "4", "٤", "四", "๔":
    possibleIntegerValue = 4
default:
    break
}
if let integerValue = possibleIntegerValue {
    print("The integer value of \(numberSymbol) is \(integerValue).")
} else {
    print("An integer value could not be found for \(numberSymbol).")
}
// Prints "The integer value of 三 is 3."

위 예시에서는 numberSymbol을 확인하여 숫자 1부터 4에 대한 숫자 기호인지, 라틴어, 아랍어, 중국어 또는 태국어 기호인지 여부를 확인한다. 일치하는 항목이 발견되면 switch 문의 case 중 하나가 옵셔널 Int? 를 possibleIntegerValue에 적절한 정수 값으로 설정한다.

switch 문의 실행이 완료되면 옵셔널 바인딩을 사용하여 값이 발견되었는지 여부를 확인한다. possibleIntegerValue 변수의 초기값은 옵셔널 형식이기 때문에 nil이므로 possibleIntegerValue는 switch 문의 처음 네 가지 사례 중 하나에 의해 실제 값으로 설정되었을 경우에만 옵셔널 바인딩이 성공한다.

위의 예에서 가능한 모든 Character 값을 나열하는 것은 실용적이지 않으므로, 기본 대소문자는 일치하지 않는 문자를 처리한다. 이 default case는 어떠한 조치도 수행할 필요가 없기 때문에 하나의 break 문을 본문으로 하여 작성된다. 기본 대소문자가 일치하는 즉시 구분문은 switch 문의 실행을 종료하고 if let 문에서 코드 실행이 계속된다.

fallthrough 문

fallthrough 키워드는 이후의 case 에 대해서도 실행하게 한다. 앞에서 언급했던 것 처럼 Swift에서는 한번 특정 case 를 타면 바로 그 switch 문은 종료된다. 마치 case 안에 break 를 자동으로 넣은 것과 같은 기능을 하는 것이다. 하지만 fallthrough 를 사용하면 이 자동으로 break 가 사용되는 것을 막는 효과를 가져온다.

let integerrToDescribe = 5
var description = "The number \(integerToDescibe) is"
switch integerToDescribe {
case 2, 3, 5, 7, 11, 14, 17, 19:
	description += " a prime number, and alse"
    fallthrough
default:
	description += " an integer."
}
print("description")
// Prints "The number 5 is a prime number, and alse an integer."

주의
fallthrough는 case 조건을 확인하지 않고 그냥 다음 case를 실행하게 만든다.

레이블 구문

아래와 같은 형태로 label 이름과 while 조건을 넣어 특정 구문을 실행하는 구문으로 사용할 수 있다.

labelName: while condition {
    statements
}

이른 탈출

guard 문을 이용해 특정 조건을 만족하지 않으면 이 후 코드를 실행하지 않도록 방어코드를 작성할 수 있다.

func greet(person: [String: String]) {
	guard let name = person["name"] else {
    	return
    }
    
    print("Hello \(name)!")
    
    guard let location = person["location"] else {
    	print("I hope the weather is nice near you.")
        return
    }
    
    print("I hope the weather is nice in \(location)")
}

greet(person: ["name: "짱구"])
// Prints "Hello 짱구!"
// Prints "I hope the weather is nice near you."

greet(person: ["name: "짱구", "location": "Korea"])
// Prints "Hello 짱구!"
// Prints "I hope the weather is nice in Korea."

이용 가능한 API 버전 확인

Swift에서는 기본으로 특정 플랫폼(iOS, macOS, tvOS, watchOS)과 특정 버전을 확인하는 구문을 제공한다. 이 구문을 활용해 특정 플랫폼과 버전을 사용하는 기기에 대한 처리를 따로 할 수 있다.

if #available(platform name version, ..., *) {
	statements to execute if the APIs are available
} else {
	fallback statements to execute if the APIs are unavailable
}

신제 사용 예시

if #available(iOS 10, macOS 10.12, *) {
    // Use iOS 10 APIs on iOS, and use macOS 10.12 APIs on macOS
} else {
    // Fall back to earlier iOS and macOS APIs
}
profile
iOS 앱개발
post-custom-banner

0개의 댓글