Apologies
You must be signed in to watch this lesson.
Monitor Download Progress Notification Center
Podcasts
Podcast episodes are quite large in file size, each episode can range from 50mb to 500mb depending on the duration. While a file is being downloaded from the internet, you can monitor it's progress by hooking up certain delegate methods. In this lesson, we will update the cells with a progress label to give users visual feedback on what's going on.

Comments (12)
blues
6 years ago
Hi Brian, Is this enough for deleting podcast file from Documents folder, or should there be some checking made when downloaded poscast list is empty. do { try FileManager.default.removeItem(at: trueLocation) } catch let err { print("Error - could not delete file:", err) }
Brian Voong
6 years ago
blues
6 years ago
Hi Brian, I don't know if this is the right place for these questions...but... I was able to get the device volume buttons work with the volume slider in PlayerDetailsView by replacing volume UISlider with UIView and then placing MPVolumeView as a subview to that view. Problem now is that I can't find to way to center the volume slider vertically inside that view. (when comparing to muted_volume and max_volume images) In PlayerDetailsView I put setupVolumeView() inside awakeFromNib() And then: fileprivate func setupVolumeView() { volumeView.backgroundColor = UIColor.clear let myVolumeView = MPVolumeView(frame: volumeView.bounds) myVolumeView.showsRouteButton = false volumeView.addSubview(myVolumeView) }
blues
6 years ago
Hi, I added this line and now it seems to be vertically centered. I don't know why value 9 seems to work with different UIView sizes. myVolumeView.center = CGPoint(x: volumeView.bounds.size.width / 2, y: volumeView.bounds.size.height - 9)
rufatmirza
6 years ago
Hi Brian, First, I want to thank you for the amazing course, it was really useful. I noticed an issue with the code. 1. deinit is never called. Well, this is understandable since we only minimize or maximize the view. But with this, we cannot remove the Notification Center observers either. 2. I think there is a retention cycle somewhere. I tried to remove the view from superview but the player continued to play and deinit is not called. I checked many things but couldn't find the place where the cycle occurs.
Dew Douglass
5 years ago
For future reference, how would I know that the selector for NotificationCenter.default.addObserver takes a parameter of type Notification?
Brian Voong
5 years ago
Dew Douglass
5 years ago
Hahaha. Oh man. 24:49, that face you make when you just laid out some super slick code haha
Brian Voong
5 years ago
atmanx5
5 years ago
Hi Brian, Great course. I don't see the source code anywhere? Did you remove it?
Brian Voong
5 years ago
atmanx5
5 years ago
got it! thanks for the quick reply.
Pavlos Nicolaou
5 years ago
Hey! did we have any solution to the issue? When you pause a podcast and select another one the Play Button does not change
Brian Voong
5 years ago
Pavlos Nicolaou
5 years ago
This is what I did! Cheers
mdoor1123
5 years ago
Hey Brian -- Really happy about this course as I learned a ton. I was wondering if you would consider doing a deeper dive into how you think about prototyping an app in Photoshop or Sketch. I'd prefer Sketch because it's already installed on my computer and is cheaper (think $99.00 vs the 29.99/month). But I'm willing to purchase Photoshop if that's what you'd be using to teach. Also, since this might be a less viewed course, wanted to make sure this was listed at a price that is economically viable for you to make it, I'd be more than willing to pay at least $75.00 USD for the course, but obviously negotiable. Meaning I'd be willing to pay more for the content or if you decided the price would need to be a bit higher. Thanks, Mike P.S: If you had other trainings on Illustrator or the Creative Cloud, I'd be willing to purchase those too.
Christophe Bugnon
5 years ago
FOR BONUS 40: Hey Brian, what do you think about change all your code with MVVM or MVP (ViewProtocol, PresenterProtocol etc...) ? And use Enums for cells styles, all application styles..., Typealias... and more if you have imagination. I watched almost all your courses but since 2 months I work as an intern in a company and they works with MVP. All the code is managed by enumerations and sometimes I'm a little bit lost to use them everywhere. It's hard to manage an app with 1000 files when you work generally with 20 or 30 files but enumeration can really help and I guess it would be a good things you help us to use it. For exemple, use it for manage our cells styles etc... Sorry for this long text, good course anyway. ;) Regards.
cofvco
5 years ago
Hi Brian, after finish this course, I learn a lot from you, but I found a bug with PlayerDetailView, when I play podcasts, durationLabel is not counting, I downloaded your code in last lession and run it, and It have bug too. I have tried to fix it, googled it but I can't figure out why it make bug?. Can you fix it and upload source code again, thanks :D
Brian Voong
5 years ago
Ouen_theara
4 years ago
Hi Brain , when I run project on iOS 13 it will crash can't run it.
ZeroSingularity
4 years ago
Part of the solution is within the project itself, you just need to rearrange the order of the calls as well as expose some the commandCenter methods to MPRemoteCommandHandlerStatus. By enabling the commandCenter command after you add a target to it will silence the warnings. The only method I've been struggling with is the handleCurrentTimeSliderChange method to work after it has been exposed to MPRemoteCommandHandlerStatus. Here's an article that goes into minor detail about the issue: https://forums.developer.apple.com/thread/121540 Solution: fileprivate func setupRemoteControl() { UIApplication.shared.beginReceivingRemoteControlEvents() let commandCenter = MPRemoteCommandCenter.shared() commandCenter.playCommand.addTarget { (_) -> MPRemoteCommandHandlerStatus in self.player.play() self.playPauseButton.setImage(#imageLiteral(resourceName: "pause"), for: .normal) self.miniPlayPauseButton.setImage(#imageLiteral(resourceName: "pause"), for: .normal) self.setupElapsedTime(playbackRate: 1) return .success } commandCenter.playCommand.isEnabled = true commandCenter.pauseCommand.addTarget { (_) -> MPRemoteCommandHandlerStatus in self.player.pause() self.playPauseButton.setImage(#imageLiteral(resourceName: "play"), for: .normal) self.miniPlayPauseButton.setImage(#imageLiteral(resourceName: "play"), for: .normal) self.setupElapsedTime(playbackRate: 0) return .success } commandCenter.pauseCommand.isEnabled = true commandCenter.togglePlayPauseCommand.addTarget { (_) -> MPRemoteCommandHandlerStatus in self.handlePlayPause() return .success } commandCenter.togglePlayPauseCommand.isEnabled = true commandCenter.nextTrackCommand.addTarget { (_) -> MPRemoteCommandHandlerStatus in self.handleNextTrack() return .success } commandCenter.nextTrackCommand.isEnabled = true commandCenter.previousTrackCommand.addTarget { (_) -> MPRemoteCommandHandlerStatus in self.handlePrevTrack() return .success } commandCenter.previousTrackCommand.isEnabled = true // //MARK:- CommandCenter Scrubbing // commandCenter.changePlaybackPositionCommand.addTarget { (_) -> MPRemoteCommandHandlerStatus in // self.handleCurrentTimeSliderChange(self) // // return .success // } // commandCenter.changePlaybackPositionCommand.isEnabled = true // commandCenter.changePlaybackPositionCommand.addTarget(self, action: #selector(handleCurrentTimeSliderChange(_:))) }
Andymartinau
4 years ago
This is so helpful! Thanks ZeroSingularity!
李承諴
3 years ago
love this course so much Professor brain, do you have idea about bonus lessons?
HELP & SUPPORT