从 NavigationController 中移除 ViewController 后 AVPlayer 继续播放

Posted

技术标签:

【中文标题】从 NavigationController 中移除 ViewController 后 AVPlayer 继续播放【英文标题】:AVPlayer continues to play after ViewController is removed from NavigationController 【发布时间】:2011-11-09 23:16:43 【问题描述】:

所以我在我的项目中使用了 ARC,当我添加一个 AVPlayerLayer 时,它工作得很好而且很漂亮,但是当我从我的 UINavigationItem 弹出 UIViewController 时,视频会继续在后台播放。有谁知道你会如何处理这个?我只是忽略了这件事似乎很容易。这是我最初实例化的代码。

self.currentItem = [[AVPlayerItem alloc] initWithURL:url];

self.player = [[AVPlayer alloc]initWithPlayerItem:self.currentItem];
self.avPlayerLayer = [AVPlayerLayer playerLayerWithPlayer:player];

self.avPlayerLayer.bounds = self.view.bounds;
self.avPlayerLayer.frame = CGRectMake(0,55, 1024, 670);

self.view.backgroundColor = [UIColor clearColor];

[self.view.layer addSublayer:avPlayerLayer];

这也是我定义属性的方式。

@property (strong) AVPlayer *player;
@property (strong) AVPlayerLayer *avPlayerLayer;
@property (strong) AVPlayerItem *currentItem;

也许这也是完全错误的。我不确定何时使用(强)与(弱)。任何情况都提前感谢您的帮助。

【问题讨论】:

在弹出视图控制器之前,您是否尝试过将其所有子视图设置为 nil? self.view = nil; [nc popViewControllerAnimated:TRUE];视频停止,然后从头重新加载并在后台重新开始播放。 我的 AVPlayer 在 tableviewcell..当我弹出到以前的 viewcontroller 时如何停止它?? 【参考方案1】:

如果 avPlayerLayer 是唯一与 avPlayer 交互的类,则无需使用用于呈现它的类中的属性来维护对它的引用(除非该类在您的代码之外使用它)共享)。事实上,这可能就是它没有按您预期的方式工作的原因。

剪辑继续播放的原因(我认为)是因为播放器没有被释放。您创建它,使用您的类中的 strong 属性拥有它,而不是由您将其交给的 AVPlayerLayer 类再次拥有它。因此,当 AVPlayerLayer 被释放时,AVPlayer 失去了一个所有者。但它仍然有一个所有者(你的班级),所以它不会被释放,它会继续播放。这里的解决方案是完全摆脱 *avPlayer 的所有属性。你不需要它。创建 AVPlayer 并将其传递给 AVPlayerLayer。这应该就是我们所需要的。

您可以做的其他事情可能会解决该行为但不能解决问题,请致电:

[avPlayer pause]

在你的 AVPlayerLayer 的 dealloc 方法中。

Re:强引用与弱引用:强引用意味着所有权。由于 ARC 正在管理内存,它会执行您以前在代码中或在属性中完成的所有 [对象保留] 和 [对象释放],即:

@property (retain) NSObject *iAmRetainedWhenProperyIsAssigned;

所以现在有了 ARC,我们简单的用户不会在代码中或在定义属性时使用诸如保留或释放之类的词。但我们仍然设计软件。 ARC 很聪明,但还不够聪明,无法推断出我们正在定义的关系的架构含义。仍然需要告知类“拥有”对属性所指对象的引用。用最基本的术语来说,这减少了我们:

(强)对 ARC 的意义与(保留)对 ARC 之前的属性(拥有/保留)的意义

(弱)对 ARC 意味着(分配)对 pre-ARC 的属性(不拥有/不保留)的意义

【讨论】:

感谢您的建议。明天我会尝试一些,看看我想出了什么。我最初将 AVPlayer 作为一个 iVar,但当我开始遇到问题时,我切换了它。 AVPLayer 类也没有 stop 属性。这仅适用于我在文档中阅读的 AVAudioPlayer 类。无论如何,再次感谢您花时间写出如此详细的帖子。 将 [avPlayer stop] 编辑为 [avPlayer pause]。我误以为 AVPLayerLayer 是自己的子类,没想到是 CALayer 子类。 据我了解,释放和释放都是由 ARC 管理的,你甚至不能调用这些函数。有错吗? 是的,如果我尝试对特定变量/属性调用 dealloc,它会给我一条错误消息,指出 ARC 禁止显式解除分配。 所以我最终只是暂停了视频。还没有把它放在设备上,看看它对内存的实际管理情况如何,但当我回到带有不同视频的页面时,它似乎重新加载得很好。【参考方案2】:

也许你没有暂停。这样做,然后删除层并取消player

[player Pause];
[player removefromsuperlayer];
player = nil;

【讨论】:

不应该是(至少从今天开始)[avPlayerLayer removefromsuperlayer]。至少这相当于我从 Swift 中看到的。 AVPlayer 不提供 removefromsuperlayer 方法。 我的 AVPlayer 在 tableviewcell..当我弹出到以前的 viewcontroller 时如何停止它??【参考方案3】:

当你想停止加载一个 AVPlayerItem 时,使用 AVQueuePlayer 的 removeAllItems 然后重新初始化它。

  [self.avPlayer removeAllItems];
  self.avPlayer = [AVQueuePlayer playerWithURL:[NSURL URLWithString:@""]];
  self.avPlayer = nil;

这将停止加载当前项目——这是我发现的唯一方法。

【讨论】:

以上是关于从 NavigationController 中移除 ViewController 后 AVPlayer 继续播放的主要内容,如果未能解决你的问题,请参考以下文章

从 fetchedResultsController fetchedObjects 中移除一个对象

从 NavigationController 后退按钮返回多个 ViewController

如何从 UITextField 中移除焦点?

如何观察 NSManagedObject 是不是从 managedObjectContext 中移除

从 UIViewController 切换到 navigationController 内的其他 ViewController

为啥业务逻辑应该从 JSP 中移出?