首页 文章

如何在下一页上更改AVAsset的URL并在没有内存问题iOS的情况下转到上一页

提问于
浏览
0

我正在构建一个应用程序,场景是这样的:

我有3个视图控制器VC1,VC2,VC3 .

scenario1我在VC2上有一个AVPlayer,它使用保存在userDefaults中的“NSURL”来播放视频 . 让我们说这个url的关键是“videoURL” . 现在如果我弹出VC2并返回VC1,dealloc()获取调用,一切都被取消分配,视频停止播放 . 所以,如果我在VC1上更改“videoURL”,然后将VC2推到导航堆栈上,我会得到一个新的AVPlayer,前一个被释放 . 到现在为止没有问题 .

scenario2如果我在VC2上更改“videoURL”,我会使用“replaceCurrentItemWithPlayerItem”来播放一个新的playerItem来播放一个新的视频 . 这里也没有问题 .

scenario3现在,如果我将VC3推入堆栈,如果我回到VC3,我不知道如何播放新的URL . 当我按下VC3时,即使我在推送VC3之前将AVPlayer设置为nil,视频也不会停止播放 . 当我停止视频并推送VC3时,我面临着内存问题 .

实现scenario3的正确方法是什么?

2 回答

  • 0

    您将不得不添加逻辑来查看控制器2的viewWillDisappear方法以停止和释放AVPlayer,并移动创建AVPlayer的逻辑并启动它来播放viewWillAppear(这样当您弹出视图控制器3并返回查看时控制器2你可以再次播放视图控制器2的视频 . )

    你如何做到这一点取决于你如何管理AVPlayer . 发布设置AVPlayer的VC2代码,并在VC2的层次结构中安装其回放层 . (编辑原始问题以包含该信息 . 不要在评论中发布代码 . 这几乎是不可读的 . )

  • 0

    这是我为scenario3做的事情:

    -(void)goToNextPage
    {
    //This stops the video....
     [player replaceCurrentItemWithPlayerItem:nil];
    }
    

    现在我正在创建一个委托 . 所以现在VC2充当VC3的委托 . 所以当我在VC3上时,我编写了一个代码来生成一个新的Url,并将其传递给VC2中的一个属性 .

    所以我得出结论,只要VC2加载到内存中,我就不需要在VC2中解除分配AVPlayer . 同时,也不需要删除与之关联的观察者 .

    这是AVPlayer及其观察者的完整演示 . 我相信它将帮助每个开始使用AVFoundation和观察者的人 .

    // VC1

    -(IBAction)gotoPlayer:(id)sender
    {
    
      PlayerViewController *playerVC = [self.storyboard instantiateViewControllerWithIdentifier:@"PlayerViewController"];
      [self.navigationController pushViewController:playerVC animated:YES];
    }
    

    //VC2.h

    @interface PlayerViewController : UIViewController<ChangeUrlDelegate>
    @property (nonatomic,strong) NSURL *url;
    
    -(void)playWithURL:(NSURL*)url_;
    
    @end
    

    //VC2.m

    -(void)viewDidLoad
    {
        [self setPlayerDataOnPageArrival];
    }
    
    
    -(void)viewDidAppear:(BOOL)animated
    {
     if(self.url)
        [self playWithURL:self.url];
     else{
          NSString *path = [[NSBundle mainBundle]pathForResource:@"sample_mpeg4" ofType:@"mp4"];
          PlayerSource *source_ = [[PlayerSource alloc]initWithURL:[[NSURL alloc] initFileURLWithPath:path]];
          [self playWithURL:source_.sourceURL];
        }
    }
    
    
    -(void)dealloc
    {
    
      NSLog(@"In playerViewController dealloc");
      [playerItem_ removeObserver:self forKeyPath:@"status"];
      [player_ removeTimeObserver:self.timeObserver];
      [[NSNotificationCenter defaultCenter]removeObserver:self   name:self.itemEndObserver object:playerItem_];
    }
    
    
    #pragma mark ChangeURLViewController delegate methods
    
    -(void)newURL:(NSURL *)url_
    {
      self.url = url_;
    }
    
    
    #pragma mark player methods
    
    -(void)setPlayerDataOnPageArrival{
    
    NSString *path = [[NSBundle mainBundle]pathForResource:@"sample_mpeg4" ofType:@"mp4"];
    PlayerSource *source_ = [[PlayerSource alloc]initWithURL:[[NSURL alloc] initFileURLWithPath:path]];
    self.url = source_.sourceURL;
    asset_ = [AVAsset assetWithURL:self.url];
    
    playerItem_ = [AVPlayerItem playerItemWithAsset:asset_];
    NSLog(@"observer added");
    [playerItem_ addObserver:self forKeyPath:@"status" options:0 context:nil];
    
    player_ = [AVPlayer playerWithPlayerItem:playerItem_];
    playerLayer = [AVPlayerLayer playerLayerWithPlayer:player_];
    
    }
    
    
    -(void)playWithURL:(NSURL*)url_{
    
    [playerLayer setFrame:self.playerView.frame];
    
    if(self.playerView.layer.sublayers.count == 0)
        [self.playerView.layer addSublayer:playerLayer];
    else{
    
        AVPlayerItem *newPlayerItem_ = [AVPlayerItem playerItemWithURL:url_];
        [player_ replaceCurrentItemWithPlayerItem:newPlayerItem_];
    
        NSLog(@"rate--->%f",player_.rate);
        if(player_.rate == 0 && player_.status == 1)
            player_.rate = 1;
        }
    }
    
    
    -(void)addPlayerItemTimeObserver{
    
    CMTime interval = CMTimeMakeWithSeconds(0.01,NSEC_PER_SEC);
     //   __weak PlayerViewController *weakSelf = self;
        self.timeObserver = [player_ addPeriodicTimeObserverForInterval:interval queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {
    
        //NSLog(@"in addPlayerItemTimeObserver");
    
        CGFloat currentTime = CMTimeGetSeconds(time);
        NSLog(@"currentTime--->%f",currentTime);
        }];
    }
    
    
    -(void)addItemEndObserverForPlayerItem{
    
    //When playback completes,an AVPlayerItem posts a notification called "AVPlayerItemDidPlayToEndTimeNotification"
    
    self.itemEndObserver = AVPlayerItemDidPlayToEndTimeNotification;
    
    [[NSNotificationCenter defaultCenter]addObserverForName:self.itemEndObserver object:nil queue:NULL usingBlock:^(NSNotification * _Nonnull note) {
    
        NSLog(@"in item end observer");
        }];
    }
    
    
    
    #pragma mark player status observer
    
    -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{
    
    NSLog(@"In observer");
    
    if (playerItem_.status == AVPlayerItemStatusReadyToPlay) {
    
        NSLog(@"success");
        [self addPlayerItemTimeObserver];
        [self addItemEndObserverForPlayerItem];
        [player_ play];
    }
    
    else if(player_.status == AVPlayerItemStatusFailed){
    
        NSLog(@"failed");
    }
    
    else if(player_.status == AVPlayerItemStatusUnknown){
    
        NSLog(@"Unknown");
        }  
    }
    
    #pragma mark action methods
    
    -(IBAction)goToNextPage:(id)sender{
    
    [player_ replaceCurrentItemWithPlayerItem:nil];
    ChangeURLViewController *changeUrlVC_ = [self.storyboard instantiateViewControllerWithIdentifier:@"ChangeURLViewController"];
    changeUrlVC_.delegate=self;
    self.url = nil;
    [self.navigationController pushViewController:changeUrlVC_ animated:YES];
    
    }
    
    
    -(IBAction)changeURL:(id)sender{
    
    NSString *path = [[NSBundle mainBundle]pathForResource:@"sample_mpeg4" ofType:@"mp4"];
    PlayerSource *source_ = [[PlayerSource alloc]initWithURL:[[NSURL alloc] initFileURLWithPath:path]];
    [self playWithURL:source_.sourceURL];
    }
    

    //VC3.h

    @protocol ChangeUrlDelegate <NSObject>
    
      -(void)newURL:(NSURL*)url_;
    
    @end
    
    @interface ChangeURLViewController : UIViewController
    
      @property (weak,nonatomic) id <ChangeUrlDelegate> delegate;
    
    @end
    

    //VC3.m

    -(void)dealloc{
    
        NSLog(@"In changeURL dealloc");
    }
    
    -(IBAction)changeURLAction:(id)sender{
    
         NSString *path = [[NSBundle mainBundle]pathForResource:@"sample_mpeg4" ofType:@"mp4"];
        PlayerSource *source_ = [[PlayerSource alloc]initWithURL:[[NSURL alloc] initFileURLWithPath:path]];
        NSLog(@"delegate---->%@",self.delegate);
        [self.delegate newURL:source_.sourceURL];
        [self.navigationController popViewControllerAnimated:YES];
    
        }
    

    注意:请注意,您应该在每个视图控制器中使用dealloc(),并且应该超时调用视图控制器从内存中删除(弹出导航堆栈) .

相关问题