Swift - 04

타입 별칭

사용자가 임의로 만든 데이터 타입이든 이미 존재하는 데이터 타입에 임의로 다른 이름을 부여할 수

있다.

typealias MyInt = Int
typealias MyDouble = Double

let age: MyInt = 24
let percentage: MyDouble = 25.5

 

튜플

  • 타입의 이름이 따로 지정되어 있지 않은, 프로그래머 마음대로 만드는 타입.
  • 지정된 데이터의 묶음
// String, Int, Double 타입을 갖는 튜플
var person: (String, Int, Double) = ("SDY", 100, 55.5)

// 인덱스를 통해서 값을 빼 올 수 있다.
print("이름: \(person.0), 나이: \(person.1), 몸무게: \(person.2)")

// 인덱스를 통해 값을 할당할 수 있다.
person.1 = 99
person.2 = 60.5

 

튜플 요소 이름 지정

// String, Int, Double 타입을 갖는 튜플
var person: (name: String, age: Int, weight: Double) = ("SDY", 100, 55.5)

// 요소 이름을 통해서 값을 빼 올 수 있다.
print("이름: \(person.name), 나이: \(person.age), 몸무게: \(person.weight)")

 

튜플 별칭 지정

typealias PersonTuple = (name: String, age: Int, height: Double)

let sdy: PersonTuple = ("sdy", 100, 55.5)

print("이름: \(sdy.name), 나이: \(sdy.age), 몸무게: \(sdy.weight)")

 

* 스위프트는 튜플 외에도 많은 수의 데이터를 묶어서 저장하고 관리할 수 있는 컬렉션 타입(배열, 딕셔너리, 세트)을 제공한다.

 

배열

  • 같은 타입의 데이터를 일렬로 나열한 후 순서대로 저장하는 형태의 컬렉션 타입
  • Array 키워드와 타입 이름의 조합으로 사용
  • 스위프트의 Array는 필요에 따라 자동으로 버퍼의 크기를 조절해주므로 요소의 삽입 및 삭제가 용이
// 대괄호를 사용하여 배열임을 표현
var names: Array<String> = ["sdy","kcs","kyh"]

// 위 선언과 정확히 동일한 표현, [String]은 Array<String>의 축약 표현
var names: [String] = ["sdy","kcs","kyh"]

var emptyArray: [Any] = [Any]()		// Any 데이터를 요소를 갖는 빈 배열을 생성
var emptyArray: [Any] = Array<Any>()	// 위 선언과 정확히 같은 동작을 하는 코드

// 배열의 타입을 정확히 명시해줬다면 []만으로도 빈 배열을 생성 가능
var emptyArray: [Any] = []
print(emptyArray.isEmpty)	// true
print(names.count)	// 3

// 요소 추가
names.append("elsa")
names.append(contentsOf: ["john", "max"])
names.insert("happy", at: 2)
names.insert(contentsOf: ["kjh","kms"], at: 3)

print(names.firstIndex(of: "sdy"))	// 0
print(names.firstIndex(of: "christal"))	// nil
print(names.first)	// sdy
print(names.last)	// max

let firstItem: String = names.removeFirst()
let lastItem: String = names.removeLast()
let indexZeroItem: String = names.remove(at: 0)

print(firstItem)	// sdy
print(lastItem)		// max
print(indexZeroItem)	// kcs
  • 빈 배열은 이니셜라이저 또는 리터널 문법을 통해 생성
  • 배열에 몇 개의 요소가 존재하는지 알고 싶으면 count 프로퍼티를 확인
  • 맨 처음과 맨 마지막 요소는 first와 last 프로퍼티를 통해 가져올 수 있다.
  • firstIndex(of:) 메서드를 사용하면 해당 인덱스를 알아낼 수 있다. (중복된 요소가 있다면 제일 먼저 발견된 요소의 인덱스를 반환)
  • 맨 뒤에 요소를 추가하고 싶다면 append(_:) 메서드를 사용
  • 중간에 요소를 삽입하고 싶다면 insert(_:at:) 메서드를 사용
  • 요소를 삭제하고 싶다면 remove(_:) 메서드를 사용하게 되는데, 메서드를 사용하면 해당 요소가 삭제된 후 반환

 

