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





All Articles