diff --git a/Sources/Extensions/Foundation/Observable.swift b/Sources/Extensions/Foundation/Observable.swift
index 069486d49b86ac461db123d9226e4f4b67462341..3df5521d1f51584adcfbe33545123ed2d49b5e1d 100644
--- a/Sources/Extensions/Foundation/Observable.swift
+++ b/Sources/Extensions/Foundation/Observable.swift
@@ -6,25 +6,14 @@
  * Copyright © 2019 Videolabs
  *
  * Authors: Soomin Lee <bubu # mikan.io>
+ *          Craig Reyenga <craig.reyenga # gmail.com>
  *
  * Refer to the COPYING file of the official project for license.
  *****************************************************************************/
 
-// MARK: - Observer
-
-// Since weak is a property assigned to anything that is of class type and not struct
-// you have to explicitly constraint your generic parameter to be of class type
-class Observer<T: AnyObject> {
-    weak var observer: T?
-
-    init(_ observer: T) {
-        self.observer = observer
-    }
-}
-
 class Observable<T: AnyObject> {
     // Using ObjectIdentifier to avoid duplication and facilitate identification of observing object
-    private(set) var observers = [ObjectIdentifier: Observer<T>]()
+    private var observers = [ObjectIdentifier: Observer<T>]()
 
     func addObserver(_ observer: T) {
         let identifier = ObjectIdentifier(observer)
@@ -35,4 +24,30 @@ class Observable<T: AnyObject> {
         let identifier = ObjectIdentifier(observer)
         observers.removeValue(forKey: identifier)
     }
+
+    /// Notify observers by executing the provided action upon each.
+    /// - Parameter action: the action to execute upon each observer
+    func notifyObservers(action: (T) -> Void) {
+        // Copy keys before iterating so we can detect observers that have been
+        // removed as a side effect of calling out to a previous observer.
+        let keys = Array(observers.keys)
+
+        for k in keys {
+            guard let observer = observers[k]?.observer else { continue }
+            action(observer)
+        }
+    }
+
+}
+
+// MARK: - Observer
+
+// Since weak is a property assigned to anything that is of class type and not struct
+// you have to explicitly constraint your generic parameter to be of class type
+fileprivate class Observer<T: AnyObject> {
+   weak var observer: T?
+
+   init(_ observer: T) {
+       self.observer = observer
+   }
 }
diff --git a/Sources/Media Library/MediaLibraryModel/AlbumModel.swift b/Sources/Media Library/MediaLibraryModel/AlbumModel.swift
index 9307edb2e57313535ab3a372f60594ae5da00129..a2ccfa9f2a58cc0588d918d6cc7cafd3546a437f 100644
--- a/Sources/Media Library/MediaLibraryModel/AlbumModel.swift	
+++ b/Sources/Media Library/MediaLibraryModel/AlbumModel.swift	
@@ -87,8 +87,8 @@ extension AlbumModel {
         }
         sortModel.currentSort = criteria
         sortModel.desc = desc
-        observable.observers.forEach() {
-            $0.value.observer?.mediaLibraryBaseModelReloadView()
+        observable.notifyObservers {
+            $0.mediaLibraryBaseModelReloadView()
         }
     }
 }
