Подтвердить что ты не робот

AVPlayerItem не может быть связан с несколькими экземплярами AVPlayer в iOS 8.4

После обновления до iOS 8.4 я получаю печально известное исключение с MPMoviePlayerController, которое гласит:

AVPlayerItem не может быть связан с несколькими экземплярами AVPlayer

Я видел несколько обходных решений, которые состоят в основном из повторной инициализации игрока, прежде чем повторно использовать его. Тем не менее, для меня авария не возникает, когда я пытаюсь воспроизвести новое видео, но, когда я выключу полноэкранный режим для проигрывателя, повернув его в портретный режим.

Это мой код:

@implementation MoviePlayerViewController

-(void)viewDidLoad
{
    [super viewDidLoad];

    self.moviePlayer.controlStyle = MPMovieControlStyleEmbedded;

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(moviePlayerWillEnterFullscreenNotification:) name:MPMoviePlayerWillEnterFullscreenNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(moviePlayerWillExitFullscreenNotification:) name:MPMoviePlayerWillExitFullscreenNotification object:nil];
}

- (void) moviePlayerWillEnterFullscreenNotification:(NSNotification*)notification
{
    [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deviceOrientationDidChange) name:UIDeviceOrientationDidChangeNotification object:nil];
}

- (void) moviePlayerWillExitFullscreenNotification:(NSNotification*)notification
{
    [[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil];
}

- (void)deviceOrientationDidChange
{
    UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
    if (orientation == UIDeviceOrientationPortrait) {
        [self.moviePlayer setFullscreen:NO animated:YES];
    }
}

@end

Изменение в полноэкранном режиме происходит в UIViewController, у которого MoviePlayerViewController есть как subview:

-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
    if (!self.moviePlayerViewController.moviePlayer.fullscreen &&
        UIInterfaceOrientationIsPortrait(fromInterfaceOrientation)) {
            [self.moviePlayerViewController.moviePlayer setFullscreen:YES animated:YES];
    }
}

Нет проблем при входе или выходе из полноэкранного режима с помощью полноэкранного режима в проигрывателе. Также я могу полностью повернуть плеер в полноэкранный режим. Однако, когда я пытаюсь повернуть его из полноэкранного (то есть от пейзажа к портрету), я получаю исключение, похоже, в строке:

[self.moviePlayer setFullscreen:NO animated:YES];

Вот моя трассировка стека при возникновении исключения:

