And one solution that binds all this information together.
Maybe player status should be handled differently, but I like the recursive way.
Note: If you do not need the exact seek time, you can use [_player seekToTime:<#(CMTime)#> completionHandler:<#^(BOOL finished)completionHandler#>]
It's faster but it seeks to the nearest key frame.
- (void)viewDidLoad
{
[super viewDidLoad];
....
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appEnteredForeground) name:UIApplicationWillEnterForegroundNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appEnteredBackground) name:UIApplicationDidEnterBackgroundNotification object:nil];
}
-(void)viewWillDisappear:(BOOL)animated
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillEnterForegroundNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:nil];
}
....
-(void) appEnteredForeground {
AVPlayerLayer *player = (AVPlayerLayer *)[playerView layer];
[player setPlayer:NULL];
[player setPlayer:_player];
[self playAt:currentTime];
}
-(void) appEnteredBackground {
[_player pause];
currentTime = [_player currentTime];
}
-(void)playAt: (CMTime)time {
if(_player.status == AVPlayerStatusReadyToPlay && _player.currentItem.status == AVPlayerItemStatusReadyToPlay) {
[_player seekToTime:time toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero completionHandler:^(BOOL finished) {
[_player play];
}];
} else {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self playAt:time];
});
}
}