[Swift 문법] - 배열, 딕셔너리, 조건문, Loop, Switch

sun02·2021년 7월 26일
0

100 days of Swift 

목록 보기
13/40

5. Arrays

배열은 많은 값을 하나의 콜렉션에 함께 넣을 수 있게 하고 콜렉션에서 위치별로 그 값에 접근할 수 있게 한다. 스위프트는 배열이 가지고 있는 데이터 타입을 알아내기 위해 타입 추론을 사용한다.

var evenNumbers = [2, 4, 6, 8]
var songs = [“Shake if off”, “You Belong with Me”, “Back to December”]

스위프트는 배열의 시작과 끝을 표시하기 위해 대괄호를 사용하고 배열의 각 아이템들은 콤마로 구분된다.

배열의 아이템을 읽을 때 문제가 있다 : 스위프트는 0부터 읽는다. 따라서 첫 번째 아이템은 0, 두 밴째는 1, 세 번째는 2 이다. 이것을 플레이그라운드에서 해보자

var songs = [“Shake if off”, “You Belong with Me”, “Back to December”]
songs[0]
songs[1]
songs[2]

이것은 결과창에서 “Shake if off”, “You Belong with Me”, 그리고 “Back to December” 를 출력할 것이다.

배열에서 아이템의 위치는 index라 불리고 너는 인덱스를 사용하여 배열의 어떤 아이템도 읽을 수 있다. 그러나, 조심해야한다 : 우리 배열에는 세 개의 아이템이 있기에 인덱스 0, 1, 2 가 잘 작동한다. 그러나 만약 songs[3]을 읽으려 한다면 네 플라이그라운드는 작동을 멈출 것이다. – 그리고 이걸 실제 앱에서 시도한다면 충돌이 일어날 것이다!

네가 배열을 만들 때 세 개의 문자열을 넣었기 때문에 스위프트는 이것이 문자열 배열인 걸 안다. 다음과 같이 플레이그라운드에서 모든 변수의 데이터 타입을 출력하는 특수 명령을 사용하여 이것을 확인할 수 있다.

var songs = [“Shake it Off”, “You Belong with Me”, “Back to December”]
type(of: songs)

이것은 Array.Type을 결과창에 출력할 것이고고, 스위프트가 songs를 문자열 배열로 인식하고 있음을 말해준다.

네가 실수로 배열의 끝에 숫자를 넣는다고 해보자. 이것을 작성하여 결과창에 어떤 것이 출력되는지 보자

var songs = [“Shake it Off”, “You Belong with Me”, “Back to December”,3]
type(of: songs)

이번에 너는 에러를 볼 것이다. 이것은 스위프트가 이와 같은 혼합 배열을 다루지 못해서가 아니라 – 나중에 어떻게 하는지 알려줄 것이다! – 스위프트가 유용하기 때문이다.
네가 보게 될 오류 메세지는 “이중 컬렉션 리터럴은 [Any]로만 유추될 수 있다; 이것이 의도된 경우 명시적 유형 주석을 추가해라”, 또는 일반 영어로, “이 배열은 너무 많은 데이터 타입을 저장하도록 설계된 것 같다 – 이것을 의도한 것이라면 명시하여라”

타입 안전성은 중요하고 스위프트가 배열에 어떤 데이터 타입도 저장할 수 있다는 것은 분명하지만 이 특별한 경우는 사고이다. 다행히, 배열에 저장할 데이터 타입의 종류를 정확히 지정하고 싶다면 너는 유형 주석을 사용할 수 이따. 배열의 타입을 지정하려면 저장하려는 데이터의 타입을 괄호로 묶으면 된다. 다음과 같이

var songs: [String] = [“Shake it Off”, “You Belong with Me”, “Back to December”,3]

이제 우리는 배열에는 문자열만 저장하고 싶다고 스위프트에 알렸기 때문에 스위프트는 위 코드를 실행하지 않을 것이다. 왜냐하면 3은 문자열이 아니기 때문이다.

