스위프트의 자료형

개요


스위프트에서 기본적으로 사용하는 Int나 String같은 자료형과 튜플이나 딕셔너리처럼 심화적인 자료형에 대해 알아보겠다.

스위프트는 Type Safety 언어이다. 값을 잘못된 자료형에 대입했을 때 컴파일 오류가 발생한다. 이로써 다른 타입의 값을 할당하는 실수를 줄일 수 있다.

또한 스위프트는 자료형을 명시해주지 않아도 값에 따라 자료형을 결정할 수 있다. 이것을 Type Inference라고 부른다.

애플 공식 스위프트 문서에는 거의 Type Inference를 사용하여 선언한다. 자료형을 명시해주지 않는다는 뜻.




변수, 상수의 자료형 출력


type(of:_)메서드를 사용하면 된다.

1
2
var exVar: Int = 10
print(type(of:exVar)) // Int




type alias


스위프트에서 지원하는 자료형에 이름을 붙여서 사용할 수 있다. typealias를 이용한다.

1
typealias MyInt = Int




Integers(인트)


Integer는 다른 언어에서도 가장 기본으로, 많이 사용하는 자료형이다. 정수를 표현하는 자료형이며 IntUInt로 구분할 수 있다.

스위프트는 부호 있는, 없는 8, 16, 32, 64비트이 형태를 지원한다. 표현하고 싶은 비트를 IntUInt뒤에 붙여주면 된다.

그냥 Int만 쓰면 환경에 따라 결정된다. 예를 들어 64비트 환경이면 Int == Int64인 것이다.

1
2
var decimal: Int = -10
var integer: UInt = 10




Bool(부울)


True or False만 표현 할 수 있는 불리언 자료형도 지원한다. Bool로 사용할 수 있다.

1
var truefalse: Bool = true




Floating-Point Numbers(부동소수)


소수점을 가지고 있는 숫자를 부동소수라고 한다. 이런 숫자들을 표현할 때는 FloatDouble를 사용하면 된다.

Double은 64비트의 표현이 가능하고 Float는 32비트의 표현이 가능하다. 즉 15자리의 십진수, 6자리의 숫자까지만 표현이 가능하다.

1
2
var fraction: Float = 12.06
var fraction: Double = 12.06




Character(캐릭터)


Charater형은 문자를 표현할 때 사용하며 Char이 아닌 Character를 사용해서 표현한다.

C언어와 다르게 스위프트에서는 문자를 표현할 때도 쌍따옴표를 사용한다.

1
var literal: Character = "A"




String(스트링)


문자열을 표현할 때는 String을 사용해서 표현한다. 다른 언어처럼 쌍따옴표로 문자열을 표현한다.

c++에서 처럼 +기호를 사용해서 문자열들을 합칠 수가 있다.

여러줄로 표현하고 싶다면 쌍따옴표 3개를 쓰면 된다.

1
2
3
4
5
6
7
8
9
10
var str: String = "Hello my name is"
var name: String = str + "kyujin"
str += "kyujin"
var ex: String = """
hello
my name
is kyujin
"""
print(str)// Hello my name is kyujin
print(name)// Hello my name is kyujin




Any, AnyObject(애니)


Any는 스위프트의 모든 자료형을 사용할 수 있다는 뜻이다.

AnyObject는 클래스의 인스턴스만 사용할 수 있다.

Any로 선언된 변수,상수는 어떤 자료형의 값으로 초기화 할 수 있다.

스위프트는 엄격한 자료형 규칙을 가지고 있으므로 되도록이면 사용하지 않는다.

1
2
3
var everything: Any = "hi"
everything = 1206
everything = 12.06




nil(닐)


c언어의 NULL과 같은 것

그냥 없음을 나타내는 것이다. 옵셔널 변수를 사용할 때 초기화를 시키지 않으면 기본으로 nil로 세팅된다.

1
2
var exInt: Int = 10
exInt = nil




Tuples(튜플)


튜플은 여러개의 값을 하나의 그룹으로 묶은 것이다. 튜플 안의 값들은 모두 같은 자료형이 아니어도 된다.

튜플은 컬렉션 자료형이 아니다. 따라서 다른 컬렉션 자료형처럼 순회는 불가능하다. 단지 임시 저장소 역할만한다.

그러므로 임시적으로 데이터를 담는 곳에는 유용하지만 복합적인 자료구조나 영구범위로 사용한다면 클래스나 구조체를 만드는 것이 낫다.

