Building Spotify App in Swift 5 & UIKit - Part 9 (Xcode 12, 2021, Swift 5) - Build App
enum BrowseSectionType {
case newReleases(viewModels: [NewRelesesCellViewModel])
case featuredPlaylists(viewModels: [NewRelesesCellViewModel])
case recommendedTracks(viewModels: [NewRelesesCellViewModel])
}
...
collectionView.register(NewReleaseCollectionViewCell.self, forCellWithReuseIdentifier: NewReleaseCollectionViewCell.identifier)
collectionView.register(FeaturedPlaylistCollectionViewCell.self, forCellWithReuseIdentifier: FeaturedPlaylistCollectionViewCell.identifier)
collectionView.register(RecommendedTrackCollectionViewCell.self, forCellWithReuseIdentifier: RecommendedTrackCollectionViewCell.identifier)
private func fetchData() {
let group = DispatchGroup()
group.enter()
group.enter()
group.enter()
var newReleases: NewReleasesResponse?
var featuredPlaylist: FeaturedPlaylistsResponse?
var recommendations: RecommendationsResponse?
group.notify(queue: .main) {
guard
let newAlbums = newReleases?.albums.items,
let playlists = featuredPlaylist?.playlists.items,
let tracks = recommendations?.tracks
else {
fatalError("Models are nil")
}
self.configureModels(newAlbums: newAlbums, playlists: playlists, tracks: tracks)
}
}
private func configureModels(newAlbums: [Album], playlists: [Playlist], tracks: [AudioTrack]) {
sections.append(.newReleases(viewModels: newAlbums.compactMap({ album in
return NewRelesesCellViewModel(name: album.name, artworkURL: URL(string: album.images.first?.url ?? ""), numberOfTrack: album.total_tracks, artistName: album.artists.first?.name ?? "-")
})))
...
collectionView.reloadData()
}
configureModels
에서는 뷰 모델을 구성하는 데이터를 파라미터로 입력받아 셀을 그리는 뷰 모델을 받음func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let type = sections[indexPath.section]
switch type {
case .newReleases(viewModels: let viewModels):
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: NewReleaseCollectionViewCell.identifier, for: indexPath) as? NewReleaseCollectionViewCell else {
return UICollectionViewCell()
}
let viewModel = viewModels[indexPath.row]
cell.configure(with: viewModel)
cell.backgroundColor = .systemGreen
return cell
...
}
guard let
캐스팅 주의configure
함수 주의import UIKit
import SDWebImage
class NewReleaseCollectionViewCell: UICollectionViewCell {
static let identifier = "NewReleaseCollectionViewCell"
private let albumCoverImageView: UIImageView = {
// ImageView
}()
private let albumNameLabel: UILabel = {
// Label
}()
private let numberOfTracksLabel: UILabel = {
// Label
}()
private let artistNameLabel: UILabel = {
// Label
}()
...
override func layoutSubviews() {
// UI layout
}
override func prepareForReuse() {
super.prepareForReuse()
albumNameLabel.text = nil
artistNameLabel.text = nil
numberOfTracksLabel.text = nil
albumCoverImageView.image = nil
// Optional <-> Data Binding
}
func configure(with viewModel: NewRelesesCellViewModel) {
albumNameLabel.text = viewModel.name
artistNameLabel.text = viewModel.artistName
numberOfTracksLabel.text = "Tracks: \(viewModel.numberOfTrack)"
albumCoverImageView.sd_setImage(with: viewModel.artworkURL, completed: nil)
}
}
configure
되는 담당 데이터는 옵셔널 선언 → prepareForReuse
에서 해당 값을 널 값 할당x
, y
좌표를 통해 조정하고 있는데, 오토 레이아웃 관련 코드로 view?.translatesAutoresizingMaskIntoConstraints=false
를 주고 anchor
값을 조정해 커스텀했던 방법과는 색달랐다. 프레임 값을 미리 알고 있을 때 유용하게 사용할 수 있을 것 같다.