# 2020-12-02
콜렉션 타입 (Collection Types)
swift에서는 콜렉션 타입으로 Array, set, Dictionary 세 가지를 지원합니다.
콜렉션의 변경
배열,셋,사전을 변수(var)에 할당하면 이 콜렉션은 변경가능하고 상수(let)에 할당하면 변경 불가능하다.
배열(Array)
배열의 축약형 문법 - 배열 타입은 Array로 적을 수 있는데 축약형으로 [] 형태로 사용할 수도 있음.
빈 배열의 생성
아래와 같이 Int형 빈 배열을 생성할 수 있다.
var someInts = [Int]()
print("someInts is of type [Int] with \(someInts.count) items.")
// someInts is of type [Int] with 0 items.
someInts.append(3)
// 배열에 3을 추가 했습니다.
someInts = []
// 배열을 비웠습니다. 배열의 아이템 타입은 그대로 Int로 유지됩니다.
기본 값으로 빈 배열 생성
repeating 메소드와 count 메소드를 이용해 기본 값으로 빈 배열을 생성할 수 있다.(아래)
var threeDoubles = Array(repeating: 0.0, count: 3)
// threeDoubles : Double 타입의 [0.0, 0.0, 0.0]
다른 배열을 추가한 배열의 생성(+ 연산자를 이용해 배열을 합칠 수 있다.)
var anotherThreeDoubles = Array(repeating: 2.5, count: 3)
// anotherThreeDoubles : [2.5, 2.5, 2.5]
var sixDoubles = threeDoubles + anotherThreeDoubles
// sixDoubles : [0.0, 0.0, 0.0, 2.5, 2.5, 2.5]
리터럴을 이용한 배열의 생성
var shoppingList: [String] = ["Eggs", "Milk"]
var shoppingList = ["Eggs", "Milk"] //가능(위와 같음)
배열의 접근 및 변환
배열의 원소 개수 확인(.count)
print("The shopping list contains \(shoppingList.count) items.")
// The shopping list contains 2 items.
배열이 비었는지 확인(.isEmpty)
if shoppingList.isEmpty {
print("The shopping list is empty.")
} else {
print("The shopping list is not empty.")
}
// The shopping list is not empty.
배열에 원소 추가(.append)
shoppingList.append("Four")
// shoppingList.count = 3
shoppingList += ["Baking Powder"]
// shoppingList.count = 4
shoppingList += [Chocolate Spread", "Cheese", "Butter"]
// shoppingList.count = 7
배열의 특정 위치의 원소 접근
var firstItem = shoppingList[0]
shoppingList[4..6] =["banana","apple"] //4,5,6번째 인덱스 아이템을 2개로 변환해서 3개에서 2개로 줄었다.
특정 위치에서 원소 추가/삭제/접근(.insert("내용",at:0 //위치), remove(at:0 //위치), [0], .removeLast())
shoppingList.insert("Maple Syrup", at:0)
let mapleSyrup = shoppingList.remove(at: 0)
firstItem = shoppingList[0]
// firstItem : "Six eggs"
let apples = shoppingList.removeLast()
배열의 순회
for-in loop을 이용해 배열을 순회할 수 있다.
for item in shoppingList{ print(item)}
배열의 값과 인덱스가 필요할 때는 enumerated() 메소드를 사용
for (index, value) in shoppingList.enumerated(){
print("item \(index+1): \(value)")
}
셋(set)
set 형태로 저장되기 위해서는 반드시 타입이 hashable이어야 한다. swift에서 String, Int, Double, Bool같은 기본 타입은 기본적으로 hashable이다. swift에서 set타입은 set으로 선언.
빈 set 생성
var letters = Set<Character>()
print("letters is of type Set<Character> with \(letters.count) items.")
// letters is of type Set<Character> with 0 items.
letters.insert("a")
letters = []
배열 리터럴을 이용한 Set 생성
var favoriteGenres: Set<String> = ["Rock", "Classical", "Hip hop"]
swift의 타입추론으로 아래와 같이 선언도 가능
var favoriteGenres: Set = ["Rock", "Classical", "Hip hop"]
Set의 접근과 변경
print("I have \(favoriteGenres.count) favorite music genres.")
// I have 3 favorite music genres.
if favoriteGenres.isEmpty {
print("As far as music goes, I'm not picky.")
} else {
print("I have particular music preferences.")
}
// I have particular preferences.
favoriteGenres.insert("Jazz") 추가
if let removedGenre = favoriteGenres.remove("Rock") {
print("\(removedGenre)? I'm over it.")
} else {
print("I never much cared for that.")
}
// Rock? I'm over it. 삭제
if favoriteGenres.contains("Funk") {
print("I get up on the good foot.")
} else {
print("It's too funky in here.")
}
// It's too funky in here. 값 확인(.contaions)
Set의 순회
for-in loop을 이용해 set을 순회할 수 있다.
for genre in favoriteGenres{ print ("\(genre)")}
let oddDigits: Set = [1, 3, 5, 7, 9]
let evenDigits: Set = [0, 2, 4, 6, 8]
let singleDigitPrimeNumbers: Set = [2, 3, 5, 7]
oddDigits.union(evenDigits).sorted()
// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
oddDigits.intersection(evenDigits).sorted()
// []
oddDigits.subtracting(singleDigitPrimeNumbers).sorted()
// [1, 9]
oddDigits.symmetricDifference(singleDigitPrimeNumbers).sorted()
// [1, 2, 9]
Set의 멤버십과 동등 비교
let houseAnimals: Set = ["🐶", "🐱"]
let farmAnimals: Set = ["🐮", "🐔", "🐑", "🐶", "🐱"]
let cityAnimals: Set = ["🐦", "🐭"]
houseAnimals.isSubset(of: farmAnimals) farmAnimals안에 houseAnimals있나?
// 참
farmAnimals.isSuperset(of: houseAnimals)farmAnimals안에 houseAnimals포함되나?
// 참
farmAnimals.isDisjoint(with: cityAnimals)farmAnimals안에 isDisjoint없나? 어떠한 교집합 요소가 없을 경우 트루
// 참
Set Operations 정리
contaions(_:) -set이 특정 요소를 포함하고 있는지 확인
isSubset(of)- of안에 a가 포함되어있나
isSuperset(of:) subset의 반대. a안에 of가 포함되어있나.
사전(Dictionaries)
축약형 Dictionary - [key: Value] 형태로 Dictionary를 선언해 사용할 수 있다.
var namesOfIntegers = [Int: String]()
namesOfIntegers[16] = "sixteen"
namesOfIntegers = [:]
// 빈 사전
리터럴을 이용한 Dictionary의 생성
[key 1: value 1, key 2: value 2, key 3: value 3] 형태로 사전을 선언할 수 있습니다.
var airports: [String: String] = = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
Dictionary의 접근과 변경
print("The airports dictionary contains \(airports.count) items.")
// The airports dictionary contains 2 items.
빈 Dictionary 확인
if airports.isEmpty {
print("The airports dictionary is empty.")
} else {
print("The airports dictionary is not empty.")
}
// The airports dictionary is not empty.
값 할당
airports["test"] = "London"
// the airports dictionary now contains 3 items
제어문(Control Flow) - swift에서는 while loop, if guard, switch, for-in문 등 많은 제어문을 제공합니다.
for-in문
let names = ["Anna", "Alex", "Brian", "Jack"]
for name in names {
print("Hello, \(name)!")
}
// Hello, Anna!
// Hello, Alex!
// Hello, Brian!
// Hello, Jack!
let numberOfLegs = ["spider": 8, "ant": 6, "cat": 4]
for (animalName, legCount) in numberOfLegs {
print("\(animalName)s have \(legCount) legs")
}
// ants have 6 legs
// spiders have 8 legs
// cats have 4 legs
let base = 3
let power = 10
var answer = 1
for _ in 1...power {
answer *= base
}
print("\(base) to the power of \(power) is \(answer)")
// Prints "3 to the power of 10 is 59049"
for-in 문을 순서대로 제어할 필요가 없다면, 변수자리에 _키워드를 사용하면 성능을 높일 수 있습니다.
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)
}
let hours = 12
let hourInterval = 3
for tickMark in stride(from: 3, through: hours, by: hourInterval) {
// render the tick mark every 3 hours (3, 6, 9, 12)
}
While문 (While Loops)
Repeat-While 문
구문(statements)을 최소 한번 이상 실행하고 while 조건이 거짓일 때까지 반복합니다.
repeat {
statements
} while condition
repeat {
// move up or down for a snake or ladder
square += board[square]
// roll the dice
diceRoll += 1
if diceRoll == 7 { diceRoll = 1 }
// move by the rolled amount
square += diceRoll
} while square < finalSquare
print("Game over!")
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"
암시적인 진행을 사용하지 않음 (No Implicit Fallthrough)
C와 Objective-C의 switch 구문과는 달리 Swift의 switch구문은 암시적인 진행을 하지 않습니다. C나 Objective-C에서는 switch 구문이 기본적으로 모든 case를 순회하여 default를 만날 때까지 진행됩니다. 그래서 그것을 진행하지 않기 위해 break라는 문구를 명시적으로 적어야 했습니다. Swift에서는 break를 적지 않아도 특정 case가 완료되면 자동으로 switch구문을 빠져 나오게 됩니다. 이런 사용법으로 인해 실수로 break를 적지않아 의도하지 않은 case문이 실행되는 것을 방지해 줍니다.
주의
break가 Swift에서 필수적이지는 않지만 case안에 특정 지점에서 멈추도록 하기 위해 break를 사용할 수 있습니다. 자세한 내용은 Break문을 참조해주세요.
case 안 에 최소 하나의 실행 구문이 반드시 있어야 합니다.
let anotherCharacter: Character = "a"
switch anotherCharacter {
case "a": // Invalid, case문에 body가 없으므로 에러가 발생합니다.
case "A":
print("The letter A")
default:
print("Not the letter A")
}
// 컴파일 에러 발생!
case 안에 콤마(,)로 구분해서 복수의 case 조건을 혼합(compound)해 사용할 수 있습니다.(아래)
let anotherCharacter: Character = "a"
switch anotherCharacter {
case "a", "A":
print("The letter A")
default:
print("Not the letter A")
}
// Prints "The letter A"
인터벌 매칭 (Interval Matching)
숫자의 특정 범위를 조건으로 사용할 수 있습니다.
let approximateCount = 62
let countedThings = "moons orbiting Saturn"
let naturalCount: String
switch approximateCount {
case 0:
naturalCount = "no"
case 1..<5:
naturalCount = "a few"
case 5..<12:
naturalCount = "several"
case 12..<100:
naturalCount = "dozens of"
case 100..<1000:
naturalCount = "hundreds of"
default:
naturalCount = "many"
}
print("There are \(naturalCount) \(countedThings).")
// Prints "There are dozens of moons orbiting Saturn."
튜플 (Tuple) 튜플을 조건으로 사용할 수 있습니다.
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"
값 바인딩 (Value Bindings)
특정 x, y 값을 각각 다른 case에 정의하고 그 정의된 상수를 또 다른 case에서 사용할 수 있습니다. 이런 기법을 값-바인딩(value bindings)라 부릅니다.
let anotherPoint = (2, 0)
switch anotherPoint {
case (let x, 0):
print("on the x-axis with an x value of \(x)")
case (0, let y):
print("on the y-axis with a y value of \(y)")
case let (x, y):
print("somewhere else at (\(x), \(y))")
}
// Prints "on the x-axis with an x value of 2"
Where 문
case에 where 조건을 사용할 수 있습니다.
let yetAnotherPoint = (1, -1)
switch yetAnotherPoint {
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"
혼합 케이스 (Compound Cases)
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 a 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"
제어 전송 구문 (Control Transfer Statements)
제어 전송 구문은 코드의 진행을 계속 할지 말지를 결정하거나, 실행되는 코드의 흐름을 바꾸기 위해 사용합니다. Swift에서는 다음 다섯 가지의 제어 전송 구문을 제공합니다.
continue
break
fallthrough
return
throw
continue 문
continue문은 현재 loop를 중지하고 다음 loop를 수행하도록 합니다.
let puzzleInput = "great minds think alike"
var puzzleOutput = ""
let charactersToRemove: [Character] = ["a", "e", "i", "o", "u", " "]
for character in puzzleInput {
if charactersToRemove.contains(character) {
continue
} else {
puzzleOutput.append(character)
}
}
print(puzzleOutput)
// Prints "grtmndsthnklk"
Break 문
break문은 전체 제어문의 실행을 즉각 중지 시킵니다. break문은 loop나 switch문에서 사용할 수 있습니다.
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).")
}
fallthrough 문
fallthrough 키워드는 이후의 case에 대해서도 실행하게 합니다. 앞에서 언급했던 것 처럼 Swift에서는 한번 특정 case를 타면 바로 그 switch 문은 종료됩니다. 마치 case 안에 break를 자동으로 넣은 것과 같은 기능을 하는 것이죠. 하지만 이 fallthrough 를 사용하면 이 자동으로 break가 사용되는 것을 막는 효과를 가져옵니다.
let integerToDescribe = 5
var description = "The number \(integerToDescribe) is"
switch integerToDescribe {
case 2, 3, 5, 7, 11, 13, 17, 19:
description += " a prime number, and also"
fallthrough
default:
description += " an integer."
}
print(description)
// Prints "The number 5 is a prime number, and also an integer."
fallthrough 는 case 조건을 확인하지 않고 그냥 다음 case를 실행하게 만듭니다.
레이블 구문 (Labeled Statements)
아래와 같은 형태로 label 이름과 while 조건을 넣어 특정 구문을 실행하는 구문으로 사용할 수 있습니다.
gameLoop: while square != finalSquare {
diceRoll += 1
if diceRoll == 7 { diceRoll = 1 }
switch square + diceRoll {
case finalSquare:
// diceRoll will move us to the final square, so the game is over
break gameLoop
case let newSquare where newSquare > finalSquare:
// diceRoll will move us beyond the final square, so roll again
continue gameLoop
default:
// this is a valid move, so find out its effect
square += diceRoll
square += board[square]
}
}
print("Game over!")
이른 탈출 (Early Exit)
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": "John"])
// Prints "Hello John!"
// Prints "I hope the weather is nice near you."
greet(person: ["name": "Jane", "location": "Cupertino"])
// Prints "Hello Jane!"
// Prints "I hope the weather is nice in Cupertino."
이용가능한 API 버전 확인 (Checking API Availability)
Swift에서는 기본으로 특정 플랫폼 (iOS, macOS, tvOS, watchOS)과 특정 버전을 확인하는 구문을 제공해 줍니다. 이 구문을 활용해 특정 플랫폼과 버전을 사용하는 기기에 대한 처리를 따로 할 수 있습니다. 구문의 기본 형태는 다음과 같습니다.
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
}
jusung.gitbook.io/the-swift-language-guide/language-guide/05-control-flow
'개발 > 아이오에스' 카테고리의 다른 글
swift] guard문 ....else{... (0) | 2020.12.21 |
---|---|
SWIFT(IOS) 아이콘 뱃지(숫자) 표시하는방법 (0) | 2020.12.16 |
클로저 (Closures) (0) | 2020.12.04 |
함수(Functions) (0) | 2020.12.03 |
기본 연산자 - 문자열과 문자 (0) | 2020.12.01 |