2012-04-04 131 views
12

我正嘗試使用AVFoundation來創建一個從文件播放視頻的應用程序。視頻顯示在一個視圖中,通過點擊父級表格中的一行來訪問。真正的應用程序將爲每一行都有一個視頻,但目前我只用一個進行測試。AVPlayer在多次播放後崩潰 -

在模擬器上運行時,應用程序可以正常運行,但是在設備上運行(在ios 5.1下)時,視頻播放正常約5次,然後以各種方式崩潰不可預知。 最常見的是,視頻加載視頻,但視頻本身不播放,但有時 coremedia.remote我得到一個EXC_BAD_ACCESS線程,抱怨沒有自動釋放池分配的對象。我添加了一個包裝啓動AVPlayer的代碼的@autoreleasepool塊,但這似乎沒有幫助。

我想知道是否GCD在主隊列上創建多個線程來播放項目,但它們沒有終止。

因此,關鍵問題是 - 我怎麼清理多餘的GCD線程AVPlayer上 運行,如果用戶點擊視頻查看 後退按鈕儘可能我已經按照提供的示例代碼蘋果的AVFoundation文檔here 我已經添加了一些日誌和(如上所述)@autoreleasepool塊內的一個GCD塊 - 除了我沒有改變代碼。

viewDidLoad方法如下:

-(void)viewDidLoad{ 
[super viewDidLoad]; 

NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"TestLapCar2Vid" withExtension:@"m4v"]; 
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:fileURL options:nil]; 
NSString *tracksKey = @"tracks"; 

[asset loadValuesAsynchronouslyForKeys:[NSArray arrayWithObject:tracksKey] completionHandler: 
^{ 
    dispatch_async(dispatch_get_main_queue(), 
    ^{ 
     @autoreleasepool { 
     NSError *error = nil; 
      AVKeyValueStatus status = [asset statusOfValueForKey:tracksKey error:&error]; 

      if(status == AVKeyValueStatusLoaded){ 
       avPlayerItem = [AVPlayerItem playerItemWithAsset:asset]; 
       [avPlayerItem addObserver:self forKeyPath:@"status" 
            options:0 context:&ItemStatusContext]; 

       [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(playerItemDidReachEnd:) 
                  name:AVPlayerItemDidPlayToEndTimeNotification object:avPlayerItem]; 

       avPlayer = [AVPlayer playerWithPlayerItem:avPlayerItem]; 
       [videoView setPlayer:avPlayer]; 
       NSLog(@"Asset loaded"); 
       [avPlayer play]; 
      } 
      else{ 
       NSLog(@"The asset's tracks were not loaded"); 
      } 

     } 
    }); 
}];  

}

viewWillDisappear方法是:

-(void)viewWillDisappear:(BOOL)animated{ 
NSLog(@"view will disappear called"); 
[super viewWillDisappear:animated]; 
dispatch_async(dispatch_get_main_queue(), 
    ^{ 
     [avPlayer pause]; 
     [avPlayerItem removeObserver:self forKeyPath:@"status"]; 
     [[NSNotificationCenter defaultCenter]removeObserver:self]; 
     NSLog(@"Race timeline nav controller has %d sub controllers",self.navigationController.childViewControllers.count); 
     avPlayerItem = nil; 
     avPlayer = nil; 
     videoView = nil; 
     dataStore = nil; 
     pkReader = nil; 
     receivedData = nil; 
     revDial = nil; 
     speedDial = nil; 
     mapView = nil; 
     throttle = nil; 
     NSLog(@"releasing stuff"); 
    }); 

}

我一直在爲此而努力的最今天 - 任何幫助將感激地收到

+0

thanx的要求! – headkit 2012-09-02 14:38:19

回答

14

您應該先從超級視圖中移除,因爲它會將保留計數減1,ARC將爲您處理相關問題。

這樣

[videoView removeFromSuperview]; 
[self setVideoView:nil]; 
+0

謝謝!這對我來說非常合適。 – theDuncs 2012-04-12 11:27:26

+0

非常感謝!我一直在這個小bug上掙扎超過1周!你救了我的日子! – Anthony 2012-06-26 03:32:52

+0

相關信息 - ARC讓我瘋狂...... – headkit 2012-09-02 14:38:51

5

可能會讓您的videoView保留在某個地方嗎?因爲如果你這樣做,你的avPlayerItem和AVPlayer保持活着,並根據this主題,你想出了4個視頻駐留在內存中的「渲染管道」的iOS限制。

請記住,將var設置爲nil並不實際釋放基礎對象。所以你的

videoView = nil; 

可以有零效應。

+0

有趣的是,知道iOS渲染管道的限制和4個視頻留在內存中! – headkit 2012-09-02 14:39:21

+0

我們需要在哪添加此行?我在'viewDidLoad'添加它,但現在它不顯示視頻 – CGR 2016-12-07 22:47:46

+1

@CGR可能是當你關閉視圖控制器與視頻? – faviomob 2016-12-07 23:17:28