본문 바로가기

iOS/Toy project

[iOS : Toy Project] Apple Music App (7) : Music Slider 기능

이전 포스팅

- AppleMusicApp(1) : 뷰 구성

- AppleMusicApp(2) : Track 모델 (데이터 구조)

- AppleMusicApp(3) : UiCollectionViewCell 업데이트

- AppleMusicApp(4) : HeaderView (CollectionReusableView)

- AppleMusicApp(5) : Player 화면 + 싱글톤

- AppleMusicApp(6) : 뷰사이 데이터 이동 

 

 

자세한 코드는 여기로!

https://github.com/yexjin/iOS_Study/tree/main/AppleMusicApp

 

GitHub - yexjin/iOS_Study: iOS 토이프로젝트 모음집📱

iOS 토이프로젝트 모음집📱. Contribute to yexjin/iOS_Study development by creating an account on GitHub.

github.com

 

 

 


 

9/26

오늘 구현할 것!

조기 슬라이드!!

 

 

1️⃣ 현재 음악이 재생되는 시간 받아오기

var timeObserver: Any?  // 현재 재생되는 item의 시간을 일정하게 관찰하는 프로퍼티
updateTime(time: CMTime.zero)
// TODO: Time Observer 구현
// - addPeriodicTimeObserver : 일정간격으로 시간을 관찰하는 함수
// - addPeriodicTimeObserver 함수를 timeObserver에 추가
timeObserver = simplePlayer.addPeriodicTimeObserver(forInterval:CMTime(seconds: 1, preferredTimescale: 10),queue:DispatchQueue.main, using:{time in
	self.updateTime(time: time)
})

CMTime (Core Media Time)

- AVFoundation 밑에 있는 Core Media

- 우리가 관찰하는 시간의 주기는 0.1초, 이를 CMTime 객체에게 넘겨줘야 함.

- 1초를 10으로 나눈것이기 때문에 CMTime(seconds: 1, perferredTimescale: 10)

DispatchQueue

- 0.1초마다 UILabel을 업뎃시켜야 하는데, UILabel은 Main thread에서 변경되어야 해서 Main thread에게 0.1초마다 알려주겠다는 뜻

- queue.DispatchQueue.main

Using (closure)

- CMTime이 인자로 넘어옴 == 해당하는 곡의 시간이 넘어옴 == 현재 재생되는 시간이 넘어감

- using:{time in self.updateTime(time: time)

 

 

TimeObserver의 틀 구현 끝!

 

 

updateTime() 수정

// currentTimeLabel과 durationTimeLabel의 text값 초기화
func updateTime(time: CMTime) {
    // TODO: 시간정보 업데이트, 심플 플레이어 이용하여 수정
    currentTimeLabel.text = secondToString(sec: simplePlayer.currentTime)
    totalDurationLabel.text = secondToString(sec: simplePlayer.totalDurationTime)
}

업데이트된 시간정보

 

 

 

 

2️⃣ slider update

- seeking: 슬라이더를 클릭하여 원하는지점으로 옮기는 행동

- 이 행동(seeking)을 하고 있지 않을 때, slider은 자동으로 업데이트 되어야 한다.

- 0.1초 단위로 updateTime()이 호출되어서 0.1초 단위로 slider 또한 자동 업데이트가 될 수 있도록 updateTime()안에 설정해주어야함!

 func updateTime(time: CMTime) {
    // print(time.seconds)
    // currentTime label, totalduration label, slider

    // TODO: 시간정보 업데이트, 심플플레이어 이용해서 수정
    currentTimeLabel.text = secondsToString(sec: simplePlayer.currentTime)   // 3.1234 >> 00:03
    totalDurationLabel.text = secondsToString(sec: simplePlayer.totalDurationTime)  // 39.2045  >> 00:39

    if isSeeking == false {
        // 노래 들으면서 시킹하면, 자꾸 슬라이더가 업데이트 됨, 따라서 시킹아닐때마 슬라이더 업데이트하자
        // TODO: 슬라이더 정보 업데이트
        timeSlider.value = Float(simplePlayer.currentTime/simplePlayer.totalDurationTime)
    }
}

- simplePlayer.currentTime과 simplePlayer.totalDurationTime은 Double 형이므로 Float 으로 타입캐스팅!

- 현재 시간을 전체시간으로 나누어서 timeSlider 값을 업데이트!

 

슬라이더를 만지지 않았을 때, 자동으로 시간이 업데이트!

 

 

 

 

3️⃣ 대망의 seeking 구현!

@IBAction func seek(_ sender: UISlider) {
    // TODO: 시킹 구현
    guard let currentItem = simplePlayer.currentItem else { return }
    let position = Double(sender.value)
    let seconds = currentItem.duration.seconds * position
    let time = CMTime(seconds: seconds, preferredTimescale: 100)
    simplePlayer.seek(to: time)
}

- 현재 재생중인 아이템을 currentItem으로 불러오고

- UISlider의 위치를 받아온다 (중간은 0.5 전체는 1, 0~1 범위의 slider)

- 이 위치에 전체 시간을 곱해주면 우리가 지정한 position의 시간이 된다.

- CMTime 객체로 생성

- seek 함수는 원하는 시간 재생을 위한 함수였다! 여기에 CMTime 객체인 time을 넣어줌!

 

 

 

🚀 구현 완료

 

 

 

 

 


 

다음은 이것저것 마무리!