[UIKit] Spotify Clone: Player 1

Junyoung Park·2022년 9월 10일
0

UIKit

목록 보기
18/142
post-thumbnail

Building Spotify App in Swift 5 & UIKit - Part 18 - Play Music (Xcode 12, 2021, Swift 5)

Spotify Clone: Player 1

구현 목표

  • 음반 선택 → 관련 뷰 모달 뷰로 띄우기

구현 태스크

  1. 음반 데이터 및 현재 뷰 컨트롤러를 파라미터 → 음원 재생 담당 플레이 뷰 모달로 띄우기
  2. 음원 재생 뷰 델리게이트 → 현재 뷰 컨트롤러 통해 앞/뒤/정지 버튼 함수 구현

핵심 코드

static func startPlayback(from viewController: UIViewController, track: AudioTrack) {
        let vc = PlayerViewController()
        vc.title = track.name
        viewController.present(UINavigationController(rootViewController: vc), animated: true, completion: nil)
    }
 func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        let section = sections[indexPath.section]
        switch section {
        ...
        case .recommendedTracks(viewModels: let viewModels):
            let track = tracks[indexPath.row]
            PlaybackPresenter.startPlayback(from: self, track: track)
        }
    }
  • 오디오 트랙 해당 UI 셀 클릭 시 PlaybackPresenter를 통해 현재 뷰 컨트롤러 및 트랙 데이터를 넘기기
import UIKit

class PlayerViewController: UIViewController {
    private let imageView: UIImageView = {
        // Track Cover View
    }()
    private let controlsView = PlayerControlsView()
    ...
}

extension PlayerViewController: PlayerControlsViewDelegate {
    // delegate functions to use playerControls
    func playerControlsViewDidTapPlayPauseButton(_ playerControllsView: PlayerControlsView) {
    }
    
    func playerControlsViewDidTapForwardButton(_ playerControllsView: PlayerControlsView) {
    }
    
    func playerControlsViewDidTapBackwardButton(_ playerControllsView: PlayerControlsView) {
    }
}
  • 플레이어 뷰는 해당 트랙의 커버 뷰 + 음원 재생 가능한 뷰로 구성
  • 음원 재생 가능한 뷰는 PlayerControlsView를 통해 별도로 구성
  • 버튼 클릭 함수를 PlayerViewController에서 별도로 사용하기 위한 델리게이트 패턴
import UIKit

protocol PlayerControlsViewDelegate: AnyObject {
    func playerControlsViewDidTapPlayPauseButton(_ playerControllsView: PlayerControlsView)
    func playerControlsViewDidTapForwardButton(_ playerControllsView: PlayerControlsView)
    func playerControlsViewDidTapBackwardButton(_ playerControllsView: PlayerControlsView)
}

final class PlayerControlsView: UIView {
    weak var delegate: PlayerControlsViewDelegate?
    
    private let volumeSlider: UISlider = {
        // volumeSlider
    }()
    
    private let titleLabel: UILabel = {
        // titleLabel
    }()
    
    private let subtitleLabel: UILabel = {
        // subtitleLabel
    }()
    
    private let backButton: UIButton = {
        // button
    }()
    
    private let nextButton: UIButton = {
        ...
    }()
    
    private let playPauseButton: UIButton = {
        ...
    }()
    // ... set UI layout
    
    private func setPlayerControlsViewUI() {
        ...
        backButton.addTarget(self, action: #selector(didTapBack), for: .touchUpInside)
        playPauseButton.addTarget(self, action: #selector(didTapPause), for: .touchUpInside)
        nextButton.addTarget(self, action: #selector(didTapNext), for: .touchUpInside)
    }
    
    @objc private func didTapBack() {
        
    }
    
    @objc private func didTapNext() {
        
    }
    
    @objc private func didTapPause() {
        
    }
}
  • 버튼 클릭 이벤트 구현 → 델리게이트 변수를 통해 현재 뷰를 가지고 있는 뷰 컨트롤러 단에서 프로토콜이 선언한 함수 등 사용 가능

구현 화면

profile
JUST DO IT

0개의 댓글