본문 바로가기

iOS 프로그래밍/문법

[swift] 문법정리5 (배열, 딕셔너리,클래스와 구조체 열거형 비교)

스위프트 배열 초기화

- 배열은 동일한 타입의 값이지만 여러 타입이 혼합된 배열도 가능하다

- 배열의 타입은 타입 어노테이션(type annotation)을 사용하여 구체적으로 지정할 수도 있고, 타입 유추(type inference)를 이용하여 컴파일러가 식별하도록 할 수도 있다.

● 가변형 문자열 배열

var treeArray = ["Pine", "Oak", "Yew"]

var treeArray : [String] = ["Pine", "Oak", "Yew"]

● 불변형 문자열 배열

let treeArray1 = ["Pine", "Oak", "Yew"]

- 배열은 생성 시에 값을 할당할 필요는 없다.

var 변수 이름 = [타입]()

 

var nameArray = [String](repeating: "SW", count: 10)
print(nameArray)
//["SW", "SW", "SW", "SW", "SW", "SW", "SW", "SW", "SW", "SW"]

 

- 기존의 배열 두 개를 합하여 새로운 배열을 생성할 수도 있다.

 

var firstArray = ["Red", "Green", "Blue"] 
var secondArray = ["Indigo", "Violet"] 
var thirdArray = firstArray + secondArray
print(thirdArray)
//["Red", "Green", "Blue", "Indigo", "Violet"]

 

스위프트 배열로 작업하기

- isEmpty, count, append, insert, remove, removeLast 속성

 

 var treeArray = [String]()

 if treeArray.isEmpty { 
     print("비어 있습니다.")
     //비어 있습니다.
} 

 treeArray.append("Redwood") 
 treeArray += ["Redwood"] 
 treeArray += ["Redwood", "Maple", "Birch"] 

 print(treeArray) 
 //["Redwood", "Redwood", "Redwood", "Maple", "Birch"]

 treeArray.insert("Maple", at: 0) 
 print(treeArray) 
 //["Maple", "Redwood", "Redwood", "Redwood", "Maple", "Birch"]

 treeArray.remove(at:2) 
 print(treeArray) 
 //["Maple", "Redwood", "Redwood", "Maple", "Birch"]

 treeArray.removeLast() 
 print(treeArray)
 //["Maple", "Redwood", "Redwood", "Maple"]

 var itemCount = treeArray.count 
 print(itemCount) 
 //4

 

배열의 반복

var treeArray = ["Pine", "Oak", "Yew", "Maple", "Birch", "Myrtle"] 
for tree in treeArray { 
    print(tree) 
}

//Pine
//Oak
//Yew
//Maple
//Birch
//Myrtle

 

스위프트 딕셔너리

- 딕셔너리는 순서가 없는 단일 컬렉션에 여러 값을 담기 위해 특별히 설계된 데이터 타입

var 변수 이름: [키 타입: 값 타입] = [키1: 값1, 키2: 값2 .... ] 

 

- 배열처럼 밴 딕셔너리를 생성할 수도 있다.

var 변수 이름: [키 타입: 값 타입] = [키1: 값1, 키2: 값2 .... ] 

 

var bookDict: [String: String] = 

["100-432112" : "Wind in the Willows", 
"200-532874" : "Tale of Two Cities", 
"202-546549" : "Sense and Sensibility", 
"104-109834" : "Shutter Island"] 

print(bookDict.count)   //4

 

딕셔너리 항목 접근, 갱신

var bookDict: [String: String] = 

["100-432112" : "Wind in the Willows", 
"200-532874" : "Tale of Two Cities", 
"202-546549" : "Sense and Sensibility", 
"104-109834" : "Shutter Island"] 

print(bookDict) 

//["202-546549": "Sense and Sensibility", "104-109834": "Shutter Island", 
//"100-432112": "Wind in the Willows", "200-532874": "Tale of Two Cities"]

print(bookDict.count) //4 
print(bookDict["200-532874"]) 
// Optional("Tale of Two Cities")

bookDict["200-532874"] = "Sense and Sensibility" 

print(bookDict["200-532874"]) 
//Optional("Sense and Sensibility")

bookDict.updateValue("The Ruins", forKey: "200-532874") 

print(bookDict["200-532874"])
//Optional("The Ruins")

 

딕셔너리 항목 추가, 제거

var bookDict = [String: String]()

bookDict["300-898871"] = "The Overlook" 

print(bookDict) 

//["300-898871": "The Overlook"]

bookDict["300-898871"] = nil 

print(bookDict)

//[:]

 

딕셔너리 반복

var bookDict: [String: String] = 

["100-432112" : "Wind in the Willows", 
"200-532874" : "Tale of Two Cities"] 

for (bookid, title) in bookDict { 
    print("Book ID: \(bookid) Title: \(title)") 
}

//Book ID: 200-532874 Title: Tale of Two Cities
//Book ID: 100-432112 Title: Wind in the Willows

 

클래스와 구조체

● 공통점

