From 93f5438b14f4be6420dadfed154006d460a9cb29 Mon Sep 17 00:00:00 2001 From: Gorjan Shukov Date: Tue, 13 Aug 2024 01:02:52 +0200 Subject: [PATCH] Add cancelDownload method on CachingPlayerItem --- Source/CachingPlayerItem.swift | 21 ++++++++++++++++----- Source/ResourceLoaderDelegate.swift | 15 ++++++++++----- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/Source/CachingPlayerItem.swift b/Source/CachingPlayerItem.swift index a936236..fe187dc 100644 --- a/Source/CachingPlayerItem.swift +++ b/Source/CachingPlayerItem.swift @@ -56,7 +56,7 @@ public final class CachingPlayerItem: AVPlayerItem { } /** - Play and cache remote media on a local file. `saveFilePath` is **radomly** generated. Requires `url.pathExtension` to not be empty otherwise the player will fail playing. + Play and cache remote media on a local file. `saveFilePath` is **randomly** generated. Requires `url.pathExtension` to not be empty otherwise the player will fail playing. - parameter url: URL referencing the media file. @@ -68,7 +68,7 @@ public final class CachingPlayerItem: AVPlayerItem { } /** - Play and cache remote media on a local file. `saveFilePath` is **radomly** generated. + Play and cache remote media on a local file. `saveFilePath` is **randomly** generated. - parameter url: URL referencing the media file. @@ -202,11 +202,11 @@ public final class CachingPlayerItem: AVPlayerItem { deinit { removeObservers() - // Don't reference lazy `resourceLoaderDelegate` if it hasn't been called before. + // Cancel download only for caching inits guard initialScheme != nil else { return } // Otherwise the ResourceLoaderDelegate wont deallocate and will keep downloading. - resourceLoaderDelegate.invalidateAndCancelSession() + cancelDownload() } // MARK: Public methods @@ -215,13 +215,24 @@ public final class CachingPlayerItem: AVPlayerItem { public func download() { // Make sure we are not initilalized with a filePath or non-caching init. guard initialScheme != nil else { - assertionFailure("CachingPlayerItem error: Download method used on a non caching instance") + assertionFailure("CachingPlayerItem error: `download` method used on a non caching instance") return } resourceLoaderDelegate.startDataRequest(with: url) } + /// Cancels the download of the media file and deletes the incomplete cached file. Works only with the initializers intended for play and cache. + public func cancelDownload() { + // Make sure we are not initilalized with a filePath or non-caching init. + guard initialScheme != nil else { + assertionFailure("CachingPlayerItem error: `cancelDownload` method used on a non caching instance") + return + } + + resourceLoaderDelegate.invalidateAndCancelSession() + } + // MARK: KVO private var playerItemContext = 0 diff --git a/Source/ResourceLoaderDelegate.swift b/Source/ResourceLoaderDelegate.swift index d49aef0..6bb022a 100644 --- a/Source/ResourceLoaderDelegate.swift +++ b/Source/ResourceLoaderDelegate.swift @@ -118,6 +118,14 @@ final class ResourceLoaderDelegate: NSObject, AVAssetResourceLoaderDelegate, URL func invalidateAndCancelSession() { session?.invalidateAndCancel() + session = nil + bufferData = Data() + pendingRequests.removeAll() + + // We need to only remove the file if it hasn't been fully downloaded + guard isDownloadComplete == false else { return } + + fileHandle.deleteFile() } // MARK: Private methods @@ -206,7 +214,7 @@ final class ResourceLoaderDelegate: NSObject, AVAssetResourceLoaderDelegate, URL } private func downloadFailed(with error: Error) { - fileHandle.deleteFile() + invalidateAndCancelSession() DispatchQueue.main.async { self.owner?.delegate?.playerItem?(self.owner!, downloadingFailedWith: error) @@ -214,9 +222,6 @@ final class ResourceLoaderDelegate: NSObject, AVAssetResourceLoaderDelegate, URL } @objc private func handleAppWillTerminate() { - // We need to only remove the file if it hasn't been fully downloaded - guard isDownloadComplete == false else { return } - - fileHandle.deleteFile() + invalidateAndCancelSession() } }