Thread : Fatal Exception: NSInvalidArgumentException
0  CoreFoundation                 0x00000001865e02d8 __exceptionPreprocess
1  libobjc.A.dylib                0x0000000197f3c0e4 objc_exception_throw
2  AVFoundation                   0x0000000184db4b50 -[AVPlayerItem _attachToFigPlayer]
3  AVFoundation                   0x0000000184da7770 -[AVPlayer _attachItem:andPerformOperation:withObject:]
4  AVFoundation                   0x0000000184dc8f00 -[AVQueuePlayer insertItem:afterItem:]
5  MediaPlayer                    0x00000001889d1d30 -[MPQueuePlayer insertItem:afterItem:]
6  MediaPlayer                    0x000000018893de7c -[MPAVQueueCoordinator _syncPlayerItems]
7  MediaPlayer                    0x000000018893d8a4 -[MPAVQueueCoordinator _syncItems]
8  MediaPlayer                    0x000000018893c68c -[MPAVQueueCoordinator reloadItemsKeepingCurrentItem:]
9  MediaPlayer                    0x000000018899fd38 -[MPAVPlaylistManager setPlaylistFeeder:startIndex:keepPlaying:]
10 MediaPlayer                    0x000000018899fb4c __67-[MPAVPlaylistManager reloadWithPlaybackContext:completionHandler:]_block_invoke
11 MediaPlayer                    0x000000018889fa5c -[MPArrayQueueFeeder reloadWithPlaybackContext:completionHandler:]
12 MediaPlayer                    0x000000018899f9b4 -[MPAVPlaylistManager reloadWithPlaybackContext:completionHandler:]
13 MediaPlayer                    0x00000001888b7550 -[MPAVController reloadWithPlaybackContext:completionHandler:]
14 MediaPlayer                    0x000000018888d114 -[MPMoviePlayerControllerNew _prepareToPlayWithStartIndex:]
15 MediaPlayer                    0x000000018888a988 -[MPMoviePlayerControllerNew _moviePlayerDidBecomeActiveNotification:]
16 CoreFoundation                 0x00000001865862c4 __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__
17 CoreFoundation                 0x00000001864c3450 _CFXNotificationPost
18 Foundation                     0x00000001873f2a80 -[NSNotificationCenter postNotificationName:object:userInfo:]
19 MediaPlayer                    0x000000018888d530 -[MPMoviePlayerControllerNew _postNotificationName:object:userInfo:]
20 MediaPlayer                    0x000000018888d494 -[MPMoviePlayerControllerNew _postNotificationName:object:]
21 MediaPlayer                    0x00000001888878dc -[MPMoviePlayerControllerNew setFullscreen:animated:]
22 myApp                          0x000000010004ddf8 -[MoviePlayerViewController deviceOrientationDidChange] (MoviePlayerViewController.m:36)
23 CoreFoundation                 0x00000001865862c4 __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__
24 CoreFoundation                 0x00000001864c3450 _CFXNotificationPost
25 Foundation                     0x00000001873f2a80 -[NSNotificationCenter postNotificationName:object:userInfo:]
26 UIKit                          0x000000018b059b34 -[UIDevice setOrientation:animated:]
27 UIKit                          0x000000018b0597f0 -[UIApplication handleEvent:withNewEvent:]
28 UIKit                          0x000000018b059080 -[UIApplication sendEvent:]
29 UIKit                          0x000000018b0c52c4 _UIApplicationHandleEvent
30 GraphicsServices               0x000000018fdc9194 _PurpleEventCallback
31 GraphicsServices               0x000000018fdc8c84 PurpleEventCallback
32 CoreFoundation                 0x0000000186597a54 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__
33 CoreFoundation                 0x00000001865979b4 __CFRunLoopDoSource1
34 CoreFoundation                 0x0000000186595934 __CFRunLoopRun
35 CoreFoundation                 0x00000001864c12d4 CFRunLoopRunSpecific
36 GraphicsServices               0x000000018fdc76fc GSEventRunModal
37 UIKit                          0x000000018b0bef40 UIApplicationMain
38 myApp                          0x000000010002b2dc main (main.m:16)
39 libdyld.dylib                  0x00000001985e6a08 start
4b9b3361

Ответ 1

Решение:

Не используйте MPMoviePlayerController, извините. Вместо этого вместо Refactor использовать AVPlayerViewController. Это более современный API; тот, который вы используете, устарел, поэтому он не шокирует, что он имеет странный таинственный крах в новой версии iOS.

Ответ 2

У меня была проблема, которая кажется вам знакомой, но может быть или не быть точно такой же. У меня было несколько контроллеров просмотра, и я организовал один контроллер просмотра, чтобы приостановить его фильм, чтобы другой мог играть. Но когда устройство повернулось, стандартный контроллер панели вкладок iOS, который я использовал, загрузил бы другие контроллеры представлений (вызывающие viewDidLoad, я считаю) для любых других вкладок на панели вкладок, если они еще не были загружены. Я не ожидал такого поведения, поскольку вкладки никогда не были выбраны мной. Мой код для загрузки фильма был в viewDidLoad, и поэтому он пытался начать воспроизведение другого фильма на другом контроллере представления, которого никогда не просили "появиться". Мне потребовалось некоторое время, чтобы понять, что происходит, потому что два контроллера представления наследуются от одного и того же базового класса, и он выглядел как правильный объект в отладчике, пока я не посмотрел ближе.

Если используется память, я переместил код для загрузки и начала воспроизведения моих фильмов в viewWillAppear, чтобы он не выполнялся, если вкладка не была выбрана. Затем, когда устройство повернуто, а другой контроллер просмотра внезапно загружен, он не имеет побочных эффектов. Странно видеть, что это так.