- 값을 저장할 프로퍼티를 정의할 수 있다.

- 메서드를 정의할 수 있다.

- []를 사용해 첨자(subscript) 문법으로 내부의 값을 액세스할 수 있는 첨자를 정의할 수 있다.

- 초기 상태 설정을 위한 초기화 함수(initializer)를 정의할 수 있다.

- extends 기능을 제공한다.

- 프로토콜을 구현할 수 있다.

● 클래스만 추가되는 특징

- 상속이 가능하다

- 타입 캐스팅을 통해 실행 시점에 클래스 인스턴스의 타입을 해석하고 검사할 수 있다.

- 해제함수(deinit)를 사용해 사용한 자원을 반환할 수 있다.

- 참조 카운팅을 통해 한 클래스 인스턴스를 여러 곳에서 참조 할 수 있다.

클래스/구조체 정의하기

● 클래스 정의하기

class 이름 { ... }

 

● 구조체 정의하기

struct 이름 { ... }

 

- 타입 이름에는 Upper Camel Case를 사용 (대문자로 시작)

- 클래스/구조체 안의 프로퍼티나 메서드는 lower Camel Case를 사용한다.

 

struct Resolution { 
    var width = 0 
    var height = 0 
} 

class VideoMode { 
    var resolution = Resolution() 
    var interlaced = false 
    var frameRate = 0.0 
    var name: String? 
}

 

인스턴스 생성 및 프로퍼티 액세스

struct Resolution { 
    var width = 0 
    var height = 0 
} 

class VideoMode { 
    var resolution = Resolution() 
    var interlaced = false 
    var frameRate = 0.0 
    var name: String? 
}

 let someResolution = Resolution() 
 let someVideoMode = VideoMode() 
 //인스턴스 생성
 print("resolution=\(someResolution.width)") 
 someVideoMode.resolution.width = 1280 
 print("width=\(someVideoMode.resolution.width)")
 //프로퍼티 액세스 

 

구조체나 열거형은 값 타입

- 값 타입은 호출, 대입 등이 일어날 때 복사를 한다는 뜻이다

let hd = Resolution(width: 1920, height: 1080)​
var cinema​ = hd

- 위 예에서, cinemahd와 같은 인스턴스를 가리키는 것이 아니고, 내용을 복사한 새 인스턴스를 만들어 가리킨다.(따라서 cinema의 프로퍼티를 변경해도 hd에는 영향을 끼치지 못한다.)

클래스는 참조 타입

- 대입시 참조(주소라고 생각하면 됨)가 복사된다.

struct st {
    var width = 0
    var height = 0
}

class cl{
    var resolution = st() 
    var frameRate = 0.0
}

 

let s = st(width: 1920, height: 1080) 
//Memberwise Initializers for Structure Types 

let c = cl()  //클래스의 인스턴스 
c.resolution = s
c.frameRate = 25.0 
print(c.frameRate)  //25.0 

let cc = c
// cc는 c와 같은 인스턴스를 가리킨다 
cc.frameRate = 30.0 
// 따라서 c의 프로퍼티도 값이 30.0으로 바뀐다 
print(c.frameRate)  //30.0

 

call by value

call by reference

struct, enum

(Int, String, Array, Dictionary등 기본 자료형)
-> 모두 구조체로 만들어짐

클래스

 

구조체와 클래스를 활용한 값 타입, 참조 타입 비교 예제

class SomeClass {
    var someProperty: String = "before"
}

var someClassInstance: SomeClass = SomeClass()

func someFunc(_ className: SomeClass) {
    var changeClass: SomeClass = className
    changeClass.someProperty = "after"
}

someFunc(someClassInstance)

print(someClassInstance.someProperty)

//////////////////////////////////////////////////////

struct SomeStruct {
    var someProperty: String = "before"
}

var someStructInstance: SomeStruct = SomeStruct()

func someFunc(_ structName: SomeStruct) {
    var changeStruct: SomeStruct = structName
    changeStruct.someProperty = "after"
}

someFunc(someStructInstance)

print(someStructInstance.someProperty)

 

열거형(enum)

- 관련있는 데어터 들이 멤버로 구성되어 있는 자료형 객체

- 하나의 case문에 멤버들 나열하는 것도 가능

enum Planet {

case Mercury, Venus, Earth, Mars

}

- 문맥에서 타입의 추론이 가능한 시점 (등호 좌변의 변수 타입이 확정적일 때)에는 열거형명 생략 가능

enum Compass { 
    case North 
    case South 
    case East 
    case West 
} 

var direction : Compass 

direction = .South 

switch direction { 
    case .North: 
        print("북") 
    case .South: 
        print("남") 
    case .East: 
        print("동") 
    case .West: 
        print("서")
}
enum Weekday {
    case mon
    case tue
    case wed
    case thu, fri, sat, sun
}

var day: Weekday = Weekday.mon

func someFunc(_ enumName: Weekday) {
    var changeEnum: Weekday = enumName
    changeEnum =  .tue
}

print(day)