튜플의 사용방법은 코드의 예로 살펴보겠다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var exTuple = (1206, "birthday") //type of exTuple is (Int, String)
var (ex1, ex2) = exTuple //ex1 = 1206, ex2 = "birthday"
var (ex3, _) = exTuple // ex3 = 1206 and the other value is ignored
print(exTuple.0) //1206
print(exTuple.1) //birthday

var exTuple2: (Int, String) = (1206, "birthday")
print(exTuple2.0) //1206
print(exTuple2.1) //birthday

var exTuple3 = (date: 1206, description: "birthday")
print(exTuple3.date) //1206
print(exTuple3.description) //birthday

var exTuple4: (date: Int, description: String) = (1206, "birthday")
print(exTuple4.date) //1206
print(exTuple4.description) //birthday

typealias exTuple5 = (date: Int, description: String)
var kyujin: exTuple5 = (1206, "birthday")




Array(배열)


튜플이 다른 자료형의 집합이었다면 배열은 같은 자료형을 가진 값들의 나열이다. Array, 중괄호를 이용하여 선언한다.

C언어에서의 배열은 선언할 때 크기가 고정되던 버퍼였다. 배열의 크기를 바꾸기 위해서는 malloc()함수를 사용하여 동적배열로 사용해야했다.

그러나 스위프트에서 지원하는 배열은 디폴트가 동적배열로 알아서 버퍼의 크기를 조절해준다. c++의 STL와 같이 메서드와 프로퍼티로 배열의 정보를 얻을 수 있다.

배열을 생성하면 배열 요소를 저장하기 위한 추가 저장 공간이 할당된다. 이 공간을 Array’s Capacity라고 한다.

스위프트는 Exponential growth strategy를 따르며 배열에 요소가 추가될 때마다 그만큼 자동으로 용량을 증가시킨다.

만약 대량의 요소가 추가될 것을 아는 경우 reserveCapacity메서드를 이용하여 추가적인 배열 용량을 할당주면 좋다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//빈 배열 생성
var emptyArray: [Any] = [Any]()                       //[Any]() == Array<Any>() == []
print(emptyArray.isEmpty)                             //true

//String 배열 선언
var exArray: [String] = ["ex0", "ex1", "ex2"]    //Array<String> == [String]// 짧은거 선호
print(exArray[0], exArray[1], exArray[2])             //ex0 ex1 ex2

//값 추가, 제거
exArray[3] = "ex3"                                    //Error
exArray.append("ex3")                                 //["ex0", "ex1", "ex2", "ex3"]
exArray.append(contentsOf: ["ex4", "ex5"])            //["ex0", "ex1", "ex2", "ex3", "ex4", "ex5"]
exArray.insert("ex6", at: 2)                          //["ex0", "ex1", "ex6", "ex2", "ex3", "ex4", "ex5"]
print(exArray.index(of: "ex6"))                       //2
exArray.remove(at: 2)                                 //["ex0", "ex1", "ex2", "ex3", "ex4", "ex5"]
exArray.removeLast()                                  //["ex0", "ex1", "ex2", "ex3", "ex4"] 

//값 출력
print(exArray.first)                                  //ex0
print(exArray.last)                                   //ex5
print(exArray[0 ... 5])                               //print 0 ~ 5st value
print(exArray.enumerated())                           //6

var exArray1 = Array(ex1: 1.2, ex2: 0.6)
print(exArray1.ex1)                                   //1.2
print(exArray1.ex2)                                   //0.6

exArray.reserveCapacity(500)                          //500개의 공간 할
exArray.capacity                                      //508




Sets(세트)


세트는 같은 자료형을 가진 각각의 값을 순서 없이 저장한다. 배열과 다른 점은 순서를 중요시하지 않으며 한 세트안에는 중복된 값이 없다는 것이다.

세트에 저장되기 위한 값들의 자료형은 해시가 가능해야한다. 스위프트의 기본 자료형은 모두 해시가 가능하다.

세트는 Set 키워드와 자료형의 조합으로 선언한다. 세트는 축약형이 없으므로 모두 써줘야한다.

선언할 때 타입 추론을 사용하면 배열로 저장되기 때문에 명시를 해줘야한다.

아래 그림과 같이 여러개의 세트를 가지고 집합연산과 관계연산을 할 수 있다.

