Building Spotify App in Swift 5 & UIKit - Part 24 - Remove from Playlist (Xcode 12, 2021, Swift 5)
LongTapGesture
→ 삭제 함수 호출@objc private func didLongPress(_ gesture: UILongPressGestureRecognizer) {
guard gesture.state == .began, isOwner == true else { return }
let touchPoint = gesture.location(in: collectionView)
guard let indexPath = collectionView.indexPathForItem(at: touchPoint) else { return }
let trackToDelete = tracks[indexPath.row]
let actionSheet = UIAlertController(title: "Delete",
message: "Would you like to delete \(trackToDelete.name) from this playlist?",
preferredStyle: .actionSheet)
actionSheet.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
actionSheet.addAction(UIAlertAction(title: "Remove", style: .destructive, handler: { [weak self] _ in
guard let self = self else { return }
APICaller.shared.removeTrackFromPlaylist(track: trackToDelete, playlist: self.playlist) { success in
if success {
DispatchQueue.main.async {
self.tracks.remove(at: indexPath.row)
self.viewModels.remove(at: indexPath.row)
self.collectionView.reloadData()
}
} else {
print("Failed to remove")
}
}
}))
present(actionSheet, animated: true, completion: nil)
}
LongTapGesture
)isOwner
플래그 비트 사영func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
let playlist = playlists[indexPath.row]
guard selectionHandler == nil else {
self.selectionHandler?(playlist)
self.dismiss(animated: true, completion: nil)
return
}
let vc = PlaylistViewController(playlist: playlist)
vc.navigationItem.largeTitleDisplayMode = .never
vc.isOwner = true
navigationController?.pushViewController(vc, animated: true)
}
LibraryPlaylistsViewController
의 테이블 뷰에서 특정 플레이리스트로 들어가기 전 isOwner
플래그 비트를 조정라이브러리가 아니라
SearchViewController
를 통해 유저가 만든 플레이리스트를 검색했을 경우에는 그 플레이리스트의isOwner
값을 조정할 수 없기 때문에 플레이리스트 자체의Owner
를 현재 유저의 프로퍼티와 비교해서 불리언 체크를 해야 할 것 같음
APICaller.shared.getCurrentUserProfile { [weak self] result in
guard let self = self else { return }
switch result {
case .success(let profile):
self.isOwner = profile.id == self.playlist.owner.id
case .failure(let error):
print(error.localizedDescription)
break
}
}
LibraryPlaylistsViewController
의 테이블 뷰 클릭을 통해 네비게이션을 띄우기 전 isOwner
를 로컬 상에서 조정하는 코드 삭제 후 리팩토링PlaylistViewContoller
내에서 스포티파이 API 직접 호출 → 현재 다루고 있는 플레이리스트의 Owner
아이디와 현재 유저의 아이디가 같은 지 직접적으로 확인 가능 public func removeTrackFromPlaylist(track: AudioTrack, playlist: Playlist, completionHandler: @escaping (Bool)->()) {
createRequest(with: URL(string: Constants.baseAPIURL + "/playlists/\(playlist.id)/tracks"), type: .DELETE) { request in
var request = request
let json:[String:Any] = [
"tracks" : [
[
"uri":"spotify:track:\(track.id)"
]
]
]
request.httpBody = try? JSONSerialization.data(withJSONObject: json, options: .fragmentsAllowed)
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
URLSession.shared.dataTask(with: request) { data, response, error in
guard
let data = data,
error == nil else {
completionHandler(false)
return
}
do {
let result = try JSONSerialization.jsonObject(with: data, options: .fragmentsAllowed)
print(result)
if let response = result as? [String:Any], response["snapshot_id"] as? String != nil {
completionHandler(true)
} else {
completionHandler(false)
}
} catch {
completionHandler(false)
}
}
.resume()
}
}
LongTapGesture
보다도 swipe to delete
가 보다 익숙한 UX를 제공하기 때문에 리팩토링할 경우 swipe to delete
할 수 있도록 사용하기 editStyle
에서는 곧바로 swipe to delete
기능을 사용할 수 있는데, 컬렉션 뷰의 경우 커스텀해야 하는 듯