안녕하세요. 미닛메이드 Minnit 입니다😌
오랜만이네요..ㅎㅎ
여러 코드들을 참고하다가 enum 옆에
CaseIterable 가 많이 눈에 들어오더라구요?
그래서 CaseIterable의 개념과 어느 경우에 사용될 수 있는지를 알아보도록 하겠습니다 !
CaseIterable 란 뭘까요?
Apple🍎의 공식 문서를 확인해보면
Protocol로 "모든 값들의 collection을 제공한다" 라고 하네요!
Swift에서는 Collection Type으로 3가지를 제공해주고 있는데
바로 Array, Set, Dictionary 가 있죠??
Collection을 제공한다 라는 말은
Collection Type처럼 사용할 수 있게 도와준다 라는 말로 들리네요!
더 자세히 말하면 CaseIterable를 선언 시 사용할 수 있는
allCases가 Collection Type으로 되어있기 때문이죠 ⭕️
static var allCases: Self.AllCases { get }
associatedtype AllCases : Collection = [Self] where Self == Self.AllCases.Element
그래서 이 CaseIterable을 enum에 사용하면
Collection Type에서 사용하는 다양한 메소드(ex. map, count 등)를 사용할 수 있게 됩니다
그래서 enum에 존재하는 모든 case들을 나열 혹은 반복하고 싶을 때 주로 사용하게 됩니다 😊
예시를 들어볼게요 💬
enum FontStyle: CaseIterable {
case title
case subtitle
case sectionTitle
case body
case comment
}
let enumCount = FontStyle.allCases.count
let enumCaseName = FontStyle.allCases.map { "\($0) 스타일" }.joined(separator: ", ")
// enumCount: 5
// enumCaseName: title 스타일, subtitle 스타일, sectionTitle 스타일, body 스타일, comment 스타일
이런 식으로 CaseIterable을 넣으면 생기는 allCases property를 이용하여
count로 case의 개수를 셀 수도 있고, map과 같은 고차 함수도 사용할 수 있네요
오호라.. 이거 잘 쓰면 편리하겠는데요 ?
CaseIterable를 어떻게 활용하면 좋을까 해서 조금 더 찾아봤습니다 !
enum TextType: CaseIterable {
case title
case subtitle
case sectionTitle
case body
case comment
}
var fonts = [TextType : UIFont]()
for type in TextType.allCases {
switch type {
case .title:
fonts[type] = .preferredFont(forTextStyle: .headline)
case .subtitle:
fonts[type] = .preferredFont(forTextStyle: .subheadline)
case .sectionTitle:
fonts[type] = .preferredFont(forTextStyle: .title2)
case .body:
fonts[type] = .preferredFont(forTextStyle: .body)
case .comment:
fonts[type] = .preferredFont(forTextStyle: .footnote)
}
}
enum의 case으로 Font 유형을 정의한 후 CaseIterable를 사용하는 경우인데요,
allCases를 이용해서 모든 케이스를 돌면서 특정 case마다 폰트 타입을 정의했습니다
그러면 ~~~
let nameLabel: UILabel = UILabel()
nameLabel.text = "이름표"
nameLabel.font = fonts[.title]
이렇게 label의 font에 활용을 할 수 있습니다 !
저는 UIFont Extension을 따로 만들어서 font를 설정하는 방식을 주로 사용했는데
이런 방법도 사용할 수 있겠네요 😊
그럼 모든 enum에 CaseIterable를 사용할 수 있을까요?
공식문서 하단을 보면
The compiler can automatically provide an implementation of the CaseIterable requirements for any enumeration without associated values or @available attributes on its cases. The synthesized allCases collection provides the cases in order of their declaration.
"컴파일러는 자동으로 연관 값이나 @available 속성이 없는 모든 열거에 대한
CaseIterable 요구 사항의 구현을 제공할 수 있다."
라는 말은 즉 @availble 속성이 있거나 연관 값(Associated Value)이 있다면
CaseIterable을 사용할 수 없다는 말이 되겠쥬 ?
이 말이 공식 문서에 2번이나 언급되어 있어서
조금 더 자세히 보고 갈게요 !
먼저 Associated Value 바로 연관 값입니다 !
연관 값은 열거형에 첨가된 추가 정보로
enum FontStyle {
case title(Int)
case subtitle(Int)
case sectionTitle
case body
case comment
}
case 중 title과 subtitle case는 (Int)의 연관 값을 가지고 있는 상태입니다 !
Raw Values와는 다른 개념인 거 아시죠?ㅎㅎ
정말 연관 값이나 @availble 속성이 있으면 CaseIterable를 사용할 수 없는 걸까요 ?
바로 테스트를 해봤습니다
"Type 'FontStyle' does not conform to protocol 'CaseIterable'
Do you want to add protocol stubs?"
라는 에러가 나오는 것을 볼 수 있습니다
( 못 믿어서 미안해요... )
연관 값이나 @availble 속성이 있는 enum에서 CaseIterable를 사용할 수 없으니 대체할 거냐
즉, allCases를 직접 정의할 것이냐를 물어보고 있네요 !
직접 구현해서 사용한다면 이렇게 연관 값이 있는 case는
직접 기본값을 넣어서 구현을 해주면 됩니다 !
enum FontStyle: CaseIterable {
static var allCases: [FontStyle] {
return [title(0), subtitle(0), sectionTitle, body, comment]
}
case title(Int)
case subtitle(Int)
case sectionTitle
case body
case comment
}
이렇게 CaseIterable의 개념과 사용을 알아보았습니다
오늘도 공식문서에 대한 신뢰감을 쌓고 가네요 !
혹시 틀린 점 있거나 더 궁금한 점이 있다면
댓글로 남겨주세요 ⭐️
오늘도 감사합니다 :)
[참고 링크]
'Develop > Swift' 카테고리의 다른 글
[Swift] WWDC22 Complications and widgets: Reloaded (1) | 2022.06.14 |
---|---|
[Swift] WWDC22 Enhance voice communication with Push to Talk (1) | 2022.06.12 |
[Swift/코드한줄] Print 문 프로퍼티 - separator, terminator (0) | 2022.05.06 |
[Swift/코드한줄] Timer.invalidate() (0) | 2022.04.08 |
[Swift/코드한줄] translatesAutoresizingMaskIntoConstraints = false (0) | 2022.01.16 |
Comment