딕셔너리

  • 요소들이 순서 없이 키와 값의 쌍으로 구성되는 컬렉션 타입
  • 키는 같은 이름을 중복해서 사용할 수 없다.
  • 딕셔너리는 Dictionary라는 키워드와 키의 타입과 값의 타입 이름의 조합으로 쓴다.
  • 빈 딕셔너리는 이니셜라이저 또는 리터럴 문법을 통해 생성 가능
  • isEmpty 프로퍼티를 통해 비어있는 딕셔너리인지 확인 가능
  • count 프로퍼티로 딕셔너리의 요소 개수를 확인 가능
// typealias를 통해 조금 더 단순하게 표현 가능
typealias StringIntDictionary = [String: Int]

// 키는 String, 값은 Int 타입인 빈 딕셔너리를 생성
var numberForName: Dictionary<String, Int> = Dictionary<String, Int>()

// 위와 같은 표현, [String: Int]는 Dictionary<String, Int>의 축약 표현
var numberForName: [String: Int] = [String: Int]()

// 위 코드와 같은 동작
var numberForName: StringIntDictionary = StringIntDictionary()

// 딕셔너리의 키와 값을 정확히 명시했다면 [:]만으로도 빈 딕셔너리를 생성 가능
var numberForName: [String: Int] = [:]

// 초기값을 주어 생성
var numberForName: [String: Int] = ["sdy": 100, "chulsoo": 200, "jenny": 300]

numberForName["chulsoo"] = 150	// chulsoo 라는 키를 가진 요소의 값을 변경
print(numberForName["chulsoo"])	// 150

numberForName["max"] = 999
print(numberForName["max"])	// 999

// sdy 키에 해당하는 값을 삭제하고 출력
print(numberForName.removeValue(forKey: "sdy"))	// 100

// sdy 키에 해당하는 값이 없을 때 기본값(0)을 반환
print(numberForName["sdy", default: 0])	// 0

 

세트

  • 같은 타입의 데이터를 순서 없이 하나의 묶음으로 저장하는 형태의 컬렙션 타입
  • 세트 내의 값은 모두 유일한 값, 즉 중복된 값이 존재하지 않다.
  • 보통 순서가 중요하지 않거나 각 요소가 유일한 값이어야 하는 경우에 사용
  • 세트의 요소로 해시 가능한 값이 들어와야 한다.
  • Set 키워드와 타입 이름의 조합으로 쓴다.
  • 배열과 마찬가지로 대괄호로 값들을 묶어 세트 타입임을 표현
  • 빈 세트는 이니셜라이저 또는 리터럴 문법을 통해 생성
  • 세트에 요소틑 추가하고 싶다면 insert(_:) 메서드를 사용
  • 요소를 삭제하고 싶다면 remove(_:) 메서드를 사용
// 빈 세트 생성
var names: Set<String> = Set<String>()
var names: Set<String> = []

// Array와 마찬가지로 대괄호를 사용하기 때문에 타입 추론을 사용하면 Array로 타입이 지정된다.
var names: Set<String> = ["sdy","chulsoo","younghee","sdy"]

names.insert("jenny")
print(names.remove("chulsoo"))	// chulsoo
print(names.remove("john"))	// nil

 

열거형

  • 연관된 항목들을 묶어서 표현할 수 있는 타입
  • 프로그래머가 정의해준 항목 값 외에는 추가, 수정이 불가
  • 스위프트의 열거형은 각 열거형이 고유의 타입을 가진다.
  • 열거형 각 항목이 원시 값(Raw Value)이라는 형태로 (정수, 실수, 문자 타입의) 실제 값을 가질 수 있다.
  • 연관 값(Associated Values)을 사용하여 값의 묶음도 구현할 수 있다.

열거형의 선언

enum School {
    case primary
    case elementary
    case middle
    case high
    // 한 줄로 모두 표현 가능
    // case primary, elementary, middle, high
}

 

열거형 변수의 생성 및 값 변경

var highestEducationLevel: School = School.high

// 위 코드와 같은 표현
var highestEducationLevel: School = .high

highestEducationLevel = .middle

 

