11//
22// FRadioPlayer.swift
3- // FRadioPlayerDemo
3+ // FRadioPlayer
44//
55// Created by Fethi El Hassasna on 2017-11-11.
6- // Copyright © 2017 Fethi El Hassasna. All rights reserved.
6+ // Copyright © 2017 Fethi El Hassasna (@fethica) . All rights reserved.
77//
88
99import AVFoundation
@@ -211,6 +211,12 @@ open class FRadioPlayer: NSObject {
211211 }
212212 }
213213
214+ /// Reachability for network interruption handling
215+ private let reachability = Reachability ( ) !
216+
217+ /// Current network connectivity
218+ private var isConnected = false
219+
214220 // MARK: - Initialization
215221
216222 private override init ( ) {
@@ -225,6 +231,11 @@ open class FRadioPlayer: NSObject {
225231
226232 // Check for headphones
227233 checkHeadphonesConnection ( outputs: AVAudioSession . sharedInstance ( ) . currentRoute. outputs)
234+
235+ // Reachability config
236+ try ? reachability. startNotifier ( )
237+ NotificationCenter . default. addObserver ( self , selector: #selector( reachabilityChanged ( note: ) ) , name: . reachabilityChanged, object: reachability)
238+ isConnected = reachability. connection != . none
228239 }
229240
230241 // MARK: - Control Methods
@@ -380,6 +391,11 @@ open class FRadioPlayer: NSObject {
380391 } )
381392 }
382393
394+ private func reloadItem( ) {
395+ player? . replaceCurrentItem ( with: nil )
396+ player? . replaceCurrentItem ( with: playerItem)
397+ }
398+
383399 private func resetPlayer( ) {
384400 stop ( )
385401 playerItem = nil
@@ -419,6 +435,34 @@ open class FRadioPlayer: NSObject {
419435 }
420436 }
421437
438+ @objc func reachabilityChanged( note: Notification ) {
439+
440+ guard let reachability = note. object as? Reachability else { return }
441+
442+ // Check if the internet connection was lost
443+ if reachability. connection != . none, !isConnected {
444+ checkNetworkInterruption ( )
445+ }
446+
447+ isConnected = reachability. connection != . none
448+ }
449+
450+ // Check if the playback could keep up after a network interruption
451+ private func checkNetworkInterruption( ) {
452+ guard
453+ let item = playerItem,
454+ !item. isPlaybackLikelyToKeepUp,
455+ reachability. connection != . none else { return }
456+
457+ player? . pause ( )
458+
459+ // Wait 1 sec to recheck and make sure the reload is needed
460+ DispatchQueue . main. asyncAfter ( deadline: DispatchTime . now ( ) + 1 ) {
461+ if !item. isPlaybackLikelyToKeepUp { self . reloadItem ( ) }
462+ self . isPlaying ? self . player? . play ( ) : self . player? . pause ( )
463+ }
464+ }
465+
422466 // MARK: - Responding to Route Changes
423467
424468 private func checkHeadphonesConnection( outputs: [ AVAudioSessionPortDescription ] ) {
@@ -464,7 +508,10 @@ open class FRadioPlayer: NSObject {
464508
465509 case " playbackBufferEmpty " :
466510
467- if item. isPlaybackBufferEmpty { self . state = . loading }
511+ if item. isPlaybackBufferEmpty {
512+ self . state = . loading
513+ self . checkNetworkInterruption ( )
514+ }
468515
469516 case " playbackLikelyToKeepUp " :
470517
@@ -480,4 +527,3 @@ open class FRadioPlayer: NSObject {
480527 }
481528 }
482529}
483-
0 commit comments