만약 여러 종류의 데이터를 가지는 배열을 원한다면, Any 데이터 타입을 사용해라

var songs: [Any] = [“Shake it Off”, “You Belong with Me”, “Back to December”,3]

- Creating arrays

위에 표시된 구문을 사용하여 배열을 만든다면 스위프트는 우리가 지정한 값으로 배열을 만들고 채운다. 배열을 만들고 나중에 채우려는 것은 간단하지 않다 – 이 구문은 작동하지 않는다.

var songs : [String]
songs[0] = “Shake it Off”

그 이유는 처음엔 불필요하게 규칙적이여 보일 수도 있지만 선응에 깊은 영향을 미치기 때문에 네가 그것에 빠질까봐 걱정이다. 단순히 var songs: [String] 이라고 적는 것은 스위프트에게 “songs 변순는 문자열 변수를 가진다”라고 말해주는 것이지 이것이 실제로 배열을 만드는 것은 아니다. 이것은 어떠한 RAM도 할당하지 않고 스위프트 배열을 만드는데에 실제로 어떠한 일을 하지도 않는다. 이것은 그저 배열이 있을 것이고 그것이 문자열을 가진다고 말해주는 것이다.

이것을 정확히 표현하는 몇 가지 방법이 있고 가장 이해가되는 방법이 이것이다.

var songs: [String] = []

이것은 우리가 문자열 배열을 만들고 싶다고 분명히 하기 위해 유형주석을 사용하고 빈 배열 [] 을 할당한다.

너는 또한 이 구조도 종종 봤을 것이다.

var songs = [String]()

이것은 같은 것을 의미한다. ()는 스위프트에게 우리가 불확실한 배열을 만들고 타입 추론을 사용하여 songs를 할당하고 싶다고 말해준다. 이 옵션은 두 개의 문자를 줄이기 때문에 프로그래머들은 이것을 선호한다

- Array operators

너는 배열에서 한정된 일련의 연산자를 사용할 수 있다. 예를 들어, 너는 +를 이용하여 두 개의 배열을 합칠 수 이따.

var songs = [“Shake it Off”, “You Belong with Me”, “Love Story”]
var songs2 = [“Today was a FairyTale”, “Welcome to New York”, Fifteen”]
var both = songs + songs2

너는 또한 더하고 할당하는 +=를 사용할 수도 있다.

both += [“Everything has Changed”]

6. Dictionaries

봐왔던 대로, 스위프트의 배열은 songs[0]과 같이 숫자 인덱스를 사용하여 개별 아이템에 접근할 수 있는 콜렉션이다. 딕셔너리는 콜렉션의 또다른 일반적인 유형의 컬렉션이지만 네가 지정한 키를 기반으로 값에 접근한다는 점에서 배열과 다르다.

예를 들기 위해, 배열에 사람 데이터를 어떻게 저장하는지 보자

var person = [“Taylor”, “Alison”, “Swift”, “December”,“taylorswift.com”]

사람의 미들네임을 읽기 위해 우리는 person[1]을 사용할 것이고 우리가 테어난 달을 읽기 위해 person[3]을 사용할 것이다. 여기엔 몇 가지 문제가 있다, 특히 배열의 각 값에 할당된 인덱스 번호를 기억하기 어렵다! 그리고 만약 그 사람이 미들네임을 갖고 있지 않다면 어떻게 될까? 다른 모든 값들의 위치가 하나씩 아래로 내려가기 때문에 네 코드에 혼란이 일어날 수도 있다.

딕셔너리로 이것을 더 합리적으로 다시 작성할 수 있다. 왜냐하면 임의의 숫자를 사용하지 않고 네가 지정한 키를 사용하여 값을 읽고 쓸 수 있기 때문이다. 예를 들어,

var person = [“first”: “Taylor”, “middle”: “Alison”, “last”: “Swfit”, “month”: “December”, “website”: “taylorswift.com”]
person[“middle”]
person[“month”]

