🍫 notion으로 보기
*본 포스트는 애플의 'A Swift Tour'를 바탕으로 작성되었으며, 공부하며 기록용으로 작성한 포스트이기 때문에 정확하지 않은 정보가 있을 수 있습니다!
** notion으로 작성한 문서를 임시로 올려둔 포스트이기 때문에 사진 링크의 오류와 문서의 형식 등으로 인해 보시기에 불편함이 있을 수 있습니다. (사진이 안나오거나 코드를 보기 불편한 점 등은 빠른 시일 내에 수정하도록 하겠습니다!)
enum
열거형enumeration을 만들기 위해서 enum
을 사용한다. 클래스와 다른 이름이 붙여진 타입들과 같이, 열거체들은 그들과 함께 메소드를 만들 수 있다.
enum Rank: Int {
case ace = 1
case two, three, four, five, six, seven, eight, nine, ten
case jack, queen, king
func simpleDescription() -> String {
switch self {
case .ace:
return "ace"
case .jack:
return "jack"
case .queen:
return "queen"
case .king:
return "king"
default:
return String(self.rawValue)
}
}
}
let ace = Rank.ace
let aceRawValue = ace.rawValue
swift에서의 self
는 인스턴스의 특별한 속성property이다. 그 스스로의 인스턴스를 잡아놓는. 대부분의 self
는 생성자initializer 혹은 클래스의 메소드, 구조체 혹은 열거형에서 나타난다.
experiment
두개의 Rank 값의 rawValue를 비교하는 함수를 작성하라.
func compareRank(valA: Rank, valB: Rank) -> Bool {
return valA.rawValue == valB.rawValue
}
compareRank(valA: Rank.ace, valB: Rank.queen) // false
compareRank(valA: Rank.two, valB: Rank.two) // true
기본적으로 스위프트는 raw 값에 0에서 시작해 1씩 증가하도록 할당하고 있다. 그러나 이는 값을 명시적으로 지정하는 것을 통해 바꿀 수 있다. 위의 예시에서, ace는 명시적으로 1이라는 raw값을 받았고, 남은 raw 값들은 그 다음 순서대로 할당받는다. 그리고 String이나 열거체의 raw 타입으로써의 floating-point number도 사용 가능하다floating-point numbers as the raw type of an enumeration. rawValue
속성을 이용해 열거체 케이스의 raw 값에 접근할 수 있다.
init?(rawValue:)
raw 값으로부터 열거체의 인스턴스를 만들기 위해 init?(rawValue:)
생성자를 사용한다. init?(rawValue:)
는 열거체 케이스에 매치되는 raw 값
을 반환하거나, 만약 매칭되는 Rank가 없으면 nil
을 반환한다.
if let convertedRank = Rank(rawValue: 3) { // rawValue가 3인 값을 매칭 => "three"
// return String(self.rawValue) => convertedRank.rawValue => "3" (: String)
let threeDescription = convertedRank.simpleDescription()
}
⚠️ Initialization of immutable value 'threeDescription' was never used; consider replacing with assignment to '_' or removing it.
//위의 코드를 수정한 것 (threeDescrption을 사용하지 않아서)
if let convertedRank = Rank(rawValue: 3) {
_ = convertedRank.simpleDescripton()
}
열거체의 케이스 값들은 진짜actual 값들이며, 단지 그들의 다른 표현법이 아니다. 실제로, 케이스 내에서 의미 있는 raw값이 아니라면 제공할 필요가 없다.
enum ***Suit*** { // 열거체
case spades, hearts, diamonds, clubs
func simpleDescription() -> String {
switch self {
case .spades:
return "spades"
case .hearts:
return "hearts"
case .diamonds:
return "diamonds"
case .clubs:
return "clubs"
}
}
}
let hearts = Suit.hearts //hearts
let heartsDescription = hearts.simpleDescription() // "hearts"
hearts
의 두 가지의 방법
hearts
에 할당할 때, 명확한 타입이 명시되어 있지 않기 때문에 열거체 케이스 Suit.hearts
가 full name으로써 참조된다..heart
로부터 참조된다. 이는 self
의 값이 suit인 것을 알기 때문이다. 즉 만약 값의 타입을 이미 알고 있다면 언제든지 함축형을 쓸 수 있다.**experiment**
spades와 clubs에 "black"을 리턴하고, hearts와 diamonds에 "red"를 리턴하는 color() 메소드를 Suit에 추가하라.
enum Suit {
case hearts, clubs, spades, diamonds
func color() -> String {
switch self {
case .spades, .clubs:
return "black"
case .hearts, .diamonds:
return "red"
}
}
}
let heartsColor = Suit.hearts.color() //"red"
let spadesColor = Suit.spades.color() // "black"
associated values
같은 raw 값
을 가진다는 것을 의미한다.관련된 값associated
을 가지게 하는 것인데, 이들은 열거체 케이스의 각 인스턴스와 다를 수 있다. 당신은 관련된 값associated values을 열거체 케이스 인스턴스의 속성들properties을 저장하는 것으로 생각할 수 있다. 예를 들어, 서버로부터 일출과 일몰의 시간을 요청하는 케이스를 생각해보자. 서버는 요청받은 정보에 대해서 응답하거나, 무엇이 잘못된 것에 대해 응답한다.//일출과 일몰의 시간을 요청하는 서버
enum ServerResponse {
case result(String, String)
case failure(String)
}
let success = ServerResponse.result("6:00 am", "8:09 pm")
let failure = ServerResponse.failure("Out of cheese.")
//success이기 때문에 success문 출력
switch success {
case let .result(sunrise, sunset):
print("Sunrise is at \(sunrise) and sunset is at \(sunset).")
case let .failure(message):
print("Failure... \(message)")
}
❗️sunrisem, sunset 시간이 ServerResponse 값으로부터 추출되었다.
: switch case와 값이 매칭되었기 때문에
***case let
: 뒤따르는 연관된 값들을 단지 variable name으로 묶는 줄임말 ?
. 그러나 각각의 variable name 앞에 let을 적어줄 수도 있다. 출처**
**experiment**
ServerResponse와 switch문에 세번째 case값을 추가하라.
enum ServerResponse {
case missing(String)
}
let missing = ServerResponse.missing("Cannot find the data.")
switch success {
case let .missing(missingMessage):
print("Server can't find that information.")
}
**struct**
구조체structure를 만들기 위해 struct
를 사용한다. 구조체는 메소드와 생성자를 포함하여 클래스와 같은 많은 역할을 지원한다. 구조체와 클래스의 가장 중요한 다른 점은 구조체는 전달될 때 언제나 복사되는 반면 클래스는 참조로 전달된다.
struct Card {
var rank: Rank
var suit: Suit
func simpleDescription() -> String {
return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"
}
}
let threeOfSpades = Card(rank: .three, suit: .spades)
let threeOfSpadesDescription = threeOfSpades.simpleDescription()