6

4 つの AVPlayerItems の配列から作成している AVQueuePlayer があり、すべて正常に再生されます。

キューの最後のアイテムの再生が終了したら何かをしたいのですが、ここでたくさんの答えを見てきましたが、これは私が望むものに対して最も有望に見えるものです: サウンドが終了した後にコードを実行する最良の方法遊んでいる

私のボタンハンドラーには、次のコードがあります。

static const NSString *ItemStatusContext;

    [thePlayerItemA addObserver:self forKeyPath:@"status" options:0 context:&ItemStatusContext];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(playerItemDidReachEnd)
                                                 name:AVPlayerItemDidPlayToEndTimeNotification
                                               object:thePlayerItemA];

     theQueuePlayer = [AVQueuePlayer playerWithPlayerItem:thePlayerItemA]; 

    [theQueuePlayer play];

そして、playerItemDidReachEnd を処理する関数があります。

- (void)playerItemDidReachEnd:(NSNotification *)notification {
// Do stuff here
NSLog(@"IT REACHED THE END");
}

しかし、これを実行すると、Internal Inconsistency Exception が発生します。

    An -observeValueForKeyPath:ofObject:change:context: message was received but not handled.
Key path: status
Observed object: <AVPlayerItem: 0x735a130, asset = <AVURLAsset: 0x73559c0, URL = file://localhost/Users/mike/Library/Application%20Support/iPhone%20Simulator/5.0/Applications/A0DBEC13-2DA6-4887-B29D-B43A78E173B8/Phonics%2001.app/yes.mp3>>
Change: {
    kind = 1;

}

私は何を間違っていますか?

4

3 に答える 3

8

このアプローチは私にとってはうまくいくようです.ボタンハンドラー内には、再生したい4つのmp3ファイルのURLを作成するためのものがたくさんあります.

AVPlayerItem *thePlayerItemA = [[AVPlayerItem alloc] initWithURL:urlA];
AVPlayerItem *thePlayerItemB = [[AVPlayerItem alloc] initWithURL:urlB];
AVPlayerItem *thePlayerItemC = [[AVPlayerItem alloc] initWithURL:urlC];    
AVPlayerItem *thePlayerItemD = [[AVPlayerItem alloc] initWithURL:urlD];  

NSArray *theItems = [NSArray arrayWithObjects:thePlayerItemA, thePlayerItemB, thePlayerItemC, thePlayerItemD, nil];
theQueuePlayer = [AVQueuePlayer queuePlayerWithItems:theItems];

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(playerItemDidReachEnd:)
                                             name:AVPlayerItemDidPlayToEndTimeNotification
                                           object:[theItems lastObject]];
[theQueuePlayer play];

その後、次のように「playerItemDidReachEnd」セレクターを実装しました。

- (void)playerItemDidReachEnd:(NSNotification *)notification {
    // Do stuff here
    NSLog(@"IT REACHED THE END");
}

これにより、4 つの MP3 ファイルがキューに入れられ、オーディオの最後の部分が終了すると、セレクターが呼び出され、私のメッセージがコンソールに表示されます。

これが他の誰かに役立つことを願っています。

于 2012-08-30T21:36:58.073 に答える
3

ステータスを観察しても、アイテムの再生がいつ終了したかはわかりません (アイテムが ReadyToPlay になったときにのみわかります)

あなたがしなければならないのは、あなたのインスタンスを初期化するために使用するAVPlayerItemDidPlayToEndTimeNotification 、playbackQueue の lastItem に登録することだけです。AVQueuePlayer

AVQueuePlayer* player = [AVQueuePlayer queuePlayerWithItems:currentPlaybackQueue];
[[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(playerItemDidReachEnd:)
                                                 name:AVPlayerItemDidPlayToEndTimeNotification
                                               object:currentPlaybackQueue.lastObject];

(セレクターには があることに注意してplayerItemDidReachEnd:ください。2つのドットを忘れました)

その-playerItemDidReachEnd:ため、必要に応じて最後に一度だけ呼び出されます。(また、オブザーバーとして自分自身を削除することを忘れないでください - を-playerItemDidReachEnd:使用して行うことができますnotification.object)

これを行うには他の方法があると言わざるを得ません: currentItem を監視するキー値を使用してから、 currentItem が in に変更されたかどうかを確認[NSNull null]observeValueForKeyPath:ます。

[player addObserver:self forKeyPath:@"currentItem" options:NSKeyValueObservingOptionNew context:nil];

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if ([keyPath isEqualToString:@"currentItem"]) {

        if (change[NSKeyValueChangeNewKey] == [NSNull null]) {
            //last item finished playing - do something

        }
    }
}

通常、for の各アイテムAVQueuePlayerを登録するため、ローカルに保存して lastObject をinでチェックしたくない場合を除き、2 番目の方法を使用します。AVPlayerItemDidPlayToEndTimeNotificationplaybackQueueplaybackQueuenotification.object-playerItemDidReachEnd:

于 2014-07-29T11:53:25.700 に答える
2

-observeValueForKeyPath:ofObject:change:context:クラスにメソッドを実装していない可能性があります。詳細については、Apple KVO ガイドをご覧ください。

于 2012-08-30T03:41:22.010 に答える