원시 값

  • 특정 타입으로 지정된 값을 가질 수 있다.
  • 열거형 이름 오른쪽에 타입을 명시
  • 원시 값을 사용하고 싶을 때 rawValue 프로퍼티 사용
enum School: String {
    case primary = "유치원"
    case elementary = "초등학교"
    case middle = "중학교"
    case high = "고등학교"
    case university = "대학교"
}

let educationLevel: School = School.university
print("저는 \(educationLevel)에 다니고 있습니다.")
// 저는 대학교에 다니고 있습니다.

 

연관 값

enum MainDish{
	case pasta(taste: String)
    case pizza(dough: String, topping: String)
    case chicken(withSauce: Bool)
    case rice
}

var dinner: MainDish = MainDish.pasta(taste: "크림")
dinner = .pizza(dough: "치즈크러스트", topping: "불고기")

 

응용

enum PastaTaste {
	case cream, tomato
}

enum PizzaDough {
	case cheeseCrust, thin, original
}

enum PizzaTopping {
	case pepperoni, cheese, bacon
}

enum MainDish{
	case pasta(taste: PastaTaste)
    case pizza(dough: PizzaDough, topping: PizzaTopping)
}

var dinner: MainDish = MainDish.pasta(taste: PastaTaste.tomato)
dinner = .pizza(dough: PizzaDough.original, topping: PizzaTopping.cheese)

 

항목 순회

열거형에 포함된 모든 케이스를 알아야 할 때 CaseIterable 프로토콜 사용

enum School: CaseIterable{	// 원시값이 있는 경우 예): String, CaseIterable
    case primary
    case elementary
    case middle
    case high
    case university
}

let allCases: [School] = School.allCases
print(allCases)
// [School.primary, School.elementary, School.middle, School.high, School.university]

 

순환 열거형

  • 열거형 항목의 연관 값이 열거형 자신의 값이고자 할 때 사용
  • 특정 항목에만 한정할 때 : case 키워드 앞에 indirect
  • 열거형 전체에 적용할 떄 : enum 키워드 앞에 indriect

ArithmeticExpression 열거형을 사용하여 (5 + 4) x 2 연산을 구현하는 예제

indirect enum ArithmeticExpression {
	case number(Int)
    case addition(ArithmeticExpreesion, ArithmeticExpreesion)
    case multiplication(ArithmeticExpreesion, ArithmeticExpreesion)
}

let five = ArithmeticExpreesion.number(5)
let four = ArithmeticExpreesion.number(4)
let sum = ArithmeticExpreesion.addition(five, four)
let final = ArithmeticExpreesion.multiplication(sum, ArithmeticExpreesion.number(2))

func evaluate(_ expression: ArithmeticExpreesion) -> Int {
	switch expression {
    case .number(let value):
    	return value
    case .addition(let left, let right):
    	return evaluate(left) + evaluate(right)
    case .multiplication(let left, let right):
    	return evaluate(left) * evaluate(right)
    }
}

let result: Int = evaluate(final)
print("(5 + 4) * 2 = \(result)")
// (5 + 4) * 2 = 18

* evaluate는 ArithmeticExpression 열거형의 계산을 도화주는 순환 함수

 

비교 가능한 열거형

  • Comparable 프로토콜을 준수하는 연관 값만 갖거나 연관 값이 없는 열거형은 Comparable 프로토콜을 채택하면 각 케이스를 비교할 수 있다.
  • 앞에 위치한 케이스가 더 작은 값

비교 가능한 열거형의 사용

enum Condition: Comparable {
	case terrible
    case bad
    case good
    case great
}

let myCondition: Condition = Condition.great
let yourCondition: Condition = Condition.bad

if myCondition >= yourCondition {
	print("제 상태가 더 좋아요")
} else {
	print("당신 상태가 더 좋아요")
}
// 제 상태가 더 좋아요

 

[출처 : Swift 프로그래밍 야곰]

 

 

'Language > Swift' 카테고리의 다른 글

Swift 네트워킹 방법  (0) 2022.07.11
Swift - 05  (0) 2022.02.08
Swift - 03  (0) 2022.01.26
Swift - 02  (0) 2022.01.11
Swift - 01  (0) 2022.01.11