0

ルートにタブ バー コントローラーを備えたアプリがあります。「ホーム ビュー」は、OpenGL で 3D レンダリングされた画面です。ビデオを表示するためにクリックできる特定の 3D オブジェクトがあります。ビデオはフルスクリーンで、フェードインおよびフェードアウトする必要があります。

これを行うために、HomeViewController で MPMoviePlayerViewController を作成し、URL を割り当てて、タブ バー コントローラーから表示しました。(HomeViewController から提示したはずですが、何らかの理由で方向が適切に変更されませんでした。これはすべてのカスタム 3D 要素に関連していると確信しており、プログラムしていないので、上位ビューから表示することで回避できます。)

(私は MPMoviePlayerViewController を (組み込みの presentModalMovieViewController などを使用せずに) モーダルに提示していることに注意してください。これは、Apple がトランジションを風変わりなスクリーン シフトにすることを強制し、私がディゾルブを望んでいたためです。)

これで問題なく動作します。モーダル ウィンドウが溶け込み、ビデオが再生されます。再生、一時停止、早送り、[完了] をクリックすると、モーダル ウィンドウが消えます。出来上がり。

ここで、まったく奇妙なバグが発生します。ビデオ プレーヤーをタップせずにコントロールをフェードアウトさせると (1 ~ 2 秒後にフェードアウトします)、ユーザーはタップしてもコントロールを元に戻すことができません。そのフェードの後、ビデオ コントローラーがユーザー入力に応答しなくなったようです。繰り返しますが、消える前にうまく機能します。しかし、その時点以降、ビデオが最後まで再生されるまで待たなければなりません (実際、その時点でモーダル ウィンドウは消えます)。

参考までに、モーダル ビデオ プレーヤーに関連するコードを次に示します。

-(void) startVideoWithURL:(NSURL *)videoURL {

    if (!self.outsideMoviePlayerViewController) {
        self.outsideMoviePlayerViewController = [[MPMoviePlayerViewController alloc] initWithContentURL:nil];
    }

    if (videoURL) {

        [self stopAnimation];

        self.outsideMoviePlayerViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
        self.outsideMoviePlayerViewController.moviePlayer.contentURL = videoURL;

        [[[AppController instance] getCustomTabBarViewController] presentModalViewController:self.outsideMoviePlayerViewController animated:YES];

        // Move observation of the dismiss from the MoviePlayerViewController to self.
        [[NSNotificationCenter defaultCenter] removeObserver:self.outsideMoviePlayerViewController
                                                        name:MPMoviePlayerPlaybackDidFinishNotification
                                                      object:self.outsideMoviePlayerViewController.moviePlayer];
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(movieFinishedCallback:)
                                                     name:MPMoviePlayerPlaybackDidFinishNotification
                                                   object:self.outsideMoviePlayerViewController.moviePlayer];

    }

}

-(void) movieFinishedCallback:(NSNotification *)aNotification {

    // Summary: Restart 3D animation, unregister from notifications, kill the modal video.

    [self startAnimation];

    MPMoviePlayerController *moviePlayer = [aNotification object];
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:MPMoviePlayerPlaybackDidFinishNotification
                                                  object:moviePlayer];

    [[[AppController instance] getCustomTabBarViewController] dismissModalViewControllerAnimated:YES];

}

このような問題について私が見つけた唯一の参考文献は、Apple サポート コミュニティのアーカイブされた投稿です。

https://discussions.apple.com/thread/2141156?start=0&tstart=0

このスレッドでは、問題の投稿者が自分で問題を解決し、問題が解決したと述べています。彼の説明は次のとおりです。

この問題は、CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE) の場合に発生します。CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.002, TRUE) に変更した後、画面をタップすることで再生コントロールを表示/非表示にできます。

残念ながら、私はゲームをプログラミングしていませんし、開発チームの誰もコード内のどこでも CFRunLoopRunInMode を呼び出していません。これに最も近いのは、アニメーション コード (同じ ViewController 内) でした。

- (void)startAnimation
{
    if (!animating)
    {
        NSLog(@"startAnimation called");
        CADisplayLink *aDisplayLink = [[UIScreen mainScreen] displayLinkWithTarget:self selector:@selector(drawFrame)];
        [aDisplayLink setFrameInterval:animationFrameInterval];
        [aDisplayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
        self.displayLink = aDisplayLink;

        animating = TRUE;
    }
}

これを引き起こしている可能性のあるものについて誰かが何か洞察を持っているなら、私はそれを感謝します. 少なくとも、今夜自分で解決できたとしても、この問題は Stack Overflow に投稿され、後世のためにアーカイブされる可能性があると考えました。

乾杯。

4

1 に答える 1

0

この問題の原因を突き止めました。

最初のビデオは再生されましたが、後続のビデオは再生されませんでした。このコードを移動しました:

if (!self.outsideMoviePlayerViewController) {
        self.outsideMoviePlayerViewController = [[MPMoviePlayerViewController alloc] initWithContentURL:nil];
}

このように、outsideMoviePlayerViewController の作成は次のブロック内にありました。

if (videoURL) {

        self.outsideMoviePlayerViewController = [[MPMoviePlayerViewController alloc] initWithContentURL:nil];

        [self stopAnimation];

        self.outsideMoviePlayerViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
        self.outsideMoviePlayerViewController.moviePlayer.contentURL = videoURL;

ビデオを再生するたびにコントローラーをリサイクルする代わりに、新しいコントローラーが作成されるようになりました。バグは消えました。モーダル ビュー コントローラーを表示するとさまざまなことが発生するため、なぜこのようなことが起こったのかは 100% わかりません。

要するに、コントローラーをメモリに保持しようとするのではなく、遅延読み込みパラダイムの一部として、最初からこれを行うべきだったということです。

于 2012-09-16T01:31:08.743 に答える