内存泄漏:AVplayerViewController

时间:2016-06-11 11:06:18

标签: ios memory-leaks avfoundation avplayer avplayerviewcontroller

当我们播放视频并返回父窗口时,我正面临内存泄漏。请参阅下面的分配工具读数截图。enter image description here每当我弹出视图控制器(显示视频)时,都会有一些与AVFoundation相关的对象保存内存。 有趣的是,所有这些对象的负责库都是AVFoundation。内存增加都不是由于APP中创建的对象造成的。这种流行框架存在一些问题的可能性非常小。我在网上看到了一些AVPlayerViewController的例子,但它们似乎有同样的问题。

有谁知道问题是什么/哪里?如果有人想要复制这个,那么他可以下载上面给出的任何2个项目。您必须在故事板中进行细微更改,才能使用导航控制器创建根视图控制器。

  • http://www.modejong.com/blog/post13_iOS8_SunSpot/index.html
  • https://github.com/coolioxlr/PageView-AVPlayer

    这就是我清理记忆的方式:

           -(void) dealloc{
    
               [self clearCurrentVideo];
    
            }
    
       -(void)clearCurrentVideo {
           [_playerItem removeObserver:self forKeyPath:@"status"];        
           [_currentVideoPlayerViewController.player removeObserver:self forKeyPath:@"rate"];
           [_currentVideoPlayerViewController.player pause];
           _currentVideoPlayerViewController.delegate=nil;
           _currentVideoPlayerViewController.player=nil;
          _playerItem=nil;
          _currentVideoPlayerViewController = nil;
       }
    

这是我加载视频资源的方式:

 -(void)playtheAsset:(AVAsset *)asset{
[asset loadValuesAsynchronouslyForKeys:@[@"playable"] completionHandler:
                 ^{
                     dispatch_async( dispatch_get_main_queue(),
                                    ^{

                                        [self loadTheAsset:asset withKeys:@[@"playable"]];
                                    });
                 }];
}


- (void)loadTheAsset:(AVAsset *)asset withKeys:(NSArray *)requestedKeys{

    /* Make sure that the value of each key has loaded successfully. */
    for (NSString *thisKey in requestedKeys)
    {
        NSError *error = nil;
        AVKeyValueStatus keyStatus = [asset statusOfValueForKey:thisKey error:&error];
        if (keyStatus == AVKeyValueStatusFailed)
        {

            //[self assetFailedToPrepareForPlayback:error];
            if([thisKey isEqualToString:@"playable"]){

                 [self showNetworkErrorLabel];

            }

            return;
        } else if ((keyStatus == AVKeyValueStatusLoaded) || ( keyStatus == AVKeyValueStatusLoading )){

            [self removeNetworkLabel ];

        }
       }

    /* Use the AVAsset playable property to detect whether the asset can be played. */
    if (!asset.playable)
    {
        /* Generate an error describing the failure. */
        NSString *localizedDescription = NSLocalizedString(@"Item cannot be played", @"Item cannot be played description");
        NSString *localizedFailureReason = NSLocalizedString(@"The assets tracks were loaded, but could not be made playable.", @"Item cannot be played failure reason");
        NSDictionary *errorDict = [NSDictionary dictionaryWithObjectsAndKeys:
                                   localizedDescription, NSLocalizedDescriptionKey,
                                   localizedFailureReason, NSLocalizedFailureReasonErrorKey,
                                   nil];
        NSError *assetCannotBePlayedError = [NSError errorWithDomain:@"StitchedStreamPlayer" code:0 userInfo:errorDict];

        NSLog(@"%@",assetCannotBePlayedError);
        [self showNetworkErrorLabel];
        /* Display the error to the user. */
        [self assetFailedToPrepareForPlayback:assetCannotBePlayedError];

        return;
    }

    /* At this point we're ready to set up for playback of the asset. */

    /* Stop observing our prior AVPlayerItem, if we have one. */
    if (_playerItem)
    {
        /* Remove existing player item key value observers and notifications. */

        [_playerItem removeObserver:self forKeyPath:@"status"];

        [[NSNotificationCenter defaultCenter] removeObserver:self
                                                        name:AVPlayerItemDidPlayToEndTimeNotification
                                                      object:_playerItem];

        [[NSNotificationCenter defaultCenter] removeObserver:self
                                                        name:AVPlayerItemPlaybackStalledNotification
                                                      object:_playerItem];


    }


    /* Create a new instance of AVPlayerItem from the now successfully loaded AVAsset. */
    _playerItem = [AVPlayerItem playerItemWithAsset:asset];

    /* Observe the player item "status" key to determine when it is ready to play. */
    [_playerItem addObserver:self
                  forKeyPath:@"status"
                     options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
                     context:AVPlayerDemoPlaybackViewControllerStatusObservationContext];

    /* When the player item has played to its end time we'll toggle
     the movie controller Pause button to be the Play button */
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(playerItemDidReachEnd:)
                                                 name:AVPlayerItemDidPlayToEndTimeNotification
                                               object:_playerItem];



       [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playerItemFailedToPlayToEndTime:) name:AVPlayerItemPlaybackStalledNotification object:_playerItem];



    // Remove the movie player view controller from the "playback did finish" notification observers
    // Observe ourselves so we can get it to use the crossfade transition
    [[NSNotificationCenter defaultCenter] removeObserver:_currentVideoPlayerViewController
                                                    name:kPlayerViewDismissedNotification
                                                  object:_currentVideoPlayerViewController.player];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(videoFinishedCallback:)
                                                 name:kPlayerViewDismissedNotification
                                               object:_currentVideoPlayerViewController.player];



    /* Create new player, if we don't already have one. */
    if (!_currentVideoPlayerViewController.player)
    {
        /* Get a new AVPlayer initialized to play the specified player item. */
        _currentVideoPlayerViewController.player=[AVPlayer playerWithPlayerItem:self->_playerItem];


         [_currentVideoPlayerViewController.player addObserver:self
         forKeyPath:@"rate"
         options:NSKeyValueObservingOptionNew
         context:AVPlayerDemoPlaybackViewControllerRateObservationContext];

    }


}

1 个答案:

答案 0 :(得分:1)

我无法弄清楚这背后的原因。我尝试使用AVPlayer而使用(引用Apple AVPlayer Demo app.)创建了我自己的UI,我找不到任何泄漏。它刚刚起作用。 如果有人遇到类似问题,请尝试从AVPlayer演示应用程序中引用代码。 如果有人知道我在这个问题上的问题的答案。请告诉我。