Building Spotify App in Swift 5 & UIKit - Part 12 - Playlists (Xcode 12, 2021, Swift 5) - Build App
RecommendedTrackCollectionViewCell
의 레이아웃 및 셀 바인딩 기법 재활용하기UIActivityViewController
구현하기private func fetchData() {
APICaller.shared.getPlaylistDetails(for: playlist) { [weak self] result in
guard let self = self else { return }
switch result {
case .success(let model):
self.viewModels = model.tracks.items.compactMap({ item in
return RecommendedTrackCellViewModel(name: item.track?.name ?? "-", artistName: item.track?.artists.first?.name ?? "-", artworkURL: URL(string: item.track?.album?.images.first?.url ?? ""))
})
DispatchQueue.main.async {
self.collectionView.reloadData()
}
break
case .failure(let error):
print(error.localizedDescription)
break
}
}
}
...
let viewModel = viewModels[indexPath.row]
cell.configure(with: viewModel)
reloadData()
함수는 메인 큐에서 사용, 메모리 누수 방지를 위한 약한 참조 → 해당 데이터를 셀의 configure
을 통해 바인딩import UIKit
import SDWebImage
protocol PlaylistHeaderCollectionReusableViewDelegate: AnyObject {
func playlistHeaderCollectionReusableViewDidTapPlayAll(_ header: PlaylistHeaderCollectionReusableView)
}
final class PlaylistHeaderCollectionReusableView: UICollectionReusableView {
static let identifier = "PlaylistHeaderCollectionReusableView"
weak var delegate: PlaylistHeaderCollectionReusableViewDelegate?
private let nameLabel: UILabel = {
// label
}()
private let descriptionLabel: UILabel = {
// label
}()
private let ownerLabel: UILabel = {
// label
}()
private let imageView: UIImageView = {
// image
}()
private let playAllButton: UIButton = {
// button
}()
...
override func layoutSubviews() {
// layout
}
func configure(with viewModel: PlaylistHeaderViewViewModel) {
nameLabel.text = viewModel.name
descriptionLabel.text = viewModel.description
ownerLabel.text = viewModel.ownerName
imageView.sd_setImage(with: viewModel.artworkURL, completed: nil)
}
@objc private func didTapPlayAll() {
delegate?.playlistHeaderCollectionReusableViewDidTapPlayAll(self)
}
}
didTapPlayAll
은 델리게이트 디자인 패턴으로 구현하기 위한 프로토콜func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
guard kind == UICollectionView.elementKindSectionHeader,
let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: PlaylistHeaderCollectionReusableView.identifier, for: indexPath) as? PlaylistHeaderCollectionReusableView else {
return UICollectionReusableView()
}
let headerViewModel = PlaylistHeaderViewViewModel(name: playlist.name,
ownerName: playlist.owner.display_name,
description: playlist.description,
artworkURL: URL(string: playlist.images.first?.url ?? ""))
header.configure(with: headerViewModel)
header.delegate = self
return header
}
extension PlaylistViewController: PlaylistHeaderCollectionReusableViewDelegate {
func playlistHeaderCollectionReusableViewDidTapPlayAll(_ header: PlaylistHeaderCollectionReusableView) {
print("Playing All")
}
}
configure
사용 @objc private func didTapShare() {
guard let url = URL(string: playlist.external_urls["spotify"] ?? "") else {
return
}
let vc = UIActivityViewController(activityItems: [url],
applicationActivities: [])
vc.popoverPresentationController?.barButtonItem = navigationItem.rightBarButtonItem
present(vc, animated: true)
}
UIActivityViewController
를 통해 공유 이벤트 발생iOS의 공유 기능을 이렇게 구현 가능한지 처음 깨달았다!