본문 바로가기

Programming/iOS

[Swift] The Basics

반응형

변수/상수

변수와 상수는 이름을 가지고 있다. 상수는 값을 변경할 수 없다. 변수는 값을 변경할 수 있다.


변수/상수 선언

변수의 type은 한번 정해지면 변경될 수 없다.

상수는 let 키워드로 선언하고 변수는 var 키워드로 선언한다.

  • let maximumNumberOfLoginAttempts = 10
  • var currentLoginAttempt = 0

한번에 여러 변수/상수를 선업할 수 있다.

  • var x = 0.0, y = 0.0, z = 0.0


타입 지정 (Type Annotations)

변수/상수를 선언할때 type을 명확하게 하기 위해 type을 지정할 수 있다.

welcomeMessage 이름의 변수가 String값을 가지게 된다면 

  • var welcomeMessage: String

(:)이 의미하는건 `... 의 type이 ... 이다` 

즉, welcomeMessage 의 type이 String 이다.

이건 String의 값만 저장할 수 있다는 말이다. nil도 허용되지 않는다.


변수/상수 네이밍

유니코드에 포함된 모든 문자로 네이밍할 수 있다. 즉, 한글도 가능!

  • let π = 3.14159
  • let 你好 = "你好世界"
  • let 개발자 = "초프"

이름에는 수학기호, 화살표, 내부에서 사용하는 유니코드, line-drawing, box-drawing등은 포함할 수 없다. 이름에 수가 포함될 수 있지만 수로 시작할 수 없다. test1234는 가능하지만 1234test는 불가능하다.

한번 선언된 이름으로 다시 선언할 수 없다.

변수는 호환 가능한 type이라면 대입하여 현재 값을 대체할 수 있다.

  • var friendlyWelcome = "Hello!"
  • friendlyWelcome = "Bonjour!"
  • // friendlyWelcome is now "Bonjour!"

상수는 변수와 다르게 한번 정해진 값은 변경할 수 없다. 변경을 시도하면 컴파일 오류가 발생한다.

  • let languageName = "Swift"
  • languageName = "Swift++"
  • // this is a compile-time error - languageName cannot be changed


변수/상수 출력

print, println 전역 함수를 사용하여 값을 출력할 수 있다. print 는 단순 출력이고 println은 출력 후 개행문자를 출력하여 다음줄로 이동한다.

  • println(friendlyWelcome)
  • println("This is a string")

문자열 안에 변수/상수 값을 출력하고 싶으면 변수명을 소괄호() 로 감싸고 앞에 sbackslash(\) 를 붙이면 된다.

  • println("The current value of friendlyWelcome is \(friendlyWelcome)")
  • // prints "The current value of friendlyWelcome is Bonjour!"


주석

C, Objective-C 의 주석과 동일하다. 한줄 주석은 slash(/) 두개로 시작한다.

  • // this is a comment

블럭 주석은 /* 로 시작하여 */ 로 끝난다.

  • /* this is also a comment,
  • but written over multiple lines */

기존 언어와 다른 점은 블럭 주석안에 블럭 주석도 허용한다는 것이다. 가장 바깥에 있는 주석이 적용된다.


Semicolons

다른 많은 언어들과 다르게 세미콜론(;)이 필요하지 않다. 다른 언어들은 명령 한줄이 끝나면 세미콜론으로 줄로 끝을 알려준다. 하지만 Swift에서는 필요없다. 하지만... 원한다면 사용해도 된다. 여러 명령을 한줄에 쓰고 싶다면 써야 한다.

  • let cat = "A"; println(cat)
  • // prints "A"


정수

소수부분이 없고 부호를 포함하는 수이다. 부호를 포함하는 signed(음수,0,양수)와 부호가 없는 unsigned(0, 양수)가 있다.

Swift는 8, 16, 32, 64 bit의 정수를 제공한다. 이 정수들의 네이밍은 C와 유사하다. 예를 들어 8bit unsigned 정수이면 UInt8, 32bit signed 정수는 Int32 이다. 대문자를 구분한다.


정수 범위

각 정수 type에 min, max 속성이 있어 최소,최대 값을 알 수 있다.

  • let minValue = UInt8.min // minValue는 unsigned 정수 최소값인 0이다.
  • let maxValue = UInt8.max // maxValue는 unsigned 정수 최대값인 255이다.


Int

대부분의 경우 정수의 사이즈를 지정하지 않아도 된다. Swift는 추가적으로 Int type을 제공한다. 현재 플랫폼의 native word size와 같은 크기의 정수 type의 크기가 된다.

32bit 플랫폼에서는 Int는 Int32와 같다.

64bit 플랫폼에서는 Int는 Int64와 같다.


UInt

Int와 같이 unsigned int인 UInt도 제공한다. 크기는 Int와 똑같은 방법으로 정해진다.

32bit 플랫폼에서 UInt는 UInt32와 같다.

64bit 플랫폼에서 UInt는 UInt64와 같다.


부동 소수점 수

