Programming/Swift(iOS)
Swift Enum - 1
홍열
2021. 4. 1. 20:53
728x90
지금부터는 swift에서 사용하는 enum타입에 대한 공부를 해볼까 합니다.
swift에서의 enum의 쓰임새는 다양합니다.
c와는 쓰임새가 정말 많이 달라서 처음에는 어렵게 느껴집니다.
제가 보는 책에서 swift enum을 유용하게 사용할 수 있는 경우를 찾아봤습니다.
- 제한된 선택지를 주고 싶을때
- 정해진 값 이외에는 입력을 받고 싶지 않을때
- 예상된 입력값이 한정되어 있을 때
-> enum은 하나를 선택하면 다른 하나를 선택 못하기때문에 Error 처리에서도 자주 등장합니다.
Swift에서 자주 사용하는 Optional도 Enum으로 구현되어 잇습니다.
enum School {
case primary
case elementary
case middle
case high
case university
}
// 변수를 생성할때 타입을 명시해줬기 때문에 값할당시에 School을 생략 가능합니다.
//var highestEducationLevel:School = School.middle
var highestEducationLevel:School = .middle
기본적인 예제를 설명하기 보다는 실전에서 사용하는 방법들에 대해서 적어볼까 합니다.
enum은 상호 베타적입니다.
아래 예제에서 hasJoined과 hasLeft가 동시에 true로 설정될 수 있습니다.
struct Message {
let userId:Int
let contents:String?
let data:Date
let hasJoined:Bool
let hasLeft:Bool
}
let joinMessage = Message(userId: 1, contents: nil, data: Date(), hasJoined: true, hasLeft: false)
let textMessage = Message(userId: 1, contents: "Hello", data: Date(), hasJoined: false, hasLeft: false)
let leftMessage = Message(userId: 1, contents: nil, data: Date(), hasJoined: false, hasLeft: true)
//문제점: 잘못된 상태의 객체가 만들어질 수 있습니다.
//join과 left가 둘 다 true인 경우가 있다.
let wrongMessage = Message(userId: 1, contents: "Hi", data: Date(), hasJoined: true, hasLeft: true)
위 부분을 enum으로 변환해보겠습니다.
참고로 enum의 case에는 tuple이 들어갈 수 있습니다.
enum Message {
case text(userId:Int, content:String, date:Date)
case join(userId:Int, date:Date)
case leave(userId:Int, date:Date)
}
//타입 추론이 가능하므로 Message.join이 아니라 .join만 사용해도 된다.
let joinMessage:Message = .join(userId:1, date:Date())
let textMessage:Message = .text(userId:1, content:"Hello", date:Date())
let leaveMessage:Message = .leave(userId:1, date:Date())
// 넘겨진 enum값에 따라서 출력을 해주는 부분
func logMessage(message:Message) {
#if false
switch message {
case .text(userId: let userId, content: let contents, date:let date):
print(userId, contents, date)
break
case .join(userId:let userId, date: let date):
print(userId, date)
break
case .leave(userId:let userId, date:let date):
print(userId, date)
break
}
#endif
#if false
switch message {
case .text(let userId, let content, let date):
print(userId, content, date)
break
case .join(let userId, let date):
print(userId, date)
break
case .leave(let userId, let date):
print(userId, date)
break
}
#endif
#if false
switch message {
case let .text(userId, contents, date):
print(userId, contents, date)
break
case let .join(userId, date):
print(userId, date)
break
case let .leave(userId, date):
print(userId, date)
break
}
#endif
}
logMessage(message:joinMessage)
logMessage(message:leaveMessage)
logMessage(message:textMessage)
enum의 case로 test, join, leave을 나타낼 수 있어 확실하게 구분이 가능합니다.
logMessage함수를 보면 전달받은 message를 switch로 분기하면서 enum case에 대해서 처리를 합니다.
let에 대한 처리를 어디서 하느냐에 따라서 좀 더 축약형이 될 수가 있습니다.
그렇다면 단일 항목에 대한 처리는 어떻게 할까요?
아래와 같이 textMessage를 가져와서 case에 대한 단일 항목 처리를 하면 됩니다.
if case .text(userId:let userId, content:let contents, date:let date) = textMessage {
print(userId, contents, date)
}
if case .join(let userId, let date) = joinMessage {
print(userId, date)
}
if case let .leave(userId, date) = leaveMessage {
print(userId, date)
}