다음과 같이 딕셔너리를 나누기 위해 공백을 많이 사용하는 것도 도움이된다.


var person = [
“first”: “Taylor”, 
“middle”: “Alison”, 
“last”: “Swfit”, 
“month”: “December”, 
“website”: “taylorswift.com”
]

person[“middle”]
person[“month”]

위에서 볼 수 있듯이, 딕셔너리를 만들 땐 키를 작성하고, 콜론을 작성한 수 값을 적는다. 너는 키를 알면 딕셔너리의 어떤 값도 읽을 수 있다. 이것이 작업하기 훨씬 편하다

배열과 마찬가지로 키는 일반적으로 문자열이지만 딕셔너리 안에 다양한 값을 저장할 수 있다.

7. Conditional statements

가끔 너는 특정 조건이 참일 때만 코드를 실행시키고 싶을 것이다. 그리고 스위프트에서 이것은 주로 if else 구문으로 표현된다. 네가 스위프트에 확인해야할 조건을 준 다음 그 조건이 참일 경우 실행할 코드 블럭을 준다.

너는 선택적으로 else를 작성하여 조건이 거짓일 때 실행할 코드 블럭을 제공하거나 더 많은 조건을 위해 else if 를 제곻할 수 있다. 코드의 “블럭”은 시작부분에 열린 중괄호 - { - 끝 부분에 닫힌 중괄호 - } – 로 표시된 코드 덩이리이다.

여기 간단한 예시가 있다.

var action : String
var person = “hater”

if person == “hater” {
   action = “hate”
}

여기서 Person 안의 문자열이 “hater”문자열과 정확히 일치하는지 확인하기 위해 == 연산자를 사용한다. 만약 그렇다면, action 변수를 “hate”로 설정한다. “curly brackets”라는 덜 기술적인 이름으로도 알려진 열기 및 닫기 중괄호가 조건이 참인 경우 실행하게 될 코드의 시작과 끝을 표시한다.

else if와 else 블럭을 추가해보자:

var action: String
var person = “hater”

if person == “hater” {
    action = “hate”
} else if person == “player” {
    action = “play”
} else {
    action = “cruise”
}

이것은 각 조건을 순서대로 확인하고 이 중 하나의 블럭만 실행된다: 한 Person은 헤이터이거나, 플레이어 이거나 또는 다른 무언가 이다.

- Evaluating multiple conditions

너는 네가 원하는 만큼 많은 조건을 평가하도록 스위프트에 요청할 수 있지만 스위프트가 코드 블럭을 실행하려면 조건이 모두 참이어야한다. 여러 조건을 확인하기 위해, && 연산자 – “그리고”를 의미함 – 를 사용한다. 예를 들어:

var action: String
var stayOutTooLate = true
var nothingInBrain = true

if stayOutTooLate && nothingInBrain {
    action = “cruise”
}

stayOutTooLate 와 nothingInBrain이 둘 다 참이기 때문에 전체 조건은 참이고 action은 “cruise”가 된다. 스위프트는 단락 평가 (short-circuit evalution)을 사용하여 성능을 향상시킨다: 만약 모두 참이어야하는 여러가지 항목을 평가할 때, 첫 번째 항목이 거짓이라면 나머지는 평가하지도 않는다.

Looking for the opposite of truth

매우 철학적이게 들릴 수 있지만, 실제로 이것은 중요하다: 가끔 너는 조건이 참이 아닌지, 즉 거짓인지 신경을 쓴다. 너는 이것을 이전에 소개되었던 !(not)연산자를 사용하여 할 수 있다. 예를 들어,

If !stayOutTooLate && !nothingInBrain {
    Action = “cruise”
}

이번에는 stayOutLate 과 nothingInBrain이 모두 거짓이면 action 변수가 설정될 것이다. - !가 이들을 뒤집었다.

8. Loops

