iOSには動画再生用にMPMovierPlayerViewController
っていうクラスがあって、URLを渡して表示するだけでめちゃくちゃ簡単に動画再生機能を実装できる。すごく便利。
その分自由度が低くてちょっとした挙動を変えるのが大変だったりする。
まず、普通に動画を再生するならこういう風に実装する。
- (void)playVideo:(NSURL*)url
MPMoviePlayerViewController *vc = [[MPMoviePlayerViewController alloc] initWithContentURL:url];
[self presentViewController:vc animated:YES completion:nil];
}
これだけのコードで再生できるから結構驚き。
ところで、この方法では再生完了時にMPMoviePlayerViewController
が勝手に閉じられてしまう。再生が終わったらそのまま待つのがいいんじゃないの、と個人的には思ったため回避方法を探すことにした。
どうやら内部ではNSNotificationCenter
を用いて動画終了時に通知を出し、その通知を受け取ったら閉じるというセレクタを呼んでいるらしい。
Dismissing MPMoviePlayerViewController the right way | I’m the one who codes!
勝手に閉じないようにするにはプレーヤーの表示前にNSNotificationCenter
から関連するものを削除してあげればよい。
- (void)playVideo:(NSURL*)url
MPMoviePlayerViewController *vc = [[MPMoviePlayerViewController alloc] initWithContentURL:url];
[[NSNotificationCenter defaultCenter] removeObserver:vc
name:MPMoviePlayerPlaybackDidFinishNotification
object:vc.moviePlayer];
[self presentViewController:vc animated:YES completion:nil];
}
これでOKと思いきやそうもいかない。なんとMPMoviePlayerViewController
がデフォルトで用意しているcloseボタンまで効かなくなってしまう。もちろんこんな挙動は困る。
回避するには、さっき削除したMPMoviePlayerPlaybackDidFinishNotification
に対応するセレクタを自前で定義し、ユーザーがボタンを操作したときには閉じるという処理にしておけばいい。
最終的なコードは次のようになる。
- (void)playVideo:(NSURL*)url
MPMoviePlayerViewController *vc = [[MPMoviePlayerViewController alloc] initWithContentURL:url];
[[NSNotificationCenter defaultCenter] removeObserver:vc
name:MPMoviePlayerPlaybackDidFinishNotification
object:vc.moviePlayer];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(videoFinished:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:vc.moviePlayer];
[self presentViewController:vc animated:YES completion:nil];
}
- (void)videoFinished:(NSNotification*)notification{
int value = [[notification.userInfo valueForKey:MPMoviePlayerPlaybackDidFinishReasonUserInfoKey] intValue];
if (value == MPMovieFinishReasonUserExited) {
[self dismissMoviePlayerViewControllerAnimated];
}
}