Apologies
You must be signed in to watch this lesson.
Tracking Playback Time
Podcasts
One of the final features of an audio application is to track the current play time of your audio stream. In today's lesson, we'll use a Periodic Observer to monitor the play time of our AVPlayer object. Because the object's that we get back are CMTime types, we'll need to convert them into pretty display strings with special formats. Once we finish the implementation on this, we'll move onto modifying the duration label as well as the scrubber slider to update as the podcast episode is playing. Enjoy.
```swift extension CMTime { func toDisplayString() -> String { if CMTimeGetSeconds(self).isNaN { return "--:--" } let totalSeconds = Int(CMTimeGetSeconds(self)) let seconds = totalSeconds % 60 let minutes = totalSeconds % (60 * 60) / 60 let hours = totalSeconds / 60 / 60 let timeFormatString = String(format: "%02d:%02d:%02d", hours, minutes, seconds) return timeFormatString } } ```

Comments (8)
rinconchris
6 years ago
HI Brian - on an iPhone 6 running iOS 11.2.6 and loading a large podcast, I was getting crashes from the CMTime extension because currentItem.duration was still undefined. I was able to fix by checking to see if self.currentItem?.status == .readyToPlay before setting the labels. Seems like a more elegant way would be to change the extension to handle undefined but unsure how to do that.
Tube
6 years ago
Instead of calculating a percentage, one can also just cram the value into the slider: self.timeSlider.maximumValue = Float(CMTimeGetSeconds(self.player.currentItem?.duration ?? CMTimeMake(0, 0)))
Brian Voong
6 years ago
Alpensol
6 years ago
Hey Brian, Thanks very much for the great material provided, I actually decided to challenge myself to do all of this programatically from the start just to improve my skills and understanding. There are a couple of interesting challenges such as view communication and data passing between objects (I created custom stackViews for many of the elements on this screen so I need to pass data between), I have been using delegation and call backs however it is getting a bit messy, would introducing custom bindings wrappers and then maybe some RxSwift be a good solution in order to comply with the SOLID principles in this case ? Also a quick question, I made a wrong comment about reference cycles on the last video however I am pretty sure here we do have a Strong Reference Cycle created when in the closure of Periodic Time Observer ?
Raph
6 years ago
Hey Brian, I cant find in the project where you added the hours? Just to check that my code is the same as what you did :) thanks :)
Brian Voong
6 years ago
Raph
6 years ago
Good Idea!
Raph
6 years ago
Little tip: An easy way to get the right VC for your element in the StoryBoard to link by the assistant editor, just press option and click on the two. For example, you're in PlayerDetailsView.swift, hold option and click on PlayerDetailsView.Xib
duypham
5 years ago
This is helpful. Thanks a lot
edward
5 years ago
Hi Brian I believe there is an error in the code snippet above. Need to remove the (60 * 60) in the minutes calculation. Keep up the great videos.
xuano
5 years ago
No, there's no error. To make it a little bit easier to understand, I would do it like this: let minutes = (totalSeconds / 60) % 60
Thanh Minh
5 years ago
I think need to check duration value with the large audio file. let durationTime = self.player.currentItem?.duration if((durationTime?.value)! > 0){ self.playerDetailsView.durationLbl.text = durationTime?.toDisplayString() }
Dew Douglass
5 years ago
Damn that refactor -> extract method feature is sick! I love all these features you're showing us!
HELP & SUPPORT