iOS AVPlayerViewController не отображает элементы управления воспроизведением

Любая идея, почему я могу заставить свой класс AVPlayerViewController воспроизводить контент, но не могу заставить его отображать элементы управления воспроизведением? Плеер загружает контент как положено, но не более того.

В моем классе MediaPlayerViewController.m у меня есть:

#pragma mark - Player
- (void)setupPlayer{

    // Sample URLs to use either a local file or streaming URL
    NSURL *url = [[NSBundle mainBundle] URLForResource:@"Besan" withExtension:@"mp4"];
    //url = [NSURL URLWithString:@"http://www.youtube.com/watch?v=qcI2_v7Vj2U"];

    // Create an instance of the AVPlayer object
    self.player = [AVPlayer playerWithURL:url];


    // Keep an eye on the status of our player
    [self.player addObserver:self forKeyPath:@"status" options:0 context:nil];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{

    if (object == self.player && [keyPath isEqualToString:@"status"]) {
        if (self.player.status == AVPlayerStatusFailed){
            NSLog(@"AVPlayer setup failed");
        } else if (self.player.status == AVPlayerStatusReadyToPlay) {
            NSLog(@"AVPlayer is ready to play");
            [self.player play];
        }
    }
}

person R Brennan    schedule 05.11.2014    source источник
comment
У меня тоже есть эта проблема. Оказывается, когда вы удаляете методObservValueForKeyPath, появляются элементы управления. Сейчас ищу обходной путь...   -  person Aaron Vegh    schedule 09.12.2014


Ответы (3)


Это не ошибка фреймворка, а связанная с тем, как работает наблюдение за ключом и значением. Осуществляя

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context

в вашем ViewController вы переопределяете реализацию AVPlayerViewController. Решение состоит в том, чтобы добавить контекст при регистрации наблюдателя:

static NSString* const AVPlayerStatusObservationContext = @"AVPlayerStatusObservationContext";

затем зарегистрируйте своего наблюдателя следующим образом

[self.player addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionPrior context:(__bridge void *)(AVPlayerStatusObservationContext)];

и сделайте следующее вObservValueForKeyPath

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{

    if (context == (__bridge void *)(AVPlayerStatusObservationContext))
    {
        NSLog(@"Change Object %@, Value %@",object,change);
    } else {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}
person holtmann    schedule 20.03.2015
comment
В документации указано, что не следует создавать подклассы AVPlayerViewController. Переопределение методов этого класса не поддерживается и приводит к неопределенному поведению. Думаю, эта проблема — одна из причин, по которой они не хотят, чтобы мы это делали :) - person fluidsonic; 18.12.2015

Как я указал в своем комментарии к вопросу, элементы управления исчезают, когда вы реализуете - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context в AVPlayerViewController. Это может быть пустая реализация; элементы управления плеером не отображаются. Это должно быть ошибка фреймворка, и я шокирован (шокирован!), что Apple этого не заметила.

Мое решение состоит в том, чтобы реализовать наблюдателя в другом классе. Я создал класс VideoObserver, унаследованный от NSObject, и настроил его так:

@implementation VideoObserver

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if ([keyPath isEqualToString:@"status"]) {
        NSLog(@"Change: %@", change);
    }
}
@end

В AVPlayerViewController я устанавливаю наблюдателя как свойство, а затем использую его, чтобы начать наблюдение:

self.observer = [VideoObserver new];

NSURL * videoURL = [NSURL URLWithString:@"http://www.quirksmode.org/html5/videos/big_buck_bunny.mp4"];
self.videoPlayer = [AVPlayer playerWithURL:videoURL];

[self.videoPlayer addObserver:self.observer forKeyPath:@"status" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial context:nil];

Я выложил свой демонстрационный проект на Github.

person Aaron Vegh    schedule 09.12.2014
comment
Спасибо, Аарон. Ваш обходной путь работает, спасибо за ответ. - person David; 11.09.2015

Возможно, смешно, но убедитесь, что элементы управления на самом деле не прячутся под TabBar. Я еще не нашел решения этой проблемы, но эта мелочь меня огорчила, и мне потребовалось немного времени, чтобы осознать ее, но на самом деле элементы управления все еще были там.

person matthewsheets    schedule 14.03.2015