Unable to simultaneously satisfy constraints Warnings with AVPlayerViewController embedded in storyboard

依然范特西╮ 提交于 2019-11-27 21:50:30

In fact, I think it's bug on Apple side.

I found a workaround : set showsPlaybackControls to YES after the AVPlayerViewController.player have been set.

I modify your sample with the following lines and no more Constraint error appears :

@interface ViewController ()

@property(weak, nonatomic) AVPlayerViewController * playerViewController;


@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    NSString *path = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"mp4"];
    NSURL *url = [[NSURL alloc] initFileURLWithPath: path];
    AVPlayer * player = [AVPlayer playerWithURL:url];

    self.playerViewController.player = player;
    self.playerViewController.showsPlaybackControls = YES;
}


- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([segue.identifier isEqualToString:@"AVPlayerSegue"]) {
        self.playerViewController = segue.destinationViewController;
    }
}


@end

Please note that the file test.mp4 have been added to the project.

I downloaded your code and took a look at it. You are not doing anything wrong. The fact that you can uncheck "Shows Playback Control" seems to indicate that the problem lies with the AVKit framework. I've even tried setting the value to false in the XIB file and then calling [self setShowsPlaybackControls:YES]; after viewDidAppear: with the same results. This is most definitely an Apple bug and you should raise a bug report.

In my case I allow on iPhones only the portrait mode while I want the AVPlayerViewController to have all directions.

In AppDelegate I have code that looks like this:

public func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> UIInterfaceOrientationMask {

    if self.window?.rootViewController?.presentedViewController is AVPlayerViewController {

        return .All
    }
    return Device.current.contains(.iPhone) ? [.Portrait, .PortraitUpsideDown] : .All
}

When AVPlayerViewController is presented modally, rotated to landscape and dismissed I'll get a very smiler error stack that some constraints broke.

To workaround I added this code to my RootViewController, which also presents any instance of AVPlayerViewController in my application:

public override func dismissViewControllerAnimated(flag: Bool, completion: (() -> Void)?) {

    if let playerViewController = self.presentedViewController as? AVPlayerViewController {

        playerViewController.showsPlaybackControls = false
    }

    super.dismissViewControllerAnimated(flag, completion: completion)
}

Basically I'm catching the moment when the user taps on the dismiss button and use the workaround found in original question post.

Unfortunately this bug is still present in ios 10.1. Anyway, I have observed that if I present the view controller with the seekTime set to 0, the bug is not present. So, my solution was to pause the player, retain the currentTime, seek the player to 0, present the controller and on the completion do the following: seek to the retained time and play again.

AVPlayer *player;
AVPlayerViewController *avPlayerController;
CMTime currentTime;

- (void)viewDidLoad {
    [super viewDidLoad];

    NSURL *videoURL = [NSURL URLWithString:@"https://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"];
    player = [AVPlayer playerWithURL:videoURL];
    AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:player];
    [self.playerView.layer addSublayer:playerLayer];
    playerLayer.frame = self.playerView.bounds;
    avPlayerController = [[AVPlayerViewController alloc] init];
    avPlayerController.player = player;

}

- (IBAction)fullScreen:(id)sender {
    [player pause];
    currentTime = player.currentTime;
    [player seekToTime:CMTimeMake(0, 1)];

    [self presentViewController:avPlayerController animated:YES completion:^{
        [avPlayerController.player seekToTime:currentTime];
        [avPlayerController.player play];
    }];
}

I realised this is happening when you try to present the same AVPlayerViewController instance (using a strong reference property) the second, third...etc time and the player controls are not reset (i.e. the progress is not at the beginning).

Actually, if you are facing the same scenario, before tapping "Done" try to drag the progress bar to the beginning and present AVPlayerViewController again. Then the auto layout issue should disappear!

So basically the Autolayout issue (Apple issue by the way) can be fixed if you reset the controls before dismissing AVPlayerViewController. But, what if you want to present the same video? In my case I want to keep the reference to AVPlayerItem:

@property (strong, nonatomic) AVPlayerItem *playerItem;

But I don't want this crash to happen:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'An AVPlayerItem cannot be associated with more than one instance of AVPlayer'
*** First throw call stack:
(0x184035900 0x1836a3f80 0x18a254958 0x18a23fc14 0x100054a2c 0x188d5fe50 0x188d5fdcc 0x188d47a88 0x188d5f6e4 0x188d18294 0x188d58820 0x188d57e1c 0x188d284cc 0x188d26794 0x183fecefc 0x183fec990 0x183fea690 0x183f19680 0x185428088 0x188d90d90 0x1000eea78 0x183aba8b8)
libc++abi.dylib: terminating with uncaught exception of type NSException

So my workaround was to create a copy of the AVPLayerItem every time I push AVPlayerViewController. With that way, the crash and auto layout issue are gone. However, the video is reset every time you push the player.

AVPlayerViewController *playerViewController = [AVPlayerViewController new];
playerViewController.player = [[AVPlayer alloc] initWithPlayerItem:self.playerItem.copy];

This warning is saying that you have used one constraint extra that didn't need to be use.

ToolBarHeight by default is 44 for all iphone devices here you have used height constraint for UIToolBar. So the Toolbar Height Constraint is extra here , Remove this constraint the warning will be remove automatically

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!