컴퓨터는 네가 이 문장을 읽는 데 걸리는 시간 동안 지겨운 작업을 수십억 번 수행하는데 탁월하다. 코드에서 작업을 반복하는 경우, 너는 코드를 여러 번 복사 붙여 넣기 하거나 loop를 사용할 수도 있다 – 조건이 참일 때 코드 블럭을 반복하는 간단한 프로그래밍 구조이다.

이를 보여주기 위해, 나는 특수한 디버깅 함수인 print()를 소개할 것이다. : 네가 출력할 텍스트를 주면, 이것은 출력한다. 만약 플레이그라운드에서 실행하고 있다면, 너는 결과 창에서 텍스트를 볼 수 있을 것이다. Xcode에서 실제 앱을 실행하고 있다면, 텍스트가 엑스코드의 로그 창에 나타나는 것을 볼 수 잇을 것이다. 어느 쪽이든, pring()는 는 변수의 내용을 살짝 엿볼 수 있는 좋은 방법이다.

이 코드를 살펴보자:


print(“1 x 10 is \(1*10)”)
print(“2 x 10 is \(2*10)”)
print(“3 x 10 is \(3*10)”)
print(“4 x 10 is \(4*10)”)
print(“5 x 10 is \(5*10)”)
print(“6 x 10 is \(6*10)”)
print(“7 x 10 is \(7*10)”)
print(“8 x 10 is \(8*10)”)
print(“9 x 10 is \(9*10)”)
print(“10 x 10 is \(10*10)”)

실행이 끝나면 플레이그라운드 결과창에 10번의 테이블이 표시된다. 하지만 이것은 효율적이지 않고 훨씬 깔끔한 방법은 닫힌 범위 연산자(...)를 사용하여 숫자 범위를 반복하는 것이다.

닫힌 범위 연산자를 사용하여 우리는 저 모든 것을 세 줄로 다시 작성할 수 있다:

for i in 1…10 {
    print(“\(i) x 10 is \(i* 10)”)
}

결과창은 이 루프에 대해 “(10 times)”만 보여주고 이것은 해당 루프가 열 번 실행되었다는 의미이다. 루프가 실제로 어떤 것을 했는지 알고 싶다면, “(10 times)” 오른쪽의 네모를 눌러봐라. 코드 안에서 “10 x 10 is 100”이라는 상자를 볼 것이고 이 상자를 우클릭한다면 “Value History” 옵션이 나타날 것이다. 이것을 클릭하면, 아래와 같은 그림을 볼 수 있을 것이다.

루프는 1부터 10까지(1과 10을 포함하여) 세고, 그 숫자를 상수 i 에 할당한 다음 괄호 안의 코드 블럭을 실행하였다.

현재 번호를 알 필요가 없다면, 밑줄을 대신 사용할 수 있다. 예를 들어, 테일러 스위프트의 가사를 다음과 같이 출력할 수 있다.

var str = “Fakers gonna”

for _ in 1 … 5 {
    str += “ fake”
}

print(str)

이것은 루프가 돌아갈 때마다 문자열을 추가함으로써 “Fakers gonna fake fake fake fake fake” 를 출력할 것이다.

만약 루프가 돌 때마다 변수에 각 숫자를 할당할 필요가 없다면, 코드는 조금 더 빨리 실행할 수 이다. 만약 i in … 을 작성한 뒤 i 를 사용하지 않는다면 엑스코드는 i 를 _로 바꾸도록 제안할 것이다.

반 개방 범위 연산자라 불리는 닫힌 범위 연산자의 변형이 있고 이들은 혼돈되기 쉽다. 반 개방 범위 연산자는 ..< 같이 생겼고 한 숫자에서 다른 숫자까지 계산하고 마지막 숫자는 제외한다. 예를 들어, 1..<5 는 1, 2, 3, 4를 셀 것이다.

- Looing over arrays

스위프트는 배열의 모든 요소를 반복하는 아주 간단한 방법을 제공한다. 배열 안에 어떤 종류의 데이터를 가지고 있는지 스위프트는 이미 알기 때문에 배열의 모든 요소를 살펴보고 네가 이름지은 상수에 이것을 할당하고 코드의 블럭을 실행한다. 예를 들어, 다음과 같이 노래 목록을 인쇄할 수 있다.


