100 Days of SwiftUI - Day 10
DAY 10. Struct
여러 개의 작은 유형으로 하나의 유형을 만들 수 있음.
struct Album {
let title: String
let artist: String
let year: Int
func printSummary() {
print("\(title) (\(year)) by \(artist))
}
}
구조체를 정의한 후 값을 할당하는 등의 작업을 할 수 있음.
let endTheory = Album(title: "End Theory", artist: "Younha", year:2021)
let invu = Album(title: "INVU", artist: "TaeYeon", year: 2022)
print(endTheory.title)
print(invu.artist)
print(endTheory.printSummary())
print(invu.printSummary())
>>>
End Theory
TaeYeon
End Theory (2021) by Younha
INVU (2022) by TaeYeon
구조체가 let
으로 선언된 경우 mutating
함수를 호출할 수 없다.
구조체 용어
프로퍼티: 구조체의 변수와 상수
메서드: 구조체의 함수
인스턴스: 구조체로부터 변수나 상수를 만든 경우
구조체 인스턴스 생성 시 초기화
ex) Album(title: “INVU”, artist: “TaeYeon”, year: 2022)
내부에서는 init()
이라는 초기화 함수를 생성하고 전달된 인수들을 사용한다.
//인스턴스를 생성하는 두 가지 방법
var lee = Employee(name:"Lee Chan Hee", vacationRemaining: 10)
var park = Employee.init(name: "Park Chan Ho", vacationRemaining: 3)
Double도 구조체로 구현이 되어 있어, Int 값을 double로 변환하는 것이 가능해진다.
구조체에 기본값을 할당하는 것도 가능하다. 구조체 인스턴스 생성 시 기본값이 아닌 다른 값을 넣게 되면, 기본값은 사라지고 그 대신 새로운 값이 입력된다.
계산된 프로퍼티, 저장된 프로퍼티
struct Employee {
let name: String
var vacationRemaining: Int
}
var archer = Employee(name: "Sterling Archer", vacationRemaining: 14)
archer.vacationRemaining -= 5
print(archer.vacationRemaining)
archer.vacationRemaining -= 3
print(archer.vacationRemaining)
저장된 프로퍼티를 수정할 수 있지만, 이 경우 기존의 값이 수정되는 것이기 때문애 초기의 값을 잃어버릴 수 있다.
struct Employee {
let name: String
var vacationAllocated = 14
var vacationTaken = 0
//계산된 프로퍼티
var vacationRemaining: Int {
vacationAllocated - vacationTaken
}
}
값이 변경되는 경우 저장 프로퍼티를, 프로퍼티를 자주 읽지 않는 경우 계산 프로퍼티를 사용한다.
프로퍼티 옵저버
프로퍼티 옵저버는 프로퍼티의 값이 변경되는 경우 실행된다.
프로퍼티 관찰자를 정의하기 위해 didSet
, willSet
키워드를 사용한다. 각각 값이 설정된 이후, 설정되기 이전에 호출된다.
didSet
내에서 이전 값을 사용하기 위해 oldValue
키워드를 사용할 수 있다.
willSet
내에서는 newValue
키워드를 사용하여 새로운 값을 사용할 수 있다.
프로퍼티 옵저버는 값이 변경될 때 실행되기 때문에, 값이 변경될 때마다 실행할 함수들이 있는 경우 유용하게 사용된다. 주로 UI의 상태가 변경될 때 사용된다.
초기화 구문
모든 프로퍼티는 초기화 구문이 끝나면 값을 가지고 있어야 한다.
구조체 인스턴스 생성 시, 내부에서는 조용히 init()
이 실행되는 것을 알 수 있었음.
멤버별(memberwise) 초기화 구문: init()
을 작성하지 않으면 자동적으로 생성되는 초기화 구문.
모든 프로퍼티에 값을 넣을 수 있도록 함.
기본값을 가지는 프로퍼티는 생략할 수 있음.
init()
을 직접 작성하는 것도 가능하다. 단 매개변수와 프로퍼티의 이름을 구분하는 것이 필요하다.
struct Player {
let name: String
let number: Int
init(name:String, number:Int) {
self.name = name
self.number = number
}
}
func
키워드를 사용하지 않고 정의할 수 있으며,
초기화 구문 내에서 프로퍼티를 사용할 때는 self
키워드를 프로퍼티 앞에 붙여 사용한다.
모든 프로퍼티를 생성 시 입력으로 받을 필요 없다. 함수를 통해 랜덤값을 할당하는 방법도 가능.
중요한 것은 초기화 구문이 끝나면 모든 프로퍼티가 값을 가지고 있어야 한다는 것.
사용자화 초기화 구문을 작성한 경우, 멤버별 초기화 구문에는 더 이상 접근할 수 없다.
만약 두 초기화 구문에 모두 접근하고 싶다면, 확장에 초기화 구문을 작성한다. (Day13)