如何修复 AVPlayer 的视图控制器层次结构?

Posted

技术标签:

【中文标题】如何修复 AVPlayer 的视图控制器层次结构?【英文标题】:How to fix view controller hierarchy for AVPlayer? 【发布时间】:2019-01-16 19:10:42 【问题描述】:

我有一个带有单人播放器和登录的 ios 应用程序。它应该像这样工作:

1) 运行应用程序 2) 登录 3) 登录后视频直接开始播放 4) 如果您退出视频,它应该询问您是否要退出 5) 如果没有应该继续播放流 6) 如果是,请退出应用程序 7) 如果用户再次登录而没有杀死应用程序,则应重复 2-7 中的步骤

但是,我的代码完成了除了最后一步之外的所有操作。如果用户注销并登录 - 它开始播放流 但是当您单击完成按钮并尝试退出视频时,它不起作用。视频保持全屏显示,并给出以下警告:

Warning: <AVPlayerViewController: 0x7f9fca08aa00> is trying to exit full screen, but is not in its view's window's view controller hierarchy. This results in undefined behavior. 

我对xcode ios和objectiveC真的很陌生,我的代码如下

- (void)viewDidLoad 

    NSLog(@"ChannelListingViewController::viewDidLoad(): Called...");
    [super viewDidLoad];

    self.check=1;

    NSLog(@"ChannelListingViewController::viewDidLoad(): Exiting...");


-(void) playVideo

    self.channelURL = [TulixAppGlobalConfig getUserSubscribedPlanChannels];


    NSURL *url = [[NSURL alloc] initWithString:[self.channelURL[1] getChannelHlsStreamURL]];
    self.player = [AVPlayer playerWithURL:url];

    // create a player view controller
    [self presentViewController:controller animated:YES completion:nil];
    self.controller.player = self.player;
    [self.player play];


-(void) viewDidAppear:(BOOL)animated


    self.controller = [[AVPlayerViewController alloc] init];

    NSLog(@"ChannelListingViewController::viewDidAppear(): Called...");
    if(self.check==0)
    
        NSLog(@" 0 checkvalue: %i",check);
        [self showLogoutConfirmationDialog];
    
    else
        self.check =0;
        NSLog(@" 1 checkvalue: %i",check);
        [self playVideo];

    

    [self spawnKeepAliveThread];
    NSLog(@"ChannelListingViewController::viewDidAppear(): Exiting...");


-(void) showLogoutConfirmationDialog

    void (^ptrFuncCompletionBlock)(void) = ^(void)      NSLog(@"ChannelListingViewController::showLogoutConfirmationDialog():GENERIC CALL BACK...");
    [self attemptToLogoutUser];
;
NSLog(@"ChannelListingViewController::showLogoutConfirmationDialog(): Called...");

UIAlertAction* alertActionYes = [UIAlertAction actionWithTitle:@"Yes" style:UIAlertActionStyleDefault
                                                         handler:^(UIAlertAction * action) 
                                                             //Do Some action here
                                                             NSLog(@"ChannelListingViewController::showLogoutConfirmationDialog:: Called for YES...");
                                                             self.check = 1;
                                                             NSLog(@" yes checkvalue: %i",check);
                                                             [self.activeAlterController dismissViewControllerAnimated:NO completion:ptrFuncCompletionBlock];
                                                             [self attemptToLogoutUser];
                                                         ];
UIAlertAction* alertActionNo = [UIAlertAction actionWithTitle:@"No" style:UIAlertActionStyleCancel
                                                          handler:^(UIAlertAction * action) 
                                                              NSLog(@"ChannelListingViewController::showLogoutConfirmationDialog:: Called for NO...");
                                                              [self playVideo];

                                                          ];

NSMutableArray* arrayAlertActions = [NSMutableArray arrayWithObjects:alertActionYes, alertActionNo, nil];
self.activeAlterController = [HelperUtility showMultiButtonDialogHavingTitle:@"Logout" withMessage:@"Are you sure you want to log out?" andAlertActions:arrayAlertActions];

[self presentViewController:self.activeAlterController animated:YES completion:nil];

NSLog(@"ChannelListingViewController::showLogoutConfirmationDialog(): Exit ");

我真的不明白为什么它在注销后不起作用并需要帮助。

【问题讨论】:

问题是播放器上的所有其他按钮都在工作。当我点击完成(退出)按钮时,它会暂停流并给出上面的警告。 友情提示:如果你的应用愿意提交到应用商店,可能会因为功能有限而无法通过审核。 @Mosbah 你说的功能有限是什么意思? 该错误通常表明您在视图层次结构中呈现全屏控制器,而该控制器无权访问“全屏”。基本场景是在控制器内呈现时推送到导航控制器内。它是需要全屏显示的导航控制器。你很可能有类似的情况。从错误的地方展示。 【参考方案1】:

您只需要将您的 avplayer 控制器与窗口视图相关联。而是只展示 avcontroller 添加以下行-

目标 C-

[self.view.window.rootViewController presentViewController:controller animated:YES completion:nil];

斯威夫特 5 -

view.window.rootViewController?.present(controller, animated: true)

【讨论】:

您好,我遇到了同样的问题,我尝试了上面的代码,但仍然遇到同样的问题。我的应用程序中有一个导航控制器和多个屏幕。我的导航层次结构中的一个视图控制器中有一个按钮,可以全屏播放视频,但是当我退出全屏时,它会一直让我回到导航控制器的第一个视图,有什么帮助吗?此外,播放视频的视图是滚动视图,我不确定这是否会有所不同。 @shant_01 我面临同样的问题。你找到解决办法了吗? 同样的问题。在导航堆栈中弹回一个视图控制器。

以上是关于如何修复 AVPlayer 的视图控制器层次结构?的主要内容,如果未能解决你的问题,请参考以下文章

如何从任何其他视图控制器获取具有视图控制器详细信息的视图层次结构?

如何直接通过点击通知警报打开隐藏在视图层次结构中的视图控制器

如何以模态方式将视图添加到不在视图层次结构中的另一个视图 iOS

切换标签栏项目时,UINavigationController 如何将其整个视图控制器表示层次结构保存在内存中?

如何在复杂的视图层次结构中呈现相机

视图层次结构未准备好