[enum - 열거형]
열거형은 처음에만 열거형 이름을 사용하고, 그 후부터는 이름은 생략하고 .부터 사용한다.
enum Compass {
case North
case South
case East
case West
}
//enum Compass {
// case North, case South, case East, case West
//} 이렇게도 가능하다.
//var x : Compass // Compass형 인스턴스 x
print(Compass.North) // North
var x = Compass.West
print(type(of:x)) // Compass
x = .East
print(x) // East
Swich ~ case 문으로 기능을 만들어 줄 수도 있다.
enum Compass {
case North
case South
case East
case West
}
var direction : Compass
direction = .North
switch direction { //switch의 비교값이 열거형 Compass
case .North: //direction이 .North이면 "북" 출력
print("북")
case .South:
print("남")
case .East:
print("동")
case .West:
print("서") //모든 열거형 case를 포함하면 default 없어도 됨
}
열거형 멤버에 Method도 넣을 수 있다.
enum Week {
case Mon, Tue, Wed, Thur, Fri, Sat, Sun
// 각 요일에 대해 "주중" 또는 "주말"을 출력하는 메서드
func printWeek() {
switch self {
case .Mon, .Tue, .Wed, .Thur, .Fri:
print("주중")
case .Sat, .Sun:
print("주말")
}
}
}
// 사용 예시
Week.Sun.printWeek() // "주말" 출력
열거형의 rawValue다. Int로 지정했을 때는 아래의 예시와 같이 출력된다.
enum Color: Int { // 원시값(rawValue) 지정
case red // red는 기본값 0을 가짐
case green = 2 // green은 2로 지정
case blue // blue는 기본값 3을 가짐 (green이 2이고 그 뒤는 자동으로 +1)
}
print(Color.red) // Color.red
print(Color.blue) // Color.blue
print(Color.red.rawValue) // 0
print(Color.blue.rawValue) // 3
String으로 지정했을 때, 값이 지정되지 않으면 case의 이름이 할당된다.
enum Week: String {
case Monday = "월"
case Tuesday = "화"
case Wednesday = "수"
case Thursday = "목"
case Friday = "금"
case Saturday // 원시값이 지정되지 않으면 케이스 이름 "Saturday"가 자동 할당됨
case Sunday // 원시값이 지정되지 않으면 케이스 이름 "Sunday"가 자동 할당됨
}
// 사용 예시
print(Week.Monday) // Week.Monday
print(Week.Monday.rawValue) // 월
print(Week.Sunday) // Week.Sunday
print(Week.Sunday.rawValue) // Sunday
연관 값을 갖는 enum. todayDate = Date.st~ 구문을 주석 처리하면 2025년 4월 30일이 출력된다.
enum Date {
case intDate(Int, Int, Int) // (Int, Int, Int)형 연관값을 갖는 intDate
case stringDate(String) // String형 연관값을 갖는 stringDate
}
var todayDate = Date.intDate(2025, 4, 30) // 연관값이 (2025, 4, 30)인 intDate
todayDate = Date.stringDate("2025년 5월 20일") // 연관값이 "2025년 5월 20일"인 stringDate로 변경
switch todayDate {
case .intDate(let year, let month, let day): // intDate일 경우
print("\(year)년 \(month)월 \(day)일")
case .stringDate(let date): // stringDate일 경우
print(date)
}
옵셔널은 연관 값을 갖는 enum이다.
let age: Int? = 30 // Optional(30)
switch age {
case .none: // nil인 경우
print("나이 정보가 없습니다.")
case .some(let a) where a < 20: // 값이 20 미만일 경우
print("\(a)살 미성년자입니다.")
case .some(let a) where a < 71: // 값이 20 이상 71 미만일 경우
print("\(a)살 성인입니다.")
default: // 그 외 (71 이상일 경우)
print("경로우대입니다.")
}
//출력
//30살 성인입니다.
//public enum Optional<Wrapped> {
// case none
// case some(Wrapped)
//} 이 소스는 iOS에서 이미 만들어 둔 소스기 때문에 작성하지 않아도 된다.
var x : Int? = 20 //.some(20)
var y : Int? = Optional.some(10)
var z : Int? = Optional.none
var x1 : Optional<Int> = 30
print(x, y, z, x1)
//Optional(20) Optional(10) nil Optional(30)
[struct - 구조체]
구조체는 Memberwise Initializer가 자동으로 만들어진다는 게 장점이다.
구조체에 초기값을 지정해 주는 경우다.
struct Resolution {
var width = 1024
var height = 768
}
let myComputer = Resolution()
print(myComputer.width) // 1024
초기값이 없는 경우, 보통은 아래처럼 init을 만들어 오류를 제거해 주어야 하는데
struct Resolution {
var width: Int
var height: Int
init(width:Int, height:Int){
self.width = width
self.height = height
}
}
let myComputer2 = Resolution(width: 1920, height: 1080)
print(myComputer2.width) // 1920
Swift는 자동으로 만들어 주기 때문에 없어도 잘 돌아간다!
struct Resolution {
var width: Int
var height: Int
}
let myComputer2 = Resolution(width: 1920, height: 1080)
print(myComputer2.width) // 1920
class 안에 struct를 넣을 수 있다.
struct Resolution {
var width = 1024
var height = 768
}
class VideoMode {
var resolution = Resolution()
var frameRate = 0.0
}
let myVideo = VideoMode()
print(myVideo.resolution.width
Swift의 기본 데이터 타입은 모두 구조체이다.
public struct Int
public struct Double
public struct String
public struct Array<Element>
.
.
.
클래스와 구조체는 무엇이 다른가?
비교 항목 | 구조체(struct) | 클래스(class) |
타입 | 값 타입. 복사됨 (Value Type) | 참조 타입. 참조됨 (Reference Type) |
상속 | ❌ 지원하지 않음 | ✅ 지원함 |
초기화 | 멤버와이즈 초기화자 제공 | 직접 init 정의 필요 |
구조체는 값 타입이기 때문에 lee에 kim을 대입하였을 때 복사가 된다. kim의 나이를 바꿔도 lee의 나이는 변하지 않는다.
struct Human {
var age : Int = 1
}
var kim = Human()
var lee = kim //값 타입
print(kim.age, lee.age) //1 1
lee.age = 20
print(kim.age, lee.age) //1 20
kim.age = 30
print(kim.age, lee.age) //30 20
하지만 클래스는 참조 타입이라 kim과 lee가 한 번에 바뀐다. struct에서 class로만 바뀌었는데 머리가 아파진다.
kim과 lee가 '같은 객체'를 참조하고 있기 때문에 lee가 바뀌어도 kim이 함께 바뀐다!
(lee = kim임에도 같은 객체를 가리키는 참조, 주소를 공유하기 때문에! kim은 lee에게 자신의 주소를 대입한 것이다.)
class Human {
var age : Int = 1
}
var kim = Human()
var lee = kim //값 타입
print(kim.age, lee.age) //1 1
lee.age = 20
print(kim.age, lee.age) //20 20
kim.age = 30
print(kim.age, lee.age) //30 30
그 다른 예제이다.
// 구조체 정의
struct Resolution {
var width = 0
var height = 0
}
// 클래스 정의
class VideoMode {
var resolution = Resolution()
var frameRate = 0
var name: String?
}
// 구조체는 값 타입 (Value Type)
var hd = Resolution(width: 1920, height: 1080)
var highDef = hd // 복사됨
print(hd.width, highDef.width) // 1920 1920
hd.width = 1024 // hd만 변경됨
print(hd.width, highDef.width) // 1024 1920
// 클래스는 참조 타입 (Reference Type)
var xMonitor = VideoMode()
xMonitor.resolution = hd
xMonitor.name = "LG"
xMonitor.frameRate = 30
print(xMonitor.frameRate) // 30
var yMonitor = xMonitor // 같은 객체를 참조
yMonitor.frameRate = 25
print(yMonitor.frameRate) // 25
print(xMonitor.frameRate) // 25 (같은 객체이므로 함께 변경됨)
[Class vs Struct]
덩치가 커지거나, 기능적으로 많은 것들이 필요한 경우 클래스를 사용한다.
하지만, 멀티 쓰레드 환경이라면 구조체가 더 안전하며 상속할 필요가 없는 경우에 사용한다.
그 예로 너비, 높이 표현하는 기하학적 모양 / 시작값, 증분, 길이 등의 순열 / 3차원 좌표 시스템의 각 좌표 등이 있다.
[extension]
클래스, 구조체, 열거형, 프로토콜에 새로운 기능을 추가할 때 사용한다.
extension은 기존 클래스에 메서드나 생성자, 계산 프로퍼티 등 기능을 추가할 때 사용한다.
앞서 말했듯이 Double 역시 iOS에서 구조체로 만들어 두었다. isZero도 그 안에 만들어져 있는 친구다.
여기에 내가 원하는 기능을 함수와 같이 추가할 수 있는데, 그것이 extension의 역할이다.
아래의 예시를 참고하면 되겠다.
extension Double {
var squared : Double {
return self * self
}
}
let myValue: Double = 3.0
print(myValue.squared) //과제
print(3.5.squared) //Double형 값에도 .으로 바로 사용 가능
print(myValue.isZero) //instance property
'iOS' 카테고리의 다른 글
Swift - Open API 기반 앱 만들기 (0) | 2025.05.07 |
---|---|
Swift - Optional Chaining, Throwing function, Generic, Array (0) | 2025.04.09 |
Swift - TableView (0) | 2025.04.02 |
Swift - 프로토콜 (0) | 2025.03.26 |
Swift의 주요 문법 복습 (0) | 2025.03.26 |