각 카테고리에 대한 contentId를 효율적으로 관리하기 위해서 enum을 사용하면 좋습니다. enum을 사용하면 각 카테고리에 해당하는 contentId를 쉽게 정의하고 관리할 수 있습니다.
여기서 enum을 정의하고, switch문을 활용하여 contentId를 매핑한 후 NetworkManager의 메서드에서 해당 contentId를 사용하여 데이터를 요청할 수 있습니다.
1. ContentCategory Enum 정의
먼저, 각 카테고리에 대응하는 contentId를 enum으로 정의합니다.
enum ContentCategory: String {
case attractions = "12"
case facilities = "14"
case events = "15"
case course = "25"
case leisureActivity = "28"
var contentId: String {
return self.rawValue
}
}
여기서 ContentCategory의 rawValue로 contentId를 설정했습니다. 이제 각 카테고리별로 contentId를 쉽게 얻을 수 있습니다.
2. didSelectItemAt 메서드 수정
didSelectItemAt 메서드에서 ContentCategory를 사용하여 각 카테고리 선택 시에 해당하는 contentId를 쉽게 가져올 수 있습니다.
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if collectionView == categoryCollectionView.getcategoryCollectionView() {
selectedIndex = indexPath.item
collectionView.reloadData() // 선택 상태 업데이트
var selectedCategory: ContentCategory?
switch selectedIndex {
case 0:
selectedCategory = .attractions
case 1:
selectedCategory = .facilities
case 2:
selectedCategory = .events
case 3:
selectedCategory = .course
case 4:
selectedCategory = .leisureActivity
default:
break
}
if let category = selectedCategory {
NetworkManager.shared.getAttractionData(contentId: category.contentId) { result in
// 데이터를 받아온 후 UI 업데이트 등을 처리
switch result {
case .success(let items):
// items를 사용하여 UI 업데이트 처리
print(items)
case .failure(let error):
// 에러 처리
print(error.localizedDescription)
}
}
}
} else if collectionView == hotplacesCollectionView.getHotPlacesCollectionView() {
// HotPlaces 컬렉션 뷰 아이템 선택 시 처리
print("Selected hot place at index \(indexPath.item)")
}
}
3. NetworkManager 메서드 수정
NetworkManager의 getAttractionData 메서드는 그대로 유지하되, contentId를 enum에서 받아온 값으로 전달할 수 있게 구성합니다.
class NetworkManager {
static let shared = NetworkManager()
func getAttractionData(contentId: String, completion: @escaping (Result<[Item], Error>) -> Void) {
guard let url = URL(string: "https://apis.data.go.kr/B551011/KorService1/searchKeyword1?serviceKey=개인키&numOfRows=1000000&pageNo=1&MobileOS=ETC&MobileApp=AppTest&_type=json&listYN=Y&arrange=A&keyword=%EA%B0%95%EC%9B%90&contentTypeId=\(contentId)") else { return }
let task = URLSession.shared.dataTask(with: URLRequest(url: url)) { data, _, error in
guard let data = data , error == nil else {
completion(.failure(error!))
return
}
do {
let results = try JSONDecoder().decode(AttractionResponse.self, from: data)
completion(.success(results.response.body.items.item))
} catch {
completion(.failure(error))
}
}
task.resume()
}
}
⭐️ enum ContentCategory에서 var contentId를 정의한 이유?
enum ContentCategory: String {
case attractions = "12"
case facilities = "14"
case events = "15"
case course = "25"
case leisureActivity = "28"
var contentId: String {
return self.rawValue
}
}
contentId를 사용하는 이유
- 가독성 향상:
- contentId라는 이름은 해당 프로퍼티가 무엇을 나타내는지 명확하게 전달합니다. 반면, rawValue는 enum의 기본 제공 프로퍼티로, 어떤 값인지 즉시 이해하기 어려울 수 있습니다.
- 예를 들어, category.contentId는 그 자체로 "카테고리의 콘텐츠 ID"라는 의미를 분명히 전달하지만, category.rawValue는 단순히 "원시 값"이라는 의미로 해석될 수 있습니다.
- 의도 명확화:
- contentId를 통해 이 값이 콘텐츠를 식별하는 ID임을 명확히 나타낼 수 있습니다. 이는 코드의 의도를 분명히 하고, 다른 개발자들이 코드를 이해하기 쉽게 만듭니다.
- 유지보수 용이성:
- 만약 나중에 contentId를 계산 방식이나 다른 값으로 변경해야 할 경우, contentId 프로퍼티 내부에서만 변경하면 되므로 코드 전체를 수정할 필요가 없습니다.
- 예를 들어, 현재는 단순히 rawValue를 반환하지만, 추후 로직이 추가될 경우에도 contentId 프로퍼티 내에서만 수정하면 됩니다.
⭐️ selectedCategory에는 원시값을 넣어야하니까 에를 들면 .events.contentId 이렇게 적어야하는거 아냐?
selectedCategory에 ContentCategory의 원시값(rawValue)을 사용하려면, selectedCategory에 직접 ContentCategory 열거형의 인스턴스를 할당하는 대신, 그 원시값을 contentId 프로퍼티를 통해 설정하는 것이 맞습니다.
수정된 코드
var selectedCategory: String?
switch selectedIndex {
case 0:
selectedCategory = ContentCategory.attractions.contentId
case 1:
selectedCategory = ContentCategory.facilities.contentId
case 2:
selectedCategory = ContentCategory.events.contentId
case 3:
selectedCategory = ContentCategory.course.contentId
case 4:
selectedCategory = ContentCategory.leisureActivity.contentId
default:
break
}
설명
- selectedCategory 변수는 String? 타입으로 선언되었습니다. 이 변수에 ContentCategory의 원시값(contentId)을 할당하기 위해서는 selectedCategory = .events.contentId처럼 contentId 프로퍼티를 통해 접근해야 합니다.
- ContentCategory의 각 경우에 대해 .attractions.contentId, .facilities.contentId 등을 사용함으로써 해당 카테고리의 ID를 selectedCategory 변수에 할당할 수 있습니다.
대안: ContentCategory? 타입 사용
만약 selectedCategory를 String이 아닌 ContentCategory? 타입으로 선언하고, 이후에 contentId를 사용할 계획이라면 아래처럼 할 수 있습니다:
var selectedCategory: ContentCategory?
switch selectedIndex {
case 0:
selectedCategory = .attractions
case 1:
selectedCategory = .facilities
case 2:
selectedCategory = .events
case 3:
selectedCategory = .course
case 4:
selectedCategory = .leisureActivity
default:
break
}
// 이후 필요할 때
if let category = selectedCategory {
let contentId = category.contentId
// contentId를 사용해 네트워크 요청을 수행하는 등의 작업
}
이 접근 방식에서는 selectedCategory를 ContentCategory 타입으로 유지하면서, 필요할 때 contentId를 얻어 사용할 수 있습니다. 이 방법은 타입 안전성을 유지하면서도 각 카테고리를 쉽게 구분할 수 있게 합니다.
'Swift' 카테고리의 다른 글
외부 API를 받는 데이터 함수의 데이터 타입 관리 (0) | 2024.09.06 |
---|---|
데이터 모델 이름을 바꿔야 한다면? (0) | 2024.09.06 |
헷갈리기 쉬운 델리게이트 패턴으로 컬렉션 셀의 데이터 전달하기 (0) | 2024.08.28 |
콜백 함수는 언제 쓰이나요? (0) | 2024.08.23 |
Swift에서 Any와 AnyObject의 차이점은 무엇인가요? (0) | 2024.08.23 |