Остановить воспроизведение элемента AVPlayer и заменить новым

В моем приложении есть табличное представление, которое при выборе открывает новый контроллер представления и использует AVPlayer, чтобы начать воспроизведение переданного ему URL-адреса. Однако, когда они возвращаются и выбирают новый элемент для воспроизведения, я не могу заставить его остановить первый и начать воспроизведение второго. Какие-либо предложения?

- (void)viewWillAppear:(BOOL)animated {
        [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];

          
           [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
           [self becomeFirstResponder];
           NSURL *newURL = [NSURL URLWithString:_entry.articleUrl];
          
           AVPlayer *player = [AVPlayer playerWithURL:newURL];
    
            _controller = [[AVPlayerViewController alloc]init];
            _controller.player = player;
        
            
           
            // show the view controller
            [self addChildViewController:_controller];
            [self.view addSubview:_controller.view];
            _controller.view.frame = self.view.frame;
    [player play];
   
    self.title = _entry.articleTitle;
   
    

    [super viewWillAppear:YES];
}

person user717452    schedule 02.03.2021    source источник
comment
Вам нужно следить за игроком и использовать [player replaceCurrentItemWithPlayerItem:[AVPlayerItem playerItemWithURL:url]], чтобы изменить текущий элемент, а затем [player play], чтобы начать воспроизведение.   -  person skaak    schedule 02.03.2021
comment
@skaak Я добавил строку кода replaceCurrentItem, и она по-прежнему делает то же самое. Продолжает воспроизводить оригинал и добавляет второй.   -  person user717452    schedule 02.03.2021
comment
Да, но вам не следует заново создавать проигрыватель, а использовать его повторно. Вероятно, вам нужен синглтон или что-то подобное для решения этой проблемы.   -  person skaak    schedule 02.03.2021
comment
Я пробовал все это @skaak и ничего не работает   -  person user717452    schedule 02.03.2021


Ответы (1)


РЕДАКТИРОВАТЬ Я изменил это, чтобы возвращать проигрыватель, когда вы отправляете сообщение startPlaying — таким образом очень легко обновить ваш контроллер, как обсуждалось в комментариях.

Вот схема, которая может сработать - не проверял, но, надеюсь, решит вашу проблему.

Заголовочный файл должен содержать

@interface MyPlayer : NSObject

// Start playing some URL and return the player
+ ( AVPlayer * ) startPlaying:( NSURL * ) url;

@end

И в файле m, очень похожем на предыдущий,

#import <AVKit/AVKit.h>
#import "MyPlayer.h"

@interface MyPlayer ()

@property (nonatomic,strong) NSObject * playerLock;
@property (nonatomic,strong) AVPlayer * player;

@end

@implementation MyPlayer

// Initialise
- ( id ) init
{
    self = super.init;

    if ( self )
    {
        self.playerLock = NSObject.new;
    }

    return self;
}

// Return singleton
+ ( MyPlayer * ) myPlayer
{
    static MyPlayer * mp;
    static dispatch_once_t t;

    dispatch_once ( & t, ^ {

        mp = [[MyPlayer alloc] init];

    } );

    return mp;
}

// Start playing some URL and return the player
+ ( AVPlayer * ) startPlaying:( NSURL * ) url
{
    MyPlayer * mp = MyPlayer.myPlayer;
    AVPlayer * player;

    @synchronized ( mp.playerLock )
    {
        if ( mp.player )
        {
            // Replace
            [mp.player replaceCurrentItemWithPlayerItem:[AVPlayerItem playerItemWithURL:url]];
        }
        else
        {
            // Create a new player
            mp.player = [AVPlayer playerWithURL:url];
        }
        
        player = mp.player;
    }

    // Start playing on a background thread
    dispatch_async ( dispatch_get_global_queue ( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 ), ^ {

        @synchronized ( mp.playerLock )
        {
            // Start playing
            mp.player.play;
        }

    } );

    return player;
}

@end

Просто отправьте сообщение [MyPlayer startPlaying:url];, чтобы воспроизвести URL-адрес, как и раньше, но на этот раз он вернет проигрыватель.

Итак, в вашем коде вы можете сделать что-то вроде

_controller.player = [MyPlayer startPlaying:url];
person skaak    schedule 02.03.2021
comment
Это работает для воспроизведения и замены звука при выборе нового, но я теряю элементы управления воспроизведением. Должен ли я помещать это как единственный код в viewWillAppear или все еще разрешать некоторые из фреймворков контроллера? - person user717452; 03.03.2021
comment
Хороший! Попробуйте следующее: где вы делаете _controller.player = player, замените его на _controller.player = MyPlayer.myPlayer.player и также выставьте свойство player в файле заголовка. - person skaak; 03.03.2021
comment
На самом деле, есть очень изящный способ решить эту проблему. Я отредактирую свой ответ, чтобы отразить это. - person skaak; 03.03.2021
comment
FWIW, все блокировки и потоки здесь, вероятно, излишни для AVPlayer, но хорошо иметь их позже, если вы, например. хотите показать какое-то сообщение во время буферизации или иным образом контролировать проигрыватель. - person skaak; 03.03.2021
comment
Спасатель! Я принял ответ. - person user717452; 03.03.2021