var songs = [“Shake it Off”, “You Belong with Me”, “Look What You Made Me Do”]

for song in songs {
    print(“My favorite song is \(song)”)
}

너는 배열을 반복하기 위해 for i in 루프 구조를 사용할 수 있다 왜냐하면 해당 상수를 이용하여 배열을 인덱싱할 수 있기 떄문이다. 다음과 같이 두 개의 배열을 인덱싱하는데 사용할 수도 있다.

var people = [“players”, “haters”, “heart-breakers”, “fakers”]
var actions = [“play”, “hate”, “break”, “fake”]

for I in 0…3 {
    print(“\(people[i] gonna \(actions[i])”)
}

너는 반 개방 범위 연산자가 무엇을 사용하는지 궁금할수도 있지만 배열은 0에서부터 계산하기 때문에 배열 작업에서 특히 유용하다. 따라ㅏ서, 0에서 3까지 3을 포함하여 계산하는 대신 0부터 배열의 아이템 개수까지 아이템 개수를 제외하고 셀 수 있다.

기억해라 : 만약 4개의 아이템을 가지고 있다면 0부터 세기 때문에 최대 인덱스는 3이다. 이것이 우리가 루프에서 제외를 사용해야하는 이유이다.

배열 안에 얼마나 많은 아이템이 있는지 세기 위해서, someArray.count를 사용해라. 우리는 코드를 다음과 같이 재작성할 수 있다.


var people = [“players”, “haters”, “heart-breakers”, “fakers”]
var actions = [“play”, “hate”, “break”, “fake”]

for I in 0..< people.count {
    print(“\(people[i] gonna \(actions[i])”)
}

Inner loops

원한다면 루프 안에 루프를 넣을 수도 있다. 또는 루프 안에 루프 그 안에 루프를 넣을 수도 있다 – 갑자기 천만 번 수행하고 있다는 것을 발견하게 될 수도 있으므로 조심해라!

우리는 이전의 두 개의 루프를 결합하여 이것을 만들 수 있다.


var people = [“players”, “haters”, “heart-breakers”, “fakers”]
var actions = [“play”, “hate”, “break”, “fake”]

for I in 0..< people.count {
    var str = “\(people[i] gonna”

    for _ in 1…5 {
        str += “\(actions[i])”
    }

    print(str)
}

이것은 “players gonna play play play play play” 를 출력한 후 haters gonna …” 를 출력한다. 이제, 당신은 아이디어를 얻었다.

한 가지 중요한 참고 : 프로그래머는 일반적으로 루프 상수에 I, j, k를 사용하지만 원하는 대로 이름을 지을 수 있다 : for personNumber in 0..< people.count 도 완벽히 유효하다.

2. While loops

세 번째 유형의 루프는 네가 멈추라고 할 때까지 코드블럭을 반복한다. 이것은 게임이 얼마나 오래 지속될지 미리 알 수 없는 게임 루프와 같은 것에 사용된다. – 너는 사용자가 게임종료를 누르거나 메인매뉴로 돌아가기 까지 계속해서 “터치확인, 로봇 애니메이션, 화면 그리기, 터치확인 ..” 을 반복한다.

이 루프는 while 루프라 불리고 다음과 같이 생겼다.

var counter = 0

while true {
    print(“Counter is now \(counter)”)
    counter += 1

    if counter == 556 {
        break
    }
}

이 코드는 새로운 키워드 break 를 소개한다. 이것은 네가 지정한 지점에서 while이나 for 루프문을 종료시킬 때 사용된다. 조건이 “참”이기 때문에 이것이 없다면 코드는 절대 끝나지 않는다. Break 문이 없다면 이 루프는 무한 루프이고 이것은 좋지 않다.

이러한 while 문은 인터넷으로부터 다운을 받거나 XML 파일을 읽을 거나, 사용자의 입력을 살피는 등 과 같이 네가 잘 모르는 데이터를 사용할 때 유용하다. 이는 루프를 충분히 여러 번 실행한 후에야 언제 중지할 지 알 수 있기 때문이다.

Break의 대응으로는 continue가 있다. 루프에서 벗어나는것은 실행을 즉시 멈추고 루프 다음을 바로 계속하는 반면, 루프를 지속하는 것은 루프의 현재 반복만 종료한다. – 루프의 맨위로 점프하여 거기서 시작한다.

예로 아래의 코드를 보자

var songs = [“Shake it Off”, “You Belong with Me”, “Look what You Made Me Do”]

for song in songs {
    if song == “You Belong with Me” {
        continue
    }

    print(“My favorite song is \(song)”)
}

이것은 테일러 스위프트의 세 곡을 반복하지만 두 개만 출력한다. Continue키워드 때문이다 : 루프가 “You Belong with Me”를 사용하려고 할 때 continue가 호출되고, 이것은 해당 루프가 즉시 시작 부분으로 다시 점프한다 – print()호출은 수행되지 않는 대신 루프는 “Look what You Made Me Do”로 계속 이어진다.

9. Switch case

너는 if 문과 이제 루프도 보았지만 스위프트는 switch/case 라 불리는 또다른 타입의 흐름 제어를 가진다. 이것을 If 의 고급 형태라고 생각하는 것이 가장 쉽다. 왜냐하면 많은 일치 항목을 가질 수 있고 스위프트는 올바른 항목을 실행할 것이기 때문이다.

가장 기본적인 switch/case 형태에서 너는 스위프트에 네가 확인하고 싶은 변수를 알리고 해당 변수에 대해 가능한 케이스 목록을 제공한다. 스위프트는 변수와 일치하는 첫 번째 케이스를 발견한 후 해당 코드블럭을 실행한다. 그 블럭이 끝나면 스위프트는 전체 switch/case 블럭을 종료한다.

여기 간단한 예시가 있다:


let liveAlbums = 2

switch liveAlbums {
case 0:
    print(“You’re just starting out”)

case 1:
    print(“You just released iTunes Live From SoHo”)

case 2:
    print(“You just released Speak Now World Tour”)

default:
    print(“Have you done something new?”)
}

우리는 if 나 else if문을 사용하여 작성할 수도 있지만 이 방법이 훨씬 명확하고 이것은 중요하다.

Switch/case의 장점은 스위프트가 케이스들을 보장한다는 것이다. 즉, 확인하지 않은 값이 변수에 있는 경우 엑스코드는 앱 빌드를 거부한다.

liveAlbums정수와 같이 값들이 효과적으로 열린 상태에서는 너는 잠재적 값을 포착하기위해 디폴트 케이스를 포함해야한다. 맞아, 네 데이터가 특정 범위 내에만 속한다는 것을 알고 있더라도 스위프트는 절대적으로 확신하기를 원한다.

스위프트는 변수와 일치시키기위해 case문에 몇 개의 평가를 적용할 수 있다. 예를 들어, 만약 가능한 값의 범위를 확인하고 싶다면 너는 닫힌 범위 연산자를 다음과 같이 사용할 수 있다.


let studioAlbums = 5

switch studioAlbums {
case 0…1:
    print(“You’re just starting out”)

case 2…3:
    print(“You’re a rising star”)

case 4…5:
    print(“You’re world famous!”)

default:
    print(“Have you done something new?”)
}

너는 스위프트의 switch/case 블럭은 다른 언어에서 본 것처럼 fall 하지 않는다는 것을 알아야한다. 만약 네가 케이스 블럭에서 break를 쓰는데에 익숙하다면 이것이 스위프트에서는 필요없다는 것을 알아야한다.

대신 너는 fallthrough 키워드를 사용하여 한 케이스가 다음 케이스로 넘어가도록 만들 수 있다. 물론 이것이 어떤 것을 의미하는지 모른다면 더 좋다 : 걱정하지 마!

                                                          

0개의 댓글