MPMoviePlayerController仍然存在内存泄漏问题

3

我释放了MPMoviePlayerController,但内存分配和存活对象仍比对象分配前高。然而,如果我重新分配对象,它不会泄漏更多。

我的应用程序实际上使用了大量媒体文件,内存消耗很高。我想完全释放不需要的内存,以避免内存警告。

电影播放器释放:

        player.initialPlaybackTime = -1;
        [player.view removeFromSuperview];
        [player stop];
        [player release];

影片播放器分配:

    NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"video0_hd.mov" ofType:nil]];
    player = [[MPMoviePlayerController alloc] initWithContentURL:url];
    player.view.frame = placeholder.frame;
    [self.view addSubview:player.view];
    [player play];
3个回答

4

我也遇到了这个问题。

iPad用于预加载视频流的缓存没有完全清空。因此,每次清理并释放带有视频播放器的页面时,清理后分配的内存仍包含缓存的内存。对于大型视频,这可能高达50 MB。

实际上,这不是内存泄漏:

如果再次打开页面,则会重新分配缓存。但是当您想要一个干净的退出情况时,这仍然是令人沮丧的,这意味着当离开此页面并进行清理时,所有由此页面使用的内存都应该被释放,包括用于缓存视频流的内存....!

经过一些严格的调整,以下命令序列似乎可以完成任务:

======================

    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:MPMoviePlayerPlaybackDidFinishNotification
                                                  object:myMoviePlayer];        

    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:MPMoviePlayerDidExitFullscreenNotification
                                                  object:myMoviePlayer];        

    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:MPMoviePlayerLoadStateDidChangeNotification
                                                  object:myMoviePlayer];

    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:MPMovieDurationAvailableNotification
                                                  object:myMoviePlayer];        
    [myMoviePlayer pause];
    myMoviePlayer.initialPlaybackTime = -1;
    [myMoviePlayer stop];
    myMoviePlayer.initialPlaybackTime = -1;
    [myMoviePlayer.view removeFromSuperview];
    [myMoviePlayer release];

=================================

步骤:

1- 删除您正在使用的电影播放器上的所有通知器。

2- 暂停电影。

3- 将播放时间设置为开始。

4- 停止电影。

5- 再次将播放时间设置为开始。

6- 现在删除电影视图。

7- 最后释放电影播放器。

在我的情况下,这会导致iPad(OS 4.2)上的视频缓存内存也被释放,并留下一个干净的分配内存情况,与打开视频播放器页面之前相同。所以进入和退出时的内存相同。

希望这有所帮助......


嗨..我遇到了这个错误 _itemFailedToPlayToEnd: { kind = 1; new = 2; old = 0; } .. 我尝试了你的代码..但是不起作用...有时视频可以播放..有时我在同一个视频中遇到了这个错误 @ladhani - Vidhyanand

0

您是在设备上还是在模拟器上运行此代码?模拟器会产生大量的虚假泄漏(例如在AudioToolbox、CoreVideo等方面)。此外,模拟器似乎会缓存整个视频并且无法正确释放,而设备只会沿途缓冲所需内容。

我在模拟器上测试了您的代码,并使用mp4视频,结果与您所说的类似(每次播放视频时有10个活动对象,没有死亡...分配了20mb,即使释放后仍剩下5mb)。在模拟器上,活动对象和内存分配会不断增长。

然而,在我的iPhone上(使用20mb视频),它仅为应用程序分配了900kb的总内存,在启动/停止/释放视频时没有明显变化。在我测试了10次(启动/停止/释放)后,它始终保持在900kb左右。

看起来又是您不能信任模拟器的时候了。

我正在测试的代码:

NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"SomeMovieFile" ofType:@"mp4"]];

MPMoviePlayerController *newPlayer = [[MPMoviePlayerController alloc] initWithContentURL:url];

self.player = newPlayer;  
[newPlayer release];

[self.view addSubview:player.view];  // for my example, I didn't set the frame location, but no difference that would do
[player play];

然后在另一个按钮里,我停止了它并释放了播放器:
[player.view removeFromSuperview];    
player.initialPlaybackTime = -1;
[player stop];
self.player = nil;  // this is just a habit of mine.. calling stop should unload the buffers though
[player release];

1
你应该避免使用"player=nil; [player release];",因为从技术上讲,你释放的是"nil",而不是已分配的播放器,这可能会导致泄漏。 - pop850
实际上,将对象设置为nil将释放对象的旧值,然后将对象值设置为nil。但是,就像任何其他对象一样,您仍然必须释放任何您明确分配/初始化的内容。我认为您正在混淆仅将对象设置为nil然后不释放它的情况。在这种情况下,您正在泄漏对象,因为您仍然有一个指向某个从未被解除分配的内存中的对象的指针。 - iwasrobbed
实际上,这段代码已在iPad上进行了测试,并且内存分配从未完全释放。 无论如何,如果您测试了您发布的代码并且没有发现任何内存泄漏,那很奇怪。在释放对象之前,您将指针设置为nil。 - Cesar
嗯...我正在iPhone 4上进行测试。我听说过iOS 3.2存在问题,需要在停止播放器之前调用[player pause];。由于我没有iPad,所以无法确定这是否会对您有所帮助。就像我说的,调用[player stop];应该会清除数据缓冲区,但是我习惯于将其设置为nil以防万一。无论哪种方式都应该可以工作。此外,请确保添加所有必要的框架(有时可以修复奇怪的泄漏)。 - iwasrobbed
@IWasRobbed:所有必要的框架?仅仅#import <MediaPlayer/MediaPlayer.h>还不够吗? - Cesar
显示剩余2条评论

0
你尝试过使用Build and Analyze(Build>Build and Analyze)吗?这可以显示出内存泄漏的确切行数(如果有的话)。
现在,我有一种感觉,问题可能出在你定义NSURL的地方。

1
这是一个自动释放对象,问题肯定不在那里。 - Cesar
同意... 你只释放那些你特别alloc / init的东西..其他所有东西都不是你的责任,尤其是如果它是一个方便类。苹果会自动释放它们。 - iwasrobbed

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接