
struct객체struct 내부엔 func 와 var 등이 포함된다.값 타입 으로 데이터를 묶어서 저장하고, 복사 시 값 이 복사 된다.복사본 이 전달된다.mutating 키워드 필수let으로 선언한 구조체 인스턴스는 내부 프로퍼티를 변경 할 수 없음.불변성 을 유지하는 데이터 모델을 만들 때// 문법
// 구조체 정의
struct Person{
// 프로퍼티(속성)
var name: String
var age: Int
// 메서드
func introduce(){
print("안녕하세요 제 이름은 \(name)이고, \(age)살 입니다.")
}
}
// 구조체 인스턴스 생성
var person1 = Person(name: "홍길동", age: "25")
person1.introduce() // 출력 : 안녕하세요 제 이름은 홍길동이고 25살입니다.
// 메소드에서 프로퍼티 변경 시 (mutating)
struct Counter{
var count = 0
mutating func increment(){ // func increment는 오류
count += 1
}
}
var counter = Counter()
counter.increment()
print(counter.count) // 출력 : 1
// let으로 선언한 구조체 인스턴스의 경우
let person2 = Person(name: "고길동", age: "30") // 구조체 인스턴스 생성
person2.age = 31 // 오류 발생
class참조 타입(Reference Type) 이다. 클래스를 복사하면 원분과 복사본이 같은 객체를 참조한다.상속 할 수 있다.디이니셜라이저(Deinitializer) 를 제공한다.deinit 메서드를 제공한다.init 생성자를 정의해야한다.Identical 연산자 === 사용 가능// 클래스 정의
class Person {
var name: String
var age: Int
// 이니셜라이저 (생성자)
init(name: String, age: Int){
self.name = name
self.age = age
}
// 메서드
func introduce() {
print("안녕하세요 제 이름은 \(name)이고, \(age)살 입니다.")
}
}
// 클래스 인스턴스 생성
let person1 = Person(name: "지민", 25)
person1.introduce()
// 클래스를 복사하면 원문과 복사본이 같은 객체를 공유한다.
let person2 = person1
person2.name = "민지"
print(person1.name) // 출력 : 민지
// Identical 연산자 (===)
let person3 = person1
print(person1 === person3) // 출력 : true (같은 객체를 참조한다.
class Student: Person {
var studentID: String
init(name: String, age: Int, studentID: String) {
self.studentID = studentID
super.init(name: name, age: age)
}
override func introduce() {
print("저는 학생 \(name)이고, \(age)살이며 학번은 \(studentID)입니다.")
}
}
let student = Student(name: "유나", age: 20, studentID: "S1234")
student.introduce()
// 출력: 저는 학생 유나이고, 20살이며 학번은 S1234입니다.
deinitclass File {
var filename: String
init(filename: String) {
self.filename = filename
print("\(filename) 파일이 생성되었습니다.")
}
deinit {
print("\(filename) 파일이 삭제되었습니다.")
}
}
var file: File? = File(filename: "test.txt")
file = nil // 파일 삭제 시 deinit 호출
// 출력: test.txt 파일이 삭제되었습니다.
값 타입 으로 인스턴스가 복사될 때 값이 복사된다.참조 타입 으로 인스턴스가 복사될 때 참조 가 복사된다.구조체는 값 타입이기 때문에 원본 구조체를 복사해도 다른 변수에 영향을 주지 않는다.
struct Person{
var name: String
}
var person1 = Person(name: "Alice")
var person2 = person1 // person1을 2에 복사
person2.name = "Bob" // 원본 구조체에 영향가지 않음. 따라서 person2만 변경된다.
// 실제 결과
print(person1.name) // 출력 : "Alice"
print(person2.name) // 출력 : "Bob"
// 즉, person1과 person2은 "서로 다른 복사본"
참조가 복사된다. → 즉, 같은 인스턴스를 여러 변수에서 참조하게 되어, 한 곳에서 변경하면 다른 곳에도 영향을 끼친다.class Person{
var name: String
init(name: String){
self.name = name
}
}
var person1 = Person(name: "Alice")
var person2 = person1 // person2에 person1 참조 전달
person2.name = "Bob" // person1과 person2 모두 데이터가 변경됨.
print(person1.name) // 출력 : "Bob"
print(person2.name) // 출력 : "Bob"
// 즉, person1과 person2는 같은 객체를 참조하고 있기에 하나를 변경하면 다른 하나도 변경된다.
@ObservedObject → 뷰가 클래스 인스턴스를 구독해 데이터 변화를 감지.@Published → 클래스 속성에 붙여, 값이 바뀔 때 SwiftUI가 자동으로 화면 업데이트.ObservableObject 프로토콜을 채택해야 @Published가 작동.💡 한 줄 정리:
@ObservedObject와 @Published는 클래스 전용. 값 변경 → 화면 자동 업데이트!
import SwiftUI
struct Diff: View {
// 구조체
let myCar = Car(name: "리어카", owner: "라이오")
// 클래스
@ObservedObject var myKar = Kar(name: "리어카2", owner: "라이오2")
var body: some View {
VStack{
Text("\(myKar.name)의 주인은 \(myKar.owner)입니다.")
Button{
let broCar = myKar
broCar.name = "동생차"
broCar.owner = "동생"
myKar.sayHi()
} label : {
Text("출발")
}
}
}
}
struct Car{
let name: String
let owner: String
func sayHi(){
print("hi \(owner)")
}
}
class Kar: ObservableObject{
@Published var name: String
var owner: String
init(name: String, owner: String){
self.name = name
self.owner = owner
}
func sayHi(){
print("hi \(owner)2")
}
}
#Preview {
Diff()
}
열거형(Enumeration, enum) : 관련된 값들의 그룹을 한데 묶어 표현하는 데이터 타입열거형이름.값 형태로 접근하지만 같은 타입 내에서 사용할 때는 .값 으로 축약이 가능하다.// 기본 열거형 선언
enum CompassPoint {
case north
case south
case east
case west
}
// 방법 1
var direction = CompassPoint.north
direction = .east // 축약형 사용 가능
print(direction) // east
// 방법 2
var dirction: CompassPoint = .north
print(dicetion) // north
// 즉, direction에는 4가지의 변수만 들어갈 수 있도록 하고싶다.
enum Weekday: String{
case monday = "Mon"
case tuesday = "Tue"
case wednesday = "Wed"
}
print(Weekday.monday.rawValue) // "Mon"
// 실제 Swift UI
import SwiftUI
struct Choice: View {
var direction: Direction = .north
var member: String = "대현"
var body: some View {
Text("방향은 \(direction.rawValue)쪽 입니다.")
// 출력 : 방향은 북쪽 입니다.
}
}
enum Direction: String {
case north = "북"
case west
case east
case south
}
case 이름을 그대로 원시 값으로 사용할 수 있다.enum Number: Int {
case one = 1
case two
case three
}
print(Number.two.rawValue)
enum MediaType {
case audio(String)
case video(String, Int)
}
let song = MediaType.audio("Pop")
let movie = MediaType.video("Action", 120)
switch movie {
case .audio(let genre):
print("Audio Genre: \(genre)")
case .video(let genre, let duration):
print("Video Genre: \(genre), Duration : \(duration) min")
}
// Video Genre: Action, Duration: 120 min
enum Beverage: String{
case coffee, tea, jucie
var description: String{
switch self {
case .coffee: return "뜨겁거나 차가운"
case .tea: return "얼그레이나 복숭아"
case .juice: return "스무디나 에이드"
}
}
}
let drink = Beverage.coffee
print(dring.description) // 뜨겁거나 차가운
옵셔널 타입 , 예외 처리 , 상태 관리 등 매우 자주 사용된다.enum NetworkError: Error{
case badURL
case timeout
case noInternet
}
Switch 는 하나의 값에 따라 여러 경우(case) 중 실행할 코드를 결정하는 조건문if-else 보다 가독성이 뛰어나고 복잡한 조건 처리에 적합하다.switch 는 강력하고 안전한 패턴 매칭을 지원한다.enum 의 모든 케이스가 나오지 않으면 오류 발생 → swift의 switch는 각 case 실행 후 자동으로 종료되기 때문에 break 가 필요 없다. → 단순 값 비교 외에 range, where 절 등 다양한 조건 추가 가능 → default 를 반드시 사용해야 한다. (단, 모든 enum 케이스를 처리하면 필요 없다.)// switch 문법 구조
switch 값 {
case 조건1:
code
case 조건2:
code
default:
위 조건에 모두 해당되지 않을 때
}
// 예시
import SwiftUI
struct Diff: View {
@State var myDirection: Direction = .south
var body: some View {
switch myDirection{
case .north:
Text("북쪽은 추워요")
case .west:
Text("서쪽은 석양이 예뻐요")
case .east:
Text("동쪽은 해보기 좋아요")
case .south:
Text("남쪽은 놀기 좋아요")
}
Button{
myDirection = .east
}label:{
Text("돌리기")
}
}
}
enum Direction: String{
case north = "북"
case west = "서"
case east = "동"
case south = "남"
}