13

を使用してファイルからビデオを再生するアプリを作成しようとしていますAVFoundation。ビデオは、親テーブルビューの行をタップしてアクセスするビューに表示されます。実際のアプリには行ごとにビデオがありますが、現時点ではテスト用に 1 つだけ使用しています。

シミュレーターで実行すると、アプリは問題ありませんが、デバイス (ios 5.1 の下) で実行すると、ビデオは約 5 回正常に再生され、さまざまな方法で予期せずクラッシュします。最も一般的なのは、ビデオ ビューは読み込まれますが、ビデオ自体は再生されませんが、自動解放プールが配置されていない状態でオブジェクトが割り当てられているという不平を言うスレッドが発生EXC_BAD_ACCESSすることがあります。coremedia.remoteAVPlayer を起動するコードをラップするブロックを追加しました@autoreleasepoolが、これは役に立たないようです。

GCD がアイテムを再生するためにメイン キューに複数のスレッドを作成しているが、それらが終了していないことが原因であるかどうか疑問に思っています。

したがって、重要な問題は、ユーザーがビデオ ビューで [戻る] ボタンを押した場合に、AVPlayer が実行されている余分な GCD スレッドをどのようにクリアするかAVFoundationです 。いくつかのロギングと (前述のように) GCD ブロックの 1 つの内部にブロックを追加しましたが、それ以外はコードを変更していません。@autoreleasepool

方法は次の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");
    });

}

私は今日のほとんどの間これに苦労してきました-どんな助けも感謝して受け取ります

4

2 に答える 2

16

保持カウントが 1 減り、ARC がコードのリリースを処理するため、最初にスーパービューから削除する必要があります。

このような

[videoView removeFromSuperview];
[self setVideoView:nil];
于 2012-04-11T00:00:35.460 に答える
5

videoView をどこかに保持したままにしておくことはできますか? そうすれば、avPlayerItem と avPlayer は生きたままになり、このトピックによれば、4 つのビデオがメモリに残っている「レンダー パイプライン」の iOS 制限に達したためです。

var を nil に設定しても、実際には基になるオブジェクトは解放されないことに注意してください。だからあなたの

videoView = nil;

効果がゼロになる可能性があります。

于 2012-04-08T15:24:25.517 に答える