MPMoviePlayer does not disappear on [moviePlayer.view removeFromSuperview] and [moviePlayer release] - objective-c

I have a problem with MPMoviePlayerController.When I am watching a video, and hit the 'Done' button on the left top, the MoviePlayer does not disappear, even though the code seems to be called:
NSURL *url = [NSURL URLWithString:article.enclosureLink];
MPMoviePlayerController *moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:url];
// Set movie player layout
[moviePlayer setControlStyle:MPMovieControlStyleFullscreen];
[moviePlayer setFullscreen:YES];
// May help to reduce latency
[moviePlayer prepareToPlay];
// Register to receive a notification when the movie has finished playing.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlayBackDidFinish:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:moviePlayer];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(movieReadyToPlay:)
name:MPMoviePlayerLoadStateDidChangeNotification
object:moviePlayer];
And the selectors:
- (void) movieReadyToPlay:(NSNotification*)notification {
MPMoviePlayerController *moviePlayer = [notification object];
if(moviePlayer.loadState == MPMovieLoadStatePlayable){
[[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerLoadStateDidChangeNotification object:moviePlayer];
moviePlayer.controlStyle = MPMovieControlStyleFullscreen;
//moviePlayer.shouldAutoplay = YES;
[self.view addSubview:moviePlayer.view];
[moviePlayer setFullscreen:YES animated:YES];
[moviePlayer play];
}
}
- (void) moviePlayBackDidFinish:(NSNotification*)notification {
MPMoviePlayerController *moviePlayer = [notification object];
[[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerPlaybackDidFinishNotification object:moviePlayer];
[moviePlayer setFullscreen:NO animated:YES];
[moviePlayer.view removeFromSuperview];
[moviePlayer release];
NSLog(#"Finished movie!");
}
This looks to me a very straight forward code, but I must make a stupid mistake. The NSLog shows that the function is called, but the player stays where it is and there is no way of getting rid of it.
Also, the very fact that the player is still operational after the alleged release seems to indicate that there is something fundamental wrong, I just don't see what.
Is there anybody who has a suggestion?
[Update:]
Strangely in the iPhone Simulator it works fine!
[Update2:]
I tried and created a specific UIviewcontroller, even though it is not the way I want to do it as the animations are not nice. But what I learned is that I have the same problem. It seems to hav to do something with dismissing the player, but it starting again.
When I put [self.moviePlayer setFullscreen:YES animated:YES]; in viewDidApear, and click the 'Done' button in the player, the player, the video starts over again when I hit the Done button (the viewDidAppear is called again). So something is triggered, so it seems to me, to make the video start again.
If I put it viewDidLoad, then the system works, but the graphics are mixed and confused...
Any help is really, really appreciated as I spend two days on this now without making head or tail of it!

For me, I tried all of these:
[moviePlayer stop];
[moviePlayer setContentURL:nil];
[moviePlayer.view removeFromSuperview];
moviePlayer = nil;
And nothing worked. I figured out it had to due with my MPMoviePlayerController entering full screen. The fix?
[moviePlayer setFullscreen:NO animated:YES];

Adding
[moviePlayer stop]
before
[moviePlayer.view removeFromSuperview]
may work.
Update:
If this doesn't work then try setting controlstyle to MPMovieControlStyleNone before removing the subview.Most of the time the controlStyle causes such problems.

Related

why isn't removeFromSuperview removing my movie subview? Xcode

I'm trying to get a movie that plays to dismiss on its own without having to hit the "Done" button. I think it's a recent iOS 6 problem since I'm following a tutorial exactly and when I insert NSLogs the NSNotification and removeFromSuperview are being recognized but the movie stays there once it has ended. Here's my code, please help:
- (IBAction)playMovie:(id)sender
{
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle]
pathForResource:#"RomneyFlipSequence1" ofType:#"mov"]];
_moviePlayer =
[[MPMoviePlayerController alloc]
initWithContentURL:url];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlayBackDidFinish:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:_moviePlayer];
_moviePlayer.controlStyle = MPMovieControlStyleDefault;
_moviePlayer.shouldAutoplay = YES;
[self.view addSubview:_moviePlayer.view];
[_moviePlayer setFullscreen:YES animated:NO];
}
- (void) moviePlayBackDidFinish:(NSNotification*)notification {
MPMoviePlayerController *player = [notification object];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerPlaybackDidFinishNotification
object:player];
if ([player
respondsToSelector:#selector(setFullscreen:animated:)])
{
[player.view removeFromSuperview];
}
}
#end
You entered the player into fullscreen mode.
[_moviePlayer setFullscreen:YES animated:NO];
Reading other solutions in SO it seems that when you press "Done" the player is taken out of fullscreen first, and then the notification is thrown. After reading this answer, adding
[_moviePlayer setFullscreen:NO animated:YES];
before your removeFromSuperview call will solve your problem.
If the above doesn't work, in addition you may try stoping the player first so the full code will be
-(void)removePlayer:(MPMoviePlayerController *)player{
NSLog(#"Playback Finished");
[[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerPlaybackDidFinishNotification object:_moviePlayer];
[[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerDidExitFullscreenNotification object:_moviePlayer];
[_moviePlayer stop]; // <-- May not be needed
if ([_moviePlayer respondsToSelector:#selector(setFullscreen:animated:)])
{
[_moviePlayer setFullscreen:NO animated:YES];
[_moviePlayer.view removeFromSuperview];
}
_moviePlayer=nil;
}
I use the same method for both notifications "Done" and "PlayBackFinished"
Hope this helps.
You had added _moviePlayer.view as a view and you are trying to remove player.view
i think this will do it :
- (void) moviePlayBackDidFinish:(NSNotification*)notification {
MPMoviePlayerController *player = [notification object];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerPlaybackDidFinishNotification
object:player];
if ([player
respondsToSelector:#selector(setFullscreen:animated:)])
{
[_moviePlayer.view removeFromSuperview];
}
}

MPMoviePlayerController cannot be removed using removeFromSuperView

I need to remove a MPMoviePlayerController from a View.
I tried this.
[moviePlayerController stop];
[moviePlayerController.view removeFromSuperview];
the video stops, but the view is not removed. I guess [moviePlayerController.view removeFromSuperview]; does not work. What could be the reason ? Any Solution to this prolem ..?
Thanks.
This problem generally occurs because of the player get deallocated.The solution is that declare the player instance in .h with property "strong".
#property (nonatomic,strong) MPMoviePlayerController* mpController;
Its a known problem that id you are using ARC, then you HAVE TO add the player to your .h because it does still get released if you declare it locally.
#property (nonatomic, strong) MPMoviePlayerController* controller;
To add the view:
self.controller = [[MPMoviePlayerController alloc] initWithContentURL:YOURVIDEOURL];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlayBackDidFinish:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:self.controller];
self.controller.controlStyle = MPMovieControlStyleDefault;
self.controller.shouldAutoplay = YES;
[self.view addSubview:self.controller.view];
[self.controller setFullscreen:YES animated:YES];
And then to remove the view:
- (void) moviePlayBackDidFinish:(NSNotification*)notification {
if (UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation))
{
[[UIApplication sharedApplication] setStatusBarOrientation:UIDeviceOrientationPortrait animated:NO];
}
MPMoviePlayerController *player = [notification object];
[[NSNotificationCenter defaultCenter]
removeObserver:self
name:MPMoviePlayerPlaybackDidFinishNotification
object:player];
if ([player
respondsToSelector:#selector(setFullscreen:animated:)])
{
[player.view removeFromSuperview];
}
}
Not entirely sure, but since I had the problem of the movieplayer not showing up because of auto deallocating, I guess you could just set moviePlayerController = nil;.
Not Totally sure if the view will disappear, but worth a try!
Try dismissViewController:animated: That will probably work.
[moviePlayerController stop];
[moviePlayerController setContentURL:nil];
[moviePlayerController.view removeFromSuperview];
this is running well in my project
For me, I tried all of these:
[moviePlayer stop];
[moviePlayer setContentURL:nil];
[moviePlayer.view removeFromSuperview];
moviePlayer = nil;
And nothing worked. I figured out it had to due with my MPMoviePlayerController entering full screen. The fix?
[moviePlayer setFullscreen:NO animated:YES];

Can not detect MPMoviePlayerDidExitFullscreenNotification

In my project, I used MPMoviePlayerController to stream video from an http url. It plays fullscreen. When the video is playing, if you tap on "Done" button the video stops and it disappears, but the problem is; if you pinch to close video screen the video screen disappears but it still plays, sound of video continues to play.
I tried to detect exit fullscreen notification and manually stop the video but it didn't work. My moviePlayerDidExitFullScreen method didn't called.
To control that if I am getting the notifications on the right way I tried to get another notification : MPMoviePlayerPlaybackStateDidChangeNotification, and it is working. It calls the method on video launching.
I searched many forums and Apple documentations but I couldn't find enough information.
Here is my code to open a fullscreen video and detect exit fullscreen :
- (void)openFullVideo
{
NSString* path = #"http://trtvizyon.mysys.com/test/leyla_ile_mecnun.mp4";
NSURL *fileURL = [NSURL URLWithString:path];
MPMoviePlayerController *player = [[MPMoviePlayerController alloc] initWithContentURL:fileURL];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePlayerDidExitFullScreen:) name:MPMoviePlayerDidExitFullscreenNotification object:nil];
player.controlStyle = MPMovieControlStyleDefault;
player.movieSourceType = MPMovieSourceTypeStreaming;
[self.view addSubview:player.view];
[player setFullscreen:YES animated:YES];
[player play];
}
- (void) moviePlayerDidExitFullScreen:(id)sender {
NSLog(#"moviePlayerDidExitFullScreen");
}
OK, I played with your code for a while, and finally shot that little bug in the gut.
Your first problem is not retaining the player object (assuming you are using ARC, if not, then skip this). So, just make sure you retain it as an instance variable for example:
//Header File
#interface ViewController : UIViewController {
MPMoviePlayerController* _player;
}
// Implementation File
- (void)openFullVideo {
// ...
_player = player;
}
Now, if that just works, then great!! But I am getting a dreaded unsolved bug on apple's side:
An AVPlayerItem can occupy only one position in a player's queue at a time
To solve this issue, do it like so:
NSString* path = #"http://trtvizyon.mysys.com/test/leyla_ile_mecnun.mp4";
NSURL *fileURL = [NSURL URLWithString:path];
MPMoviePlayerController *player = [[MPMoviePlayerController alloc] init];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePlayerDidExitFullScreen:) name:MPMoviePlayerDidExitFullscreenNotification object:nil];
player.controlStyle = MPMovieControlStyleDefault;
player.movieSourceType = MPMovieSourceTypeStreaming;
[self.view addSubview:player.view];
[player setContentURL:fileURL];
[player setInitialPlaybackTime:-1.f];
[player setFullscreen:YES animated:YES];
[player prepareToPlay];
[player play];
_player = player;
That should do it!
Some Other Friendly Advice:
Make sure you remove yourself from NSNotificationCenter before playing the movie again.
I would suggest adding something like if (_player != nil) to avoid recreating the object.

When my movie is finished to play, the app crashes

I tried to launch a movie by clicking in a button. When I click the Movie player appears and works fine. The movie plays until the end and the Movie player disappears. After it disappears, my app crashes...
I use my View Controller in Tab Bar Application with this code :
- (void)moviePlayBackDidFinish:(NSNotification *) aNotification{
MPMoviePlayerController *player = [aNotification object];
[player setFullscreen:NO animated:YES];
[player.view removeFromSuperview];
[player stop];
player.initialPlaybackTime = -1.0;
[[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerPlaybackDidFinishNotification object:player];
[player release];
player=nil;
}
- (IBAction)playVideo:(UIButton *)playButton{
NSString *url = [[NSBundle mainBundle] pathForResource:#"Teaser 04" ofType:#"mov"];
MPMoviePlayerController *player = [[MPMoviePlayerController alloc] initWithContentURL:[NSURL fileURLWithPath:url]];
player.shouldAutoplay = YES;
player.view.frame = CGRectMake(0., 44., self.view.bounds.size.width, self.view.bounds.size.height-44);
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePlayBackDidFinish:) name:MPMoviePlayerPlaybackDidFinishNotification object:player];
[self.view addSubview:player.view];
[player play];
}
I don't know what I'm doing wrong. I just want configure a button that start the video and when the video is finished, the MoviePlayer View disappears and the app come back to my initial .xib
Thank you for your help
I found the solution, I don't know if it is the best but for what I want it's working :
- (void)movieFinishedCallBack:(NSNotification *) aNotification{
MPMoviePlayerController *player = [aNotification object];
[[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerPlaybackDidFinishNotification object:player];
[player.view removeFromSuperview];
[player stop];
[player release];
}
- (IBAction)playVideo:(UIButton *)playButton{
NSString *url = [[NSBundle mainBundle] pathForResource:#"Teaser 04" ofType:#"mov"];
MPMoviePlayerController *player = [[MPMoviePlayerController alloc] initWithContentURL:[NSURL fileURLWithPath:url]];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(movieFinishedCallBack:) name:MPMoviePlayerPlaybackDidFinishNotification object:player];
player.view.frame = CGRectMake(0, 0, 950, 600);
[self.view addSubview:player.view];
[player play];
}
I could be wrong, but my guess is that the player gets used somewhere in the backtrace for the call to moviePlayBackDidFinish: ... If I'm right, then deallocing the object there - which it looks like you're doing - is bad news, since the object is still needed somewhere up in the stack.
Check out this post for more details: How to release MPMoviePlayerController?

MPMoviePlayerController problems on iPad

I'm trying to use the MPMoviePlayerController class on the iPad.
Here's my code:
multimediaPlayer = [[MPMoviePlayerController alloc] initWithContentURL:[NSURL fileURLWithPath:path]];
multimediaPlayer.movieControlMode = MPMovieControlModeDefault;
[multimediaPlayer play];
and this works very well on the iPhone but it don't want to run on the iPad. I hear the sound of the video, but the movie doesn't playing.
Why it can be this problem?
Below code working perfect for my application. Hope it would do same for you.
The main thing is to set the frame of mpMoviePlayerController's frame. if you don't do it, it would almost not show the video.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[[UIApplication sharedApplication] setStatusBarHidden:YES];
// Register to receive a notification when the movie has finished playing.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlayBackDidFinish:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:nil];
// Register to receive a notification when the movie scaling mode has changed.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(movieScalingModeDidChange:)
name:MPMoviePlayerScalingModeDidChangeNotification
object:nil];
kDomain = [NSString stringWithString:#"http://www.virtua-book.com/"];
[navigationController setNavigationBarHidden:YES];
NSURL *ur=[[NSURL alloc] initFileURLWithPath:[[NSBundle mainBundle] pathForResource:#"IPAD" ofType:#"mp4"]];
mpMCtr=[[MPMoviePlayerController alloc] initWithContentURL:ur];
mpMCtr.fullscreen=YES;
[mpMCtr setScalingMode:MPMovieScalingModeFill];
[mpMCtr setShouldAutoplay:YES];
[mpMCtr setControlStyle:MPMovieControlStyleNone];
[mpMCtr setMovieSourceType:MPMovieSourceTypeFile];
mpMCtr.view.frame = CGRectMake(0, 0, 1024, 768);
[mpMCtr setRepeatMode:MPMovieRepeatModeNone];
[mpMCtr play];
[ur release];
// Override point for customization after app launch
[navigationController.view addSubview:mpMCtr.view];
[window addSubview:[navigationController view]];
[window makeKeyAndVisible];
return YES;
}
// Notification called when the movie finished playing.
- (void) moviePlayBackDidFinish:(NSNotification*)notification
{
[mpMCtr.view removeFromSuperview];
}
To fix back/forward (or previous/next) buttons you should do the following:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePlayerPlaybackStateDidChange:) name:MPMoviePlayerPlaybackStateDidChangeNotification object:nil];
...
- (void) moviePlayerPlaybackStateDidChange: (NSNotification *) notification {
if (moviePlayer.playbackState == MPMoviePlaybackStateStopped) {
[moviePlayer setContentURL:[moviePlayer contentURL]];
[moviePlayer play];
}
}
Something along these lines is probably what you want to do:
MPMoviePlayerViewController *mpvc = [[MPMoviePlayerViewController alloc] initWithContentUrl:movieUrl];
[self presentMoviePlayerViewController:mpvc];
MPMoviePlayerViewController *mp = [[MPMoviePlayerViewController alloc]initWithContentURL:movieURL];
mp.moviePlayer.controlStyle = 2;
Ok, guys, I found that this: is deprecated.
The solution is multimediaPlayer.controlStyle = MPMovieControlStyleDefault; but it still doesn't work.