[UIKit] Spotify Clone: Search UI 2

Junyoung Park·2022년 9월 7일
0

UIKit

목록 보기
15/142
post-thumbnail
post-custom-banner

Building Spotify App in Swift 5 & UIKit - Part 15 - Categories (Xcode 12, 2021, Swift 5)

Spotify Clone: Search UI 2

구현 목표

  • 장르 카테고리 셀 구현
  • 장르별 플레이리스트 뷰 컨트롤러 재활용

구현 태스크

  1. 장르별 디테일 플레이리스트 API 데이터 패치
  2. 플레이리스트 컬렉션 뷰 구성
  3. 플레이리스트 컬렉션 뷰 클릭을 통한 플레이리스트 디테일 뷰 (플레이리스트 뷰 컨트롤러) 재활용

핵심 코드

public func getCategoryPlaylists(category: Category,completionHandler: @escaping((Result<[Playlist], Error>)->())) {
        createRequest(with: URL(string: Constants.baseAPIURL + "/browse/categories/\(category.id)/playlists?limit=50"), type: .GET) { request in
            URLSession.shared.dataTask(with: request) { data, response, error in
                guard
                    let data = data,
                    error == nil else {
                    completionHandler(.failure(APIError.failedToGetData))
                    return
                }
                do {
                    let result = try JSONDecoder().decode(CategoryPlaylistsResponse.self, from: data)
                    let playlists = result.playlists.items
                    completionHandler(.success(playlists))
                } catch {
                    completionHandler(.failure(error))
                }
            }
            .resume()
        }
    }
  • 선택된 카테고리 정보를 바탕으로 해당 플레이리스트 목록을 패치하는 API 함수
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: FeaturedPlaylistCollectionViewCell.identifier, for: indexPath) as? FeaturedPlaylistCollectionViewCell else {
            return UICollectionViewCell()
        }
        let playlist = playlists[indexPath.row]
        let viewModel = FeaturedPlaylistCellViewModel(name: playlist.name, artworkURL: URL(string: playlist.images.first?.url ?? ""), creatorName: playlist.owner.display_name)
        cell.configure(with: viewModel)
        return cell
    }
    
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        collectionView.deselectItem(at: indexPath, animated: true)
        let vc = PlaylistViewController(playlist: playlists[indexPath.row])
        vc.navigationItem.largeTitleDisplayMode = .never
        navigationController?.pushViewController(vc, animated: true)
    }
  • 해당 카테고리 별로 패치한 플레이리스트를 컬렉션 뷰로 구현
  • 뷰 모델을 통해 해당 셀을 바인딩
  • 클릭 시 해당 플레이리스트 뷰로 네비게이션 이동(PlaylisyViewController 재활용)

구현 화면

뷰 컨트롤러 간의 재활용, 데이터 바인딩은 이전과 매우 동일한 로직이다. 어떻게 컬렉션 뷰의 배치를 짜고 엮을지가 가장 큰 차이점이랄까.

  • 왜인지는 모르겠지만 스포티파이가 제공하는 track JSON 모델의 특정 변수 하나가 어제까지의 타입 정보와 달라지는 바람에 JSON 디코딩이 계속 안 되는 일이 일어났다.
  • 결국 코딩 키 값 에러를 찍어주는 디버깅을 돌린 뒤에야 결국 (홈페이지에는 널 값이 가능한지 표시되어 있지 않은) available_markets 변수가 [String] 타입이 아니라 [String]?이어야 함을 알 수 있었다.
  • 타입 하나의 문제로 잘 굴러가던 API 패치가 안 되다니... 정말 사소한 데에서 주의를 기울이자. 그렇지 못하다면, 디버깅 프린트 문을 계속해서 찍어봐야 한다는 사실을 다시 한 번 깨달았다.
profile
JUST DO IT
post-custom-banner

0개의 댓글