소수부분이 포함되는 수이다. 3.14159, -273.15

정수보다 더 큰 범위의 수를 나타낼 수 있다. Swift에는 2개의 부동 소수점 수 type을 제공한다.

Double - 64bit 부동 소수점 수. 매우 큰 수, 특별히 정확해야 할때 사용한다.

Float - 32bit 부동 소수점 수. 64bit 의 정확도가 필요 없을때 사용한다.


Type Safety and Type Inference

Swift는 type safe한 언어이다. 값 type을 명확하게 해준다. String인 변수에 Int값을 대입할 수 없다.

Type-checking은 다른 type의 값을 사용하면서 발생할 수 있는 오류를 피하게 해준다. 그렇지만 모든 변수, 상수 선언에 type을 지정해야 하는 것은 아니다. 원한다면 type을 지정하지 않아도 된다. Swift는 알아서 적절한 type을 추론해준다. 

C, Objective-C보다 변수/상수 선언이 간단해졌지만 여전히 명확한 type이 존재한다. type을 지정하는 일을 대신해준다.

type 추론은 변수/상수 초기값을 지정한 선언에서 유용하다. 선언할때 값만 넣어주면 된다. 

예를 들어 type지정 없이 42로 초기화 하면 수처럼 보이기 때문에 Swift는 Int로 추론한다.

  • let meaningOfLife = 42
  • // meaningOfLife is inferred to be of type Int

만약 type 지정없이 부동 소수점 수로 초기화 하면 Double로 추론된다.

  • let pi = 3.14159
  • // pi is inferred to be of type Double

Float이 아닌 항상 Double로 추론된다.

만약 정수와 부동 소수점 수 를 같이 사용한다면 Double로 추론된다.

  • let anotherPi = 3 + 0.14159
  • // anotherPi is also inferred to be of type Double

3은 type이 지정되어 있지 않다. 이 식의 type은 소수부분이 존재하므로 Double로 추론된다.


Numeric Literals

정수는 다음과 같이 쓰여진다.

  • 10진수는 접두사 없음
  • 2진수는 점두사 0b
  • 8진수는 접두사 0o
  • 16진수는 접두사 0x

10진수 정수 17은 다음과 같이 표현될 수 있다.

  • let decimalInteger = 17
  • let binaryInteger = 0b10001
  • let octalInteger = 0o21
  • let hexadecimalInteger = 0x11

부동소수점 수는 10,16진수로 표현 가능하다. 선택적으로 승을 표현할 수 있다. 10진수에는 밑이 10인 대소문자 e, 16진수에는 밑이 2인 대소문자 p로 승을 표현한다.

1.25e2 는 1.25 x 10^2 또는 125.0 이다.
1.25e-2 는 1.25 x 10^(-2) 또는 0.0125 이다.

0xFp2 는 15 x 2^2 또는 60.0 이다.
0xFp-2 는 15 x 2^(-2) 또는 3.75 이다.

아래 3개의 상수는 모두 12.1875 값을 가진다.

  • let decimalDouble = 12.1875
  • let exponentDouble = 1.21875e1
  • let hexadecimalDouble = 0xC.3p0

Numeric literals에는 읽기 쉽게 하기 위해 여분의 형식이 존재한다. 정수, 실수 모두 숫자 앞에 여분의 0 을 붙이거나 밑줄을 포함할 수 있다. 밑줄은 무시되고 앞에 있는 0또한 무시된다.

  • let paddedDouble = 000123.456
  • let oneMillion = 1_000_000
  • let justOverOneMillion = 1_000_000.000_000_1


Numeric Type Conversion

일반적인 경우 정수 변수, 상수에서 음수가 되지 않는다고 해도 Int를 사용해라. 모든 경우 기본 정수 type을 사용하면 플랫폼에 상관없이 동일한 크기의 type이 지정되므로 호환성이 좋아진다. 

  • var numberA : Int8 = 1
  • var numberB : Int16 = 2
  • numberB = numberA
  • numberA = numberB

numberA, numberB 가 모두 정수라고 해도 8bit, 16bit 크기가 다르므로 서로 호환가능하지 않다. 서로 다른 타입이라고 보면 된다. 그래서 b = a, a = b는 컴파일 오류가 발생한다. Int8을 Int16으로 변환할 수 없고 Int16을 Int8로 변한할 수 없기 때문이다.

성능, 메모리 사용, 최적화 등 직접 다뤄야하는 특별한 상황일때만 기본 Int, UInt가 아닌 다른 정수 type을 사용하자.


정수 변환

각 정수 type에 따라 저장될 수 있는 값의 범위가 다르다. 

Int8 : -128 ~ 127
UInt8  : 0 ~ 255

값이 유요한 범위에 맞지 않는다면 컴파일 오류가 발생한다.

  • let cannotBeNegative: UInt8 = -1
  • let tooBig: Int8 = Int8.max + 1

케이스별로 정수변환을 허용해줘야 한다. 이 방법은 변환중 발생할 수 있는 에러를 방지한다.

다른 type으로 변환하기 위해서는 원하는 타입으로 새로운 수를 초기화 해줘야 한다.

  • let twoThousand: UInt16 = 2_000
  • let one: UInt8 = 1
  • let twoThousandAndOne = twoThousand + UInt16(one)

twoThousand + one 은 서로 다른 type이라 계산이 불가능하다. 하지만 UInt16(one)을 해주므로써 one의 값을 UInt16 type의 값으로 새로 만든다. twoThousand 와 type이 같아져서 계산이 되고 twoThousandAndOne은 UInt16으로 추론된다.

SomeType(ofInitialValue)는 Swift에서 변환하는 기본적인 방법이다. UInt16에는 UInt8의 값을 받을 수 있는 초기화가 있어서 기존에 있던 UInt8의 값으로 새로운 UIn16을 만들 수 있다. 여기에 아무 type이나 넣으면 안된다. 초기화에 정해진 type만 가능하다. 


정수와 부동소수점 수 변환

정수와 부동소수점 수 사이에 변환도 정수변환과 같이 명확하게 type을 지정해 줘야 한다.

  • let three = 3
  • let pointOneFourOneFiveNine = 0.14159
  • let pi = Double(three) + pointOneFourOneFiveNine
  • // pi는 3.14159 이 되고 Double type으로 추론된다.

three가 새로운 Double로 만들어 진다. 그럼 pointOneFourOneFieNine과 같은 Double type이 된다. 변환없이는 계산이 허용되지 않는다.

부동소수점 수 에서 정수로 변환도 가능하다. 정수로 변환하면 소수점 부분은 모두 버려진다.

  • let integerPi = Int(pi)
  • // integerPi equals 3, and is inferred to be of type Int


Type 별칭 (Type Aliases)

존재하는 type 을 다른 이름으로 별칭을 정의할 수 있다. C 계열의 typedef와 같다. typealias 키워드를 이용하면 된다.

존재하는 type을 좀더 적절한 이름으로 변경할때 유용하다.

  • typealias AudioSample = UInt16
  • var maxAmplitudeFound = AudioSample.min
  • // maxAmplitudeFound is now 0

AudioSample.min 은 UInt16.min과 같다.


Booleans

Swift에는 기본 Boolean type을 제공하며 Bool이라고 한다.  true, false 값만 가질 수 있다.

  • let orangesAreOrange = true
  • let turnipsAreDelicious = false

bool 값으로 초기화 되서 orangesAreOrange, turnipsAreDelicious 는 모두 Bool로 추론된다.

Bool은 조건문에서 유용하다. 

  • if turnipsAreDelicious {
  • println("Mmm, tasty turnips!")
  • } else {
  • println("Eww, turnips are horrible.")
  • }
  • // prints "Eww, turnips are horrible."

C, Objective-C와 다르게 true,false가 아닌 값이 true,false를 대신할 수 없다. Java와 같이 Bool은 Bool이어야 한다.

  • let i = 1
  • if i {
  • // i는 Bool이 아니라 Int이기 때문에 컴파일 오류가 발생한다.
  • }
  • let i = 1
  • if i == 1 {
  • // == 로 논리 비교를 하였기 때문에 결과는 Bool이 되어서 문제가 없다.
  • }


Tuples

single compound value안에 여러개의 값을 그룹화 시켜준다. 

  • let http404Error = (404, "Not Found")
  • // http404Error is of type (Int, String), and equals (404, "Not Found")

http404Error는 (Int, String) type의 튜플이다.

튜플은 많은 타입을 포함할 수 있다.

튜플의 값들은 변수/상수로 분해될 수 잇다.

  • let (statusCode, statusMessage) = http404Error
  • println("The status code is \(statusCode)")
  • // prints "The status code is 404"
  • println("The status message is \(statusMessage)")
  • // prints "The status message is Not Found"

튜플 중 특정 값만을 원한다면 무시할 부분에는 밑줄(_)을 이용하면 된다.

  • let (justTheStatusCode, _) = http404Error
  • println("The status code is \(justTheStatusCode)")
  • // prints "The status code is 404"

array처럼 각각의 element에 접근할 수 있다. 시작은 0부터이다.

  • println("The status code is \(http404Error.0)")
  • // prints "The status code is 404"
  • println("The status message is \(http404Error.1)")
  • // prints "The status message is Not Found"

각각의 element에 이름을 정의할 수 있다.

  • let http200Status = (statusCode: 200, description: "OK")
  • println("The status code is \(http200Status.statusCode)")
  • // prints "The status code is 200"
  • println("The status message is \(http200Status.description)")
  • // prints "The status message is OK"

함수의 return값으로 쓰기에 유용하다. 하나의 type을 return받는 것 보다 더 많은 유용한 정보를 받을 수 있다.


나머지는.... 다른 곳에 번역이 너무 잘 되어 있어서 이만 한다...

나도 이제 번역된거 봐야지~ ㅋ

반응형