순서가 중요하지 않은 배열이라면 세트로 저장하는게 좋다. 속도가 훨씬 빠르기 때문이다.

세트는 수학에서의 집합개념을 기반으로 만든 자료형으로 비교연산과 집합연산을 지원한다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//빈 세트 생성
var EmptySet = Set<String>()
var EmptySet: Set<String> = []

//세트 선언
var greeting: Set<String> = ["Hi", "Hola", "안녕"]
var farewell: Set<String> = ["Bye", "Adiós", "안녕"]

//세트 수정
greeting.insert("Ni hao")                           	    //["Hi", "Hola", "안녕", "Ni hao"]
greeting.remove("Ni hao")                            	    //["Hi", "Hola", "안녕"]
//greeting.removeAll()                               	    // empty

//세트의 집합연산
greeting.intersection(farewell)                      	    //["안녕"]
greeting.symmetricDifference(farewell)                      //["Hi", "Hola", "Bye", "Adiós"]
greeting.union(farewell)                             	    //["Hi", "Hola", "안녕", "Bye", "Adiós"]
greeting.subtracting(farewell)                       	    //["Hi", "Hola"]

//세트의 관계연산
var sayHelloGoodbye: Set<String> = greeting.union(farewell) //["Hi", "Hola", "안녕", "Bye", "Adiós"]

greeting.isSubset(of:sayHelloGoodbye)			    // isSubset(of:) == of~의 부분집합인지??
farewell.isStrictSubset(of:sayHelloGoodbye)		    // isStrictSubset(of:) == (of~의 부분집합 && 같은집합이 아닌지??)

sayHelloGoodbye.isSuperset(of:greeting)			    // isSuperset(of:) == of~의 전체집합인지??
sayHelloGoodbye.isStrictSuperset(of:farewell)		    // isStrictSuperset(of:) == (of~의 전체집합 && 같은집합이 아닌지??)

greeting.isDisjoint(with: farewell) 	       		    //isDisjoint(with:) == with~와 교집합이 없는지?




Dictionaries(딕셔너리)


딕셔너리는 순서없이 같은 자료형의 값들을 키에 맵핑시켜서 저장하는 자료형이다.

각각의 값은 고유의 키를 가지고 있고 이것은 딕셔너리에서 값들에 접근할 때 사용할 수 있다.

그렇기 때문에 값은 중복될 수 있지만 키는 중복될수 없다.

딕셔너리는 Dictionary<Key, Value> 형태로 사용할 수 있다.

1
2
3
4
5
6
7
8
9
10
// 빈 딕셔너리 생성
var emptyDic: [Int: String] = [:] // [:] == [Int: String]()

// 딕셔너리 선언
var exDic: [Int: String] = [1: "one", 2: "two", 3: "three"]

// 딕셔너리 수정
exDic[4] = "four" // 4 : four
exDic.updateValue("five", forKey: 4) // 4 : five
exDic.removeValue(forKey: 4)




컬렉션형 그림





Enumerations(열거형)


열거형 그 자체로 고유의 값을 가질 수 있다. Raw Value 혹은 Associated Value의 형태로 가진다.

열거형은 enum으로 선언할 수 있다.

rawValue Example

특정 타입으로 지정된 값

1
2
3
4
5
6
7
8
9
10
11
12
13
14
enum Planet {
	case mercury
	case venus
	case earth
}

enum CompassPoint: String {
	case north = "북", south = "남", east = "동", west = "서"
}

var whichPlanet: Planet = Planet.earth //same as .earth
let earthsOrder: Int = Planet.earth.rawValue // 3
let sunsetDirection: String = CompassPoint.west.rawValue // 서

Associated Values

1
2
3
4
5
6
7
enum Barcode {
	case upc(Int, Int, Int, Int)
	case qrCode(String)
}

var candy: Barcode = Barcode.upc(1, 2, 0, 6)
candy =  .qrCode("gift")

Iterating

열거형의 모든 케이스를 알고 싶을 때 사용한다.

1
2
3
4
5
6
7
enum Beverage: String, CaseIterable {
	case coffee = "커피", tea = "차", juice = "juice"
}

let beverageCount = Beverage.allCases.count // 3
let allCases: [Beverage] = Beverage.allCases
print(allCases)




형변환


메모리에 저장된 값은 변경하지 않고 일시적으로 하는 것을 Type Casting.

메모리의 값을 바꾸는 것은 Type Conversion이라고 한다.

자료형(값)의 형태로 한다.