@@ -112,8 +112,8 @@ extension VLCMLAlbum: SearchableMLModel {
 extension AlbumModel: MediaLibraryObserver {
     func medialibrary(_ medialibrary: MediaLibraryService, didAddAlbums albums: [VLCMLAlbum]) {
         albums.forEach({ append($0) })
-        observable.observers.forEach() {
-            $0.value.observer?.mediaLibraryBaseModelReloadView()
+        observable.notifyObservers {
+            $0.mediaLibraryBaseModelReloadView()
         }
     }
 
@@ -134,8 +134,8 @@ extension AlbumModel: MediaLibraryObserver {
 
         fileArrayLock.lock()
         files = swapModels(with: albums)
-        observable.observers.forEach() {
-            $0.value.observer?.mediaLibraryBaseModelReloadView()
+        observable.notifyObservers {
+            $0.mediaLibraryBaseModelReloadView()
         }
     }
 
@@ -147,8 +147,8 @@ extension AlbumModel: MediaLibraryObserver {
         files.removeAll {
             albumsIds.contains(NSNumber(value: $0.identifier()))
         }
-        observable.observers.forEach() {
-            $0.value.observer?.mediaLibraryBaseModelReloadView()
+        observable.notifyObservers {
+            $0.mediaLibraryBaseModelReloadView()
         }
     }
 
diff --git a/Sources/Media Library/MediaLibraryModel/ArtistModel.swift b/Sources/Media Library/MediaLibraryModel/ArtistModel.swift
index fdb169ad05239e81752fba751fc62e3c89c2986b..4934fab6e74f0e9e862abe0e7fdafe38c1e4c2a9 100644
--- a/Sources/Media Library/MediaLibraryModel/ArtistModel.swift	
+++ b/Sources/Media Library/MediaLibraryModel/ArtistModel.swift	
@@ -94,8 +94,8 @@ extension ArtistModel {
                                 medialibrary.artists(sortingCriteria: criteria, desc: desc, listAll: true)
         sortModel.currentSort = criteria
         sortModel.desc = desc
-        observable.observers.forEach() {
-            $0.value.observer?.mediaLibraryBaseModelReloadView()
+        observable.notifyObservers {
+            $0.mediaLibraryBaseModelReloadView()
         }
     }
 }
@@ -112,8 +112,8 @@ extension VLCMLArtist: SearchableMLModel {
 extension ArtistModel: MediaLibraryObserver {
     func medialibrary(_ medialibrary: MediaLibraryService, didAddArtists artists: [VLCMLArtist]) {
         artists.forEach({ append($0) })
-        observable.observers.forEach() {
-            $0.value.observer?.mediaLibraryBaseModelReloadView()
+        observable.notifyObservers {
+            $0.mediaLibraryBaseModelReloadView()
         }
     }
 
@@ -137,8 +137,8 @@ extension ArtistModel: MediaLibraryObserver {
         files = swapModels(with: artists)
         addNewArtists(artists)
         filterGeneratedArtists()
-        observable.observers.forEach() {
-            $0.value.observer?.mediaLibraryBaseModelReloadView()
+        observable.notifyObservers {
+            $0.mediaLibraryBaseModelReloadView()
         }
     }
 
@@ -150,8 +150,8 @@ extension ArtistModel: MediaLibraryObserver {
         files.removeAll {
             artistsIds.contains(NSNumber(value: $0.identifier()))
         }
-        observable.observers.forEach() {
-            $0.value.observer?.mediaLibraryBaseModelReloadView()
+        observable.notifyObservers {
+            $0.mediaLibraryBaseModelReloadView()
         }
     }
 
diff --git a/Sources/Media Library/MediaLibraryModel/CollectionModel.swift b/Sources/Media Library/MediaLibraryModel/CollectionModel.swift
index ab4a6c14673759ebbc0f6608cd9586927e794fca..9bd87f214be04a9b3cac52b6c72d9a0cbf5f9242 100644
--- a/Sources/Media Library/MediaLibraryModel/CollectionModel.swift	
+++ b/Sources/Media Library/MediaLibraryModel/CollectionModel.swift	
@@ -110,8 +110,8 @@ class CollectionModel: MLBaseModel {
         files = mediaCollection.files(with: criteria, desc: desc) ?? []
         sortModel.currentSort = criteria
         sortModel.desc = desc
-        observable.observers.forEach() {
-            $0.value.observer?.mediaLibraryBaseModelReloadView()
+        observable.notifyObservers {
+            $0.mediaLibraryBaseModelReloadView()
         }
     }
 }
@@ -126,8 +126,8 @@ extension CollectionModel: MediaLibraryObserver {
         if mediaCollection is VLCMLPlaylist {
             fileArrayLock.lock()
             files = mediaCollection.files() ?? []
-            observable.observers.forEach() {
-                $0.value.observer?.mediaLibraryBaseModelReloadView()
+            observable.notifyObservers {
+                $0.mediaLibraryBaseModelReloadView()
             }
 
             sort(by: sortModel.currentSort, desc: sortModel.desc)
@@ -140,8 +140,8 @@ extension CollectionModel: MediaLibraryObserver {
         }
         fileArrayLock.lock()
         files = mediaCollection.files() ?? []
-        observable.observers.forEach() {
-            $0.value.observer?.mediaLibraryBaseModelReloadView()
+        observable.notifyObservers {
+            $0.mediaLibraryBaseModelReloadView()
         }
 
         sort(by: sortModel.currentSort, desc: sortModel.desc)
@@ -153,8 +153,8 @@ extension CollectionModel: MediaLibraryObserver {
         }
         fileArrayLock.lock()
         files = mediaCollection.files() ?? []
-        observable.observers.forEach() {
-            $0.value.observer?.mediaLibraryBaseModelReloadView()
+        observable.notifyObservers {
+            $0.mediaLibraryBaseModelReloadView()
         }
 
         sort(by: sortModel.currentSort, desc: sortModel.desc)
@@ -171,8 +171,8 @@ extension CollectionModel: MediaLibraryObserver {
         }
         fileArrayLock.lock()
         files = mediaCollection.files() ?? []
-        observable.observers.forEach() {
-            $0.value.observer?.mediaLibraryBaseModelReloadView()
+        observable.notifyObservers {
+            $0.mediaLibraryBaseModelReloadView()
         }
 
         sort(by: sortModel.currentSort, desc: sortModel.desc)
diff --git a/Sources/Media Library/MediaLibraryModel/GenreModel.swift b/Sources/Media Library/MediaLibraryModel/GenreModel.swift
index 004e07a70924891da42e65a5bd32092d6a808ea6..6824e031eea5f28fe3d8c7dcd15e9c8d352c524f 100644
--- a/Sources/Media Library/MediaLibraryModel/GenreModel.swift	
+++ b/Sources/Media Library/MediaLibraryModel/GenreModel.swift	
@@ -53,8 +53,8 @@ class GenreModel: AudioCollectionModel {
 extension GenreModel: MediaLibraryObserver {
     func medialibrary(_ medialibrary: MediaLibraryService, didAddGenres genres: [VLCMLGenre]) {
         genres.forEach({ append($0) })
-        observable.observers.forEach() {
-            $0.value.observer?.mediaLibraryBaseModelReloadView()
+        observable.notifyObservers {
+            $0.mediaLibraryBaseModelReloadView()
         }
     }
 
@@ -74,8 +74,8 @@ extension GenreModel: MediaLibraryObserver {
 
         fileArrayLock.lock()
         files = swapModels(with: genres)
-        observable.observers.forEach() {
-            $0.value.observer?.mediaLibraryBaseModelReloadView()
+        observable.notifyObservers {
+            $0.mediaLibraryBaseModelReloadView()
         }
     }
 
@@ -87,8 +87,8 @@ extension GenreModel: MediaLibraryObserver {
         files.removeAll {
             genresIds.contains(NSNumber(value: $0.identifier()))
         }
-        observable.observers.forEach() {
-            $0.value.observer?.mediaLibraryBaseModelReloadView()
+        observable.notifyObservers {
+            $0.mediaLibraryBaseModelReloadView()
         }
     }
 
@@ -111,8 +111,8 @@ extension GenreModel {
         files = medialibrary.genres(sortingCriteria: criteria, desc: desc)
         sortModel.currentSort = criteria
         sortModel.desc = desc
-        observable.observers.forEach() {
-            $0.value.observer?.mediaLibraryBaseModelReloadView()
+        observable.notifyObservers {
+            $0.mediaLibraryBaseModelReloadView()
         }
     }
 }
diff --git a/Sources/Media Library/MediaLibraryModel/HistoryModel.swift b/Sources/Media Library/MediaLibraryModel/HistoryModel.swift
index 04a0897576d76d62ee50720790975539799726ab..c168736371b7fb5d45ef5d23f8fa96d327fe20fb 100644
--- a/Sources/Media Library/MediaLibraryModel/HistoryModel.swift	
+++ b/Sources/Media Library/MediaLibraryModel/HistoryModel.swift	
@@ -57,8 +57,8 @@ extension HistoryModel: MediaLibraryObserver {
         } else {
             files = medialibrary.medialib.videoHistory() ?? []
         }
-        observable.observers.forEach() {
-            $0.value.observer?.mediaLibraryBaseModelReloadView()
+        observable.notifyObservers {
+            $0.mediaLibraryBaseModelReloadView()
         }
     }
 
@@ -72,8 +72,8 @@ extension HistoryModel: MediaLibraryObserver {
         } else {
             files = medialibrary.medialib.videoHistory() ?? []
         }
-        observable.observers.forEach() {
-            $0.value.observer?.mediaLibraryBaseModelReloadView()
+        observable.notifyObservers {
+            $0.mediaLibraryBaseModelReloadView()
         }
     }
     
diff --git a/Sources/Media Library/MediaLibraryModel/MediaGroupViewModel.swift b/Sources/Media Library/MediaLibraryModel/MediaGroupViewModel.swift
index 688a92d2bf2c01a5e180943d3e674a2c622b2bbc..43bdd193d32d2842cbb5edc4af7d546c7da2176f 100644
--- a/Sources/Media Library/MediaLibraryModel/MediaGroupViewModel.swift	
+++ b/Sources/Media Library/MediaLibraryModel/MediaGroupViewModel.swift	
@@ -95,8 +95,8 @@ class MediaGroupViewModel: MLBaseModel {
         }
         sortModel.currentSort = criteria
         sortModel.desc = desc
-        observable.observers.forEach() {
-            $0.value.observer?.mediaLibraryBaseModelReloadView()
+        observable.notifyObservers {
+            $0.mediaLibraryBaseModelReloadView()
         }
     }
 
@@ -172,8 +172,8 @@ extension MediaGroupViewModel: MediaLibraryObserver {
                 }
             }
         }
-        observable.observers.forEach() {
-            $0.value.observer?.mediaLibraryBaseModelReloadView()
+        observable.notifyObservers {
+            $0.mediaLibraryBaseModelReloadView()
         }
     }
 
@@ -192,8 +192,8 @@ extension MediaGroupViewModel: MediaLibraryObserver {
         fileArrayQueue.sync {
             files = swapModels(with: mediaGroups)
         }
-        observable.observers.forEach() {
-            $0.value.observer?.mediaLibraryBaseModelReloadView()
+        observable.notifyObservers {
+            $0.mediaLibraryBaseModelReloadView()
         }
     }
 
@@ -204,18 +204,18 @@ extension MediaGroupViewModel: MediaLibraryObserver {
                 mediaGroupsIds.contains(NSNumber(value: $0.identifier()))
             }
         }
-        observable.observers.forEach() {
-            $0.value.observer?.mediaLibraryBaseModelReloadView()
+        observable.notifyObservers {
+            $0.mediaLibraryBaseModelReloadView()
         }
     }
 
     // MARK: - VLCMLMedia
 
     func medialibrary(_ medialibrary: MediaLibraryService, didModifyVideos videos: [VLCMLMedia]) {
-        if !videos.isEmpty {
-            observable.observers.forEach() {
-                $0.value.observer?.mediaLibraryBaseModelReloadView()
-            }
+        guard !videos.isEmpty else { return }
+
+        observable.notifyObservers {
+            $0.mediaLibraryBaseModelReloadView()
         }
     }
 
@@ -227,8 +227,8 @@ extension MediaGroupViewModel: MediaLibraryObserver {
         guard success else {
             return
         }
-        observable.observers.forEach() {
-            $0.value.observer?.mediaLibraryBaseModelReloadView()
+        observable.notifyObservers {
+            $0.mediaLibraryBaseModelReloadView()
         }
     }
 }
diff --git a/Sources/Media Library/MediaLibraryModel/PlaylistModel.swift b/Sources/Media Library/MediaLibraryModel/PlaylistModel.swift
index 43311aa91630a11530d6f7b247a7cb6369f25fdb..25c1e973220ac424dfdb39742ded4d9b91322d0e 100644
--- a/Sources/Media Library/MediaLibraryModel/PlaylistModel.swift	
+++ b/Sources/Media Library/MediaLibraryModel/PlaylistModel.swift	
@@ -77,8 +77,8 @@ class PlaylistModel: MLBaseModel {
         // Update directly the UI without waiting the delegate to avoid showing 'ghost' items
         fileArrayLock.lock()
         filterFilesFromDeletion(of: items)
-        observable.observers.forEach() {
-            $0.value.observer?.mediaLibraryBaseModelReloadView()
+        observable.notifyObservers {
+            $0.mediaLibraryBaseModelReloadView()
         }
     }
 
@@ -89,8 +89,8 @@ class PlaylistModel: MLBaseModel {
             return
         }
         append(playlist)
-        observable.observers.forEach() {
-            $0.value.observer?.mediaLibraryBaseModelReloadView()
+        observable.notifyObservers {
+            $0.mediaLibraryBaseModelReloadView()
         }
     }
 }
@@ -105,8 +105,8 @@ extension PlaylistModel {
         files = medialibrary.playlists(sortingCriteria: criteria, desc: desc)
         sortModel.currentSort = criteria
         sortModel.desc = desc
-        observable.observers.forEach() {
-            $0.value.observer?.mediaLibraryBaseModelReloadView()
+        observable.notifyObservers {
+            $0.mediaLibraryBaseModelReloadView()
         }
     }
 }
@@ -122,8 +122,8 @@ extension VLCMLPlaylist: SearchableMLModel {
 extension PlaylistModel: MediaLibraryObserver {
     func medialibrary(_ medialibrary: MediaLibraryService, didAddPlaylists playlists: [VLCMLPlaylist]) {
         playlists.forEach({ append($0) })
-        observable.observers.forEach() {
-            $0.value.observer?.mediaLibraryBaseModelReloadView()
+        observable.notifyObservers {
+            $0.mediaLibraryBaseModelReloadView()
         }
     }
 
@@ -144,8 +144,8 @@ extension PlaylistModel: MediaLibraryObserver {
 
         fileArrayLock.lock()
         files = swapModels(with: playlists)
-        observable.observers.forEach() {
-            $0.value.observer?.mediaLibraryBaseModelReloadView()
+        observable.notifyObservers {
+            $0.mediaLibraryBaseModelReloadView()
         }
     }
 
@@ -160,8 +160,8 @@ extension PlaylistModel: MediaLibraryObserver {
             }
             return true
         }
-        observable.observers.forEach() {
-            $0.value.observer?.mediaLibraryBaseModelReloadView()
+        observable.notifyObservers {
+            $0.mediaLibraryBaseModelReloadView()
         }
     }
 
diff --git a/Sources/Media Library/MediaLibraryModel/ShowEpisodeModel.swift b/Sources/Media Library/MediaLibraryModel/ShowEpisodeModel.swift
index af6291946bc0c78804e94379c33e29ec42343f21..debed46d1d025aa2c664a9e4240eaa9c9b49fe3f 100644
--- a/Sources/Media Library/MediaLibraryModel/ShowEpisodeModel.swift	
+++ b/Sources/Media Library/MediaLibraryModel/ShowEpisodeModel.swift	
@@ -58,8 +58,8 @@ extension ShowEpisodeModel {
 extension ShowEpisodeModel: MediaLibraryObserver {
     func medialibrary(_ medialibrary: MediaLibraryService, didAddShowEpisodes showEpisodes: [VLCMLMedia]) {
         showEpisodes.forEach({ append($0) })
-        observable.observers.forEach() {
-            $0.value.observer?.mediaLibraryBaseModelReloadView()
+        observable.notifyObservers {
+            $0.mediaLibraryBaseModelReloadView()
         }
     }
 
diff --git a/Sources/Media Library/MediaLibraryModel/TrackModel.swift b/Sources/Media Library/MediaLibraryModel/TrackModel.swift
index c837addd7f199c6052c83e07eb66dbbb6aa75095..f7cdb6b0c5f633eafd7d8e2c67ba2ea671f113d5 100644
--- a/Sources/Media Library/MediaLibraryModel/TrackModel.swift	
+++ b/Sources/Media Library/MediaLibraryModel/TrackModel.swift	
@@ -54,8 +54,8 @@ extension TrackModel {
                                    desc: desc)
         sortModel.currentSort = criteria
         sortModel.desc = desc
-        observable.observers.forEach() {
-            $0.value.observer?.mediaLibraryBaseModelReloadView()
+        observable.notifyObservers {
+            $0.mediaLibraryBaseModelReloadView()
         }
     }
 }
@@ -69,8 +69,8 @@ extension TrackModel: MediaLibraryObserver {
         }
         fileArrayLock.lock()
         tracks.forEach({ append($0) })
-        observable.observers.forEach() {
-            $0.value.observer?.mediaLibraryBaseModelReloadView()
+        observable.notifyObservers {
+            $0.mediaLibraryBaseModelReloadView()
         }
     }
 
@@ -81,8 +81,8 @@ extension TrackModel: MediaLibraryObserver {
             }
             fileArrayLock.lock()
             files = swapModels(with: tracks)
-            observable.observers.forEach() {
-                $0.value.observer?.mediaLibraryBaseModelReloadView()
+            observable.notifyObservers {
+                $0.mediaLibraryBaseModelReloadView()
             }
         }
     }
@@ -98,8 +98,8 @@ extension TrackModel: MediaLibraryObserver {
             }
             return true
         }
-        observable.observers.forEach() {
-            $0.value.observer?.mediaLibraryBaseModelReloadView()
+        observable.notifyObservers {
+            $0.mediaLibraryBaseModelReloadView()
         }
     }
 }
diff --git a/Sources/Media Library/MediaLibraryModel/VideoModel.swift b/Sources/Media Library/MediaLibraryModel/VideoModel.swift
index f5bca292857ed0d5d0574e134c3544c6b263cc24..d438d50f4517211bb1a9a81458e8125c1c677af5 100644
--- a/Sources/Media Library/MediaLibraryModel/VideoModel.swift	
+++ b/Sources/Media Library/MediaLibraryModel/VideoModel.swift	
@@ -55,8 +55,8 @@ extension VideoModel {
                                    desc: desc)
         sortModel.currentSort = criteria
         sortModel.desc = desc
-        observable.observers.forEach() {
-            $0.value.observer?.mediaLibraryBaseModelReloadView()
+        observable.notifyObservers {
+            $0.mediaLibraryBaseModelReloadView()
         }
     }
 }
@@ -70,8 +70,8 @@ extension VideoModel: MediaLibraryObserver {
         }
         fileArrayLock.lock()
         videos.forEach({ append($0) })
-        observable.observers.forEach() {
-            $0.value.observer?.mediaLibraryBaseModelReloadView()
+        observable.notifyObservers {
+            $0.mediaLibraryBaseModelReloadView()
         }
     }
 
@@ -82,8 +82,8 @@ extension VideoModel: MediaLibraryObserver {
             }
             fileArrayLock.lock()
             files = swapModels(with: videos)
-            observable.observers.forEach() {
-                $0.value.observer?.mediaLibraryBaseModelReloadView()
+            observable.notifyObservers {
+                $0.mediaLibraryBaseModelReloadView()
             }
         }
     }
@@ -99,8 +99,8 @@ extension VideoModel: MediaLibraryObserver {
             }
             return true
         }
-        observable.observers.forEach() {
-            $0.value.observer?.mediaLibraryBaseModelReloadView()
+        observable.notifyObservers {
+            $0.mediaLibraryBaseModelReloadView()
         }
     }
 
@@ -117,8 +117,8 @@ extension VideoModel: MediaLibraryObserver {
         }
         fileArrayLock.lock()
         files = swapModels(with: [media])
-        observable.observers.forEach() {
-            $0.value.observer?.mediaLibraryBaseModelReloadView()
+        observable.notifyObservers {
+            $0.mediaLibraryBaseModelReloadView()
         }
     }
 }
diff --git a/Sources/Media Library/MediaLibraryService.swift b/Sources/Media Library/MediaLibraryService.swift
index 766b4de0789d3d4d15a542e7e0c501cbc011f9d4..4a218f2e734cc7a1f75419bc1f6f498ec7dd3775 100644
--- a/Sources/Media Library/MediaLibraryService.swift	
+++ b/Sources/Media Library/MediaLibraryService.swift	
@@ -510,9 +510,9 @@ extension MediaLibraryService: VLCMediaLibraryDelegate {
         let videos = media.filter {( $0.type() == .video )}
         let tracks = media.filter {( $0.type() == .audio )}
 
-        for observer in observable.observers {
-            observer.value.observer?.medialibrary?(self, didAddVideos: videos)
-            observer.value.observer?.medialibrary?(self, didAddTracks: tracks)
+        observable.notifyObservers {
+            $0.medialibrary?(self, didAddVideos: videos)
+            $0.medialibrary?(self, didAddTracks: tracks)
         }
     }
 
@@ -534,11 +534,11 @@ extension MediaLibraryService: VLCMediaLibraryDelegate {
         let tracks = media.filter {( $0.type() == .audio)}
 
         // Shows and albumtracks are known only after when the medialibrary calls didModifyMedia
-        for observer in observable.observers {
-            observer.value.observer?.medialibrary?(self, didAddShowEpisodes: showEpisodes)
-            observer.value.observer?.medialibrary?(self, didAddAlbumTracks: albumTrack)
-            observer.value.observer?.medialibrary?(self, didModifyVideos: videos)
-            observer.value.observer?.medialibrary?(self, didModifyTracks: tracks)
+        observable.notifyObservers {
+            $0.medialibrary?(self, didAddShowEpisodes: showEpisodes)
+            $0.medialibrary?(self, didAddAlbumTracks: albumTrack)
+            $0.medialibrary?(self, didModifyVideos: videos)
+            $0.medialibrary?(self, didModifyTracks: tracks)
         }
     }
 
@@ -547,16 +547,16 @@ extension MediaLibraryService: VLCMediaLibraryDelegate {
         mediaIds.forEach { stringIds.append("\($0)") }
         CSSearchableIndex.default().deleteSearchableItems(withIdentifiers: stringIds, completionHandler: nil)
 
-        for observer in observable.observers {
-            observer.value.observer?.medialibrary?(self, didDeleteMediaWithIds: mediaIds)
+        observable.notifyObservers {
+            $0.medialibrary?(self, didDeleteMediaWithIds: mediaIds)
         }
     }
 
     func medialibrary(_ medialibrary: VLCMediaLibrary, thumbnailReadyFor media: VLCMLMedia,
                       of type: VLCMLThumbnailSizeType, withSuccess success: Bool) {
-        for observer in observable.observers {
-            observer.value.observer?.medialibrary?(self, thumbnailReady: media,
-                                                   type: type, success: success)
+        observable.notifyObservers {
+            $0.medialibrary?(self, thumbnailReady: media,
+                             type: type, success: success)
         }
     }
 }
@@ -565,21 +565,21 @@ extension MediaLibraryService: VLCMediaLibraryDelegate {
 
 extension MediaLibraryService {
     func medialibrary(_ medialibrary: VLCMediaLibrary, didAdd artists: [VLCMLArtist]) {
-        for observer in observable.observers {
-            observer.value.observer?.medialibrary?(self, didAddArtists: artists)
+        observable.notifyObservers {
+            $0.medialibrary?(self, didAddArtists: artists)
         }
     }
 
     func medialibrary(_ medialibrary: VLCMediaLibrary,
                       didModifyArtistsWithIds artistsIds: [NSNumber]) {
-        for observer in observable.observers {
-            observer.value.observer?.medialibrary?(self, didModifyArtistsWithIds: artistsIds)
+        observable.notifyObservers {
+            $0.medialibrary?(self, didModifyArtistsWithIds: artistsIds)
         }
     }
 
     func medialibrary(_ medialibrary: VLCMediaLibrary, didDeleteArtistsWithIds artistsIds: [NSNumber]) {
-        for observer in observable.observers {
-            observer.value.observer?.medialibrary?(self, didDeleteArtistsWithIds: artistsIds)
+        observable.notifyObservers {
+            $0.medialibrary?(self, didDeleteArtistsWithIds: artistsIds)
         }
     }
 }
@@ -588,21 +588,21 @@ extension MediaLibraryService {
 
 extension MediaLibraryService {
     func medialibrary(_ medialibrary: VLCMediaLibrary, didAdd albums: [VLCMLAlbum]) {
-        for observer in observable.observers {
-            observer.value.observer?.medialibrary?(self, didAddAlbums: albums)
+        observable.notifyObservers {
+            $0.medialibrary?(self, didAddAlbums: albums)
         }
     }
 
     func medialibrary(_ medialibrary: VLCMediaLibrary,
                       didModifyAlbumsWithIds albumsIds: [NSNumber]) {
-        for observer in observable.observers {
-            observer.value.observer?.medialibrary?(self, didModifyAlbumsWithIds: albumsIds)
+        observable.notifyObservers {
+            $0.medialibrary?(self, didModifyAlbumsWithIds: albumsIds)
         }
     }
 
     func medialibrary(_ medialibrary: VLCMediaLibrary, didDeleteAlbumsWithIds albumsIds: [NSNumber]) {
-        for observer in observable.observers {
-            observer.value.observer?.medialibrary?(self, didDeleteAlbumsWithIds: albumsIds)
+        observable.notifyObservers {
+            $0.medialibrary?(self, didDeleteAlbumsWithIds: albumsIds)
         }
     }
 }
@@ -611,22 +611,22 @@ extension MediaLibraryService {
 
 extension MediaLibraryService {
     func medialibrary(_ medialibrary: VLCMediaLibrary, didAdd genres: [VLCMLGenre]) {
-        for observer in observable.observers {
-            observer.value.observer?.medialibrary?(self, didAddGenres: genres)
+        observable.notifyObservers {
+            $0.medialibrary?(self, didAddGenres: genres)
         }
     }
 
     func medialibrary(_ medialibrary: VLCMediaLibrary,
                       didModifyGenresWithIds genresIds: [NSNumber]) {
-        for observer in observable.observers {
-            observer.value.observer?.medialibrary?(self, didModifyGenresWithIds: genresIds)
+        observable.notifyObservers {
+            $0.medialibrary?(self, didModifyGenresWithIds: genresIds)
         }
     }
 
     func medialibrary(_ medialibrary: VLCMediaLibrary,
                       didDeleteGenresWithIds genresIds: [NSNumber]) {
-        for observer in observable.observers {
-            observer.value.observer?.medialibrary?(self, didDeleteGenresWithIds: genresIds)
+        observable.notifyObservers {
+            $0.medialibrary?(self, didDeleteGenresWithIds: genresIds)
         }
     }
 }
@@ -635,21 +635,21 @@ extension MediaLibraryService {
 
 extension MediaLibraryService {
     func medialibrary(_ medialibrary: VLCMediaLibrary, didAdd playlists: [VLCMLPlaylist]) {
-        for observer in observable.observers {
-            observer.value.observer?.medialibrary?(self, didAddPlaylists: playlists)
+        observable.notifyObservers {
+            $0.medialibrary?(self, didAddPlaylists: playlists)
         }
     }
 
     func medialibrary(_ medialibrary: VLCMediaLibrary,
                       didModifyPlaylistsWithIds playlistsIds: [NSNumber]) {
-        for observer in observable.observers {
-            observer.value.observer?.medialibrary?(self, didModifyPlaylistsWithIds: playlistsIds)
+        observable.notifyObservers {
+            $0.medialibrary?(self, didModifyPlaylistsWithIds: playlistsIds)
         }
     }
 
     func medialibrary(_ medialibrary: VLCMediaLibrary, didDeletePlaylistsWithIds playlistsIds: [NSNumber]) {
-        for observer in observable.observers {
-            observer.value.observer?.medialibrary?(self, didDeletePlaylistsWithIds: playlistsIds)
+        observable.notifyObservers {
+            $0.medialibrary?(self, didDeletePlaylistsWithIds: playlistsIds)
         }
     }
 }
@@ -658,25 +658,22 @@ extension MediaLibraryService {
 
 extension MediaLibraryService {
     func medialibrary(_ medialibrary: VLCMediaLibrary, didAdd mediaGroups: [VLCMLMediaGroup]) {
-        for observer in observable.observers {
-            observer.value.observer?.medialibrary?(self,
-                                                   didAddMediaGroups: mediaGroups)
+        observable.notifyObservers {
+            $0.medialibrary?(self, didAddMediaGroups: mediaGroups)
         }
     }
 
     func medialibrary(_ medialibrary: VLCMediaLibrary,
                       didModifyMediaGroupsWithIds mediaGroupsIds: [NSNumber]) {
-        for observer in observable.observers {
-            observer.value.observer?.medialibrary?(self,
-                                                   didModifyMediaGroupsWithIds: mediaGroupsIds)
+        observable.notifyObservers {
+            $0.medialibrary?(self, didModifyMediaGroupsWithIds: mediaGroupsIds)
         }
     }
 
     func medialibrary(_ medialibrary: VLCMediaLibrary,
                       didDeleteMediaGroupsWithIds mediaGroupsIds: [NSNumber]) {
-        for observer in observable.observers {
-            observer.value.observer?.medialibrary?(self,
-                                                   didDeleteMediaGroupsWithIds: mediaGroupsIds)
+        observable.notifyObservers {
+            $0.medialibrary?(self, didDeleteMediaGroupsWithIds: mediaGroupsIds)
         }
     }
 }
@@ -717,16 +714,16 @@ extension MediaLibraryService {
 
 extension MediaLibraryService {
     func medialibraryDidStartRescan(_ medialibrary: VLCMediaLibrary) {
-        for observer in observable.observers {
-            observer.value.observer?.medialibraryDidStartRescan?()
+        observable.notifyObservers {
+            $0.medialibraryDidStartRescan?()
         }
     }
 }
 
 extension MediaLibraryService {
     func medialibrary(_ medialibrary: VLCMediaLibrary, historyChangedOf type: VLCMLHistoryType) {
-        for observer in observable.observers {
-            observer.value.observer?.medialibrary?(self, historyChangedOfType: type)
+        observable.notifyObservers {
+            $0.medialibrary?(self, historyChangedOfType: type)
         }
     }
 }