I play audio using AVPlayer in the background and foreground from AppDelegate.After adding observer to check the play, a crash occurs when app goes to foreground from background while audio is playing
Crash : "an instance of class AVPlayerItem was deallocated while key value observers were still registered with it"
Many threads explains to remove observer so that we could avoid the crash.But thats in the case of moving to different viewControllers.I want to keep the audio playing in foreground and background.
Can someone help me to solve this?
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;
}