How do I deal with the AVPlayerItem watcher when the app goes out of the background?
I am playing audio with AVPlayer in background and foreground from AppDelegate. After adding a watcher to test playback, it crashes when applied to the foreground from background during audio playback
Failure: "An instance of the AVPlayerItem class has been freed while observers with key values ββwere still registered with it"
Many threads explain the removal of the observer so that we can avoid a crash. But in case of switching to different viewControllers.I want the audio to play in the foreground and in the background.
Can anyone help me to solve this problem?
This is my code:
case AudioLocation:{
audioUrl = [NSURL URLWithString:[responseDictionary
objectForKey:@"result"]];
if(!([[[NSUserDefaults
standardUserDefaults]objectForKey:@"audioURL"] isEqual:
[responseDictionary objectForKey:@"result"]]))
{
playerItem = [AVPlayerItem playerItemWithURL:audioUrl];
player = [AVPlayer playerWithPlayerItem:playerItem];
player = [AVPlayer playerWithURL:audioUrl];
player.automaticallyWaitsToMinimizeStalling = false;
[player.currentItem addObserver:self forKeyPath:@"status"
options:0 context:nil];
[player addObserver:self forKeyPath:@"rate" options:0
context:nil];
[player play];
isPlaying = YES;
}
-(void)observeValueForKeyPath:(NSString*)keyPath
ofObject:(id)object
change:(NSDictionary*)change
context:(void*)context {
if ([keyPath isEqualToString:@"status"]) {
if (player.status == AVPlayerStatusFailed) {
}
}else if ([keyPath isEqualToString:@"rate"]) {
if (player.rate == 0 && //if player rate dropped to 0
CMTIME_COMPARE_INLINE(player.currentItem.currentTime, >,
kCMTimeZero) &&
CMTIME_COMPARE_INLINE(player.currentItem.currentTime, <,
player.currentItem.duration) &&isPlaying)
[self handleStalled];
}
}
-(void)handleStalled {
NSLog(@"Handle stalled. Available: %lf", [self availableDuration]);
if (player.currentItem.playbackLikelyToKeepUp || //
[self availableDuration] -
CMTimeGetSeconds(player.currentItem.currentTime) > 10.0) {
[player play];
} else {
[self performSelector:@selector(handleStalled) withObject:nil
afterDelay:0.5]; //try again
}
}
- (NSTimeInterval) availableDuration
{
NSArray *loadedTimeRanges = [[player currentItem] loadedTimeRanges];
CMTimeRange timeRange = [[loadedTimeRanges objectAtIndex:0]
CMTimeRangeValue];
Float64 startSeconds = CMTimeGetSeconds(timeRange.start);
Float64 durationSeconds = CMTimeGetSeconds(timeRange.duration);
NSTimeInterval result = startSeconds + durationSeconds;
return result;
}
+3
source to share
No one has answered this question yet
Check out similar questions: