@@ -16,6 +16,9 @@ import CoreImage
1616@MainActor @preconcurrency
1717public protocol AbstractPlayer : AnyObject {
1818
19+ /// Observes the status property of the new player item.
20+ var statusObserver : NSKeyValueObservation ? { get set }
21+
1922 /// An optional property that stores the current video settings.
2023 ///
2124 /// This property holds an instance of `VideoSettings` or nil if no settings have been configured yet.
@@ -147,6 +150,38 @@ extension AbstractPlayer{
147150 func pause( ) {
148151 player? . pause ( )
149152 }
153+
154+
155+
156+ /// Sets up an observer for the status of the provided `AVPlayerItem`.
157+ ///
158+ /// This method observes changes in the status of `newItem` and triggers the provided callback
159+ /// whenever the status changes to `.readyToPlay` or `.failed`. Once the callback is invoked,
160+ /// the observer is invalidated, ensuring that the callback is called only once.
161+ ///
162+ /// - Parameters:
163+ /// - newItem: The `AVPlayerItem` whose status is to be observed.
164+ /// - callback: A closure that is called when the item's status changes to `.readyToPlay` or `.failed`.
165+ func setupStateItemStatusObserver( newItem: AVPlayerItem , callback: ( ( AVPlayerItem . Status ) -> Void ) ? ) {
166+ statusObserver? . invalidate ( )
167+
168+ if let callback = callback {
169+ //.unknown: This state is essentially the default, indicating that the player item is new or has not yet attempted to load its assets.
170+ statusObserver = newItem. observe ( \. status, options: [ . new, . old] ) { [ weak self] item, _ in
171+ guard item. status == . readyToPlay || item. status == . failed else {
172+ return
173+ }
174+
175+ callback ( item. status)
176+ self ? . clearStatusObserver ( )
177+ }
178+ }
179+ }
180+
181+ func clearStatusObserver( ) {
182+ statusObserver? . invalidate ( )
183+ statusObserver = nil
184+ }
150185
151186 /// Seeks the video to a specific time.
152187 /// This method moves the playback position to the specified time with precise accuracy.
@@ -160,15 +195,23 @@ extension AbstractPlayer{
160195
161196 guard currentItem? . status == . readyToPlay else {
162197 /// The case when the video is finished and we are trying to seek back
163- if let currentAsset, let currentSettings{
164- let settings = currentSettings//.GetSettingsWithNotAutoPlay
165- update ( asset : currentAsset , settings : settings ) { [ weak self] status in
198+ if let currentItem , let currentAsset, let currentSettings{
199+
200+ let callback : ( ( AVPlayerItem . Status ) -> Void ) ? = { [ weak self] status in
166201 if status == . readyToPlay{
167202 self ? . seek ( to: time)
168203 } else {
169204 self ? . delegate? . didSeek ( value: false , currentTime: time)
170205 }
171206 }
207+
208+ guard playerLooper == nil else {
209+ setupStateItemStatusObserver ( newItem: currentItem, callback: callback)
210+ return
211+ }
212+
213+ let settings = currentSettings//.GetSettingsWithNotAutoPlay
214+ update ( asset: currentAsset, settings: settings, callback: callback)
172215 return
173216 }
174217
0 commit comments