4
votes

I'm fairly new to coding for the iOS platform and objective C in general. I'm writing a simple iPhone app utilizing storyboard that has a tall png file displayed via UIImageView embedded within a UIScrollView and a button next to it that will play a movie.

My issue is that when the movie finishes/exits and comes back to the original screen, the scrolling within the UIScrollView does not work. I have nailed down the "cause". It occurs when I add the MPMoviePlayerViewController object.view to the self.view subview. But I'm not sure how to rectify this issue. Here is my distilled code:

.h file

@interface StuffViewController : UIViewController 

@property (strong,nonatomic) IBOutlet UIImageView *imageView;
@property (strong,nonatomic) IBOutlet UIScrollView *scrollView;

-(IBAction) playMovie;
-(void) moviePlayBackDidFinish:(NSNotification*)notification;

@end

.m file

-(void) viewDidLoad {
    self.imageView.image = [UIImage imageNamed:@"image.png"];
}

-(void) viewDidAppear:(BOOL)animated {
    self.scrollView.contentSize = self.imageView.image.size;
}

-(void) playMovie {
    NSURL *movieURL = [NSURL fileURLWithPath:[[NSBundle mainBundle]
                                         pathForResource:@"movieTitle" ofType:@"mp4"]];
    MPMoviePlayerController *moviePlayer = [[MPMoviePlayerController alloc] 
                                                initWithContentURL:movieURL];
       [[NSNotificationCenter defaultCenter] addObserver:self
                                        selector:@selector(moviePlayBackDidFinish:)
                                            name:MPMoviePlayerPlaybackDidFinishNotification
                                          object:moviePlayer];
    [moviePlayer setMovieSourceType:MPMovieSourceTypeFile];
    [[self view] addSubview:moviePlayer.view];   //SCROLLING BREAKS HERE
    [moviePlayer setFullscreen:YES];
    [moviePlayer play];
}

-(void)moviePlayBackDidFinish: (NSNotification*)notification {
    MPMoviePlayerController *movieDone = [notification object];
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [movieDone.view removeFromSuperview];
    [movieDone setFullscreen:NO];
}

I have determined the culprit by commenting out sections, and like I said, the scrolling "locks" at the "[[self view] addSubview:moviePlayer.view];" line and doesn't recover until I navigate to a different view and then come back.

Any and all help on this would be greatly appreciated.

EDIT: I have discovered an interesting wrinkle that might help discover the underlying issue.

I have been using MPMoviePlayerController this whole time. However upon switching to MPMoviePlayerViewController some interesting things have been happening.

Here is the changed -(void)playMovie

-(void) playMovie {
   self.scrollView.contentOffset = CGPointZero;
   NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle]
                                    pathForResource:totalTitle ofType:@"mp4"]];
   MPMoviePlayerViewController *playerController =  [[MPMoviePlayerViewController alloc] initWithContentURL:url];
   [self presentMoviePlayerViewControllerAnimated:playerController];
   playerController.moviePlayer.movieSourceType = MPMovieSourceTypeFile;
   [playerController.moviePlayer play];
   playerController = nil;
}

What is interesting is that the UIScrollView will still work, HOWEVER, if it has been scrolled down at all it will no longer be able to scroll up from where it was when the movie started. I fixed this by adding self.scrollView.contentOffset = CGPointZero at the beginning of the playMovie to tell the scrollView to move to the top (so there would be nothing above it to have to scroll back to). I assume that adding some sort of if-statement to the code in viewDidAppear that would keep scrollView.contentSize from re-executing might fix the problem of not being able to scroll back up, however I like the 'cleanness' of it starting back at the top.

One last issue though. Using MPMoviePlayerViewController like this has caused a number of interesting errors to pop up in my debugger right when MPMoviePlayerViewController *playerController = [[MPMoviePlayerViewController alloc] initWithContentURL:url]; line is executed. They are as follows:

Oct 25 10:25:51 Compy.local AppName[14590] <Error>: CGContextSaveGState: invalid context 0x0 
Oct 25 10:25:51 Compy.local AppName[14590] <Error>: CGContextClipToRect: invalid context 0x0
Oct 25 10:25:51 Compy.local AppName[14590] <Error>: CGContextTranslateCTM: invalid context 0x0
Oct 25 10:25:51 Compy.local AppName[14590] <Error>: CGContextDrawShading: invalid context 0x0
Oct 25 10:25:51 Compy.local AppName[14590] <Error>: CGContextRestoreGState: invalid context 0x0

It doesn't seem to break anything. I tend to be a perfectionist when it comes to errant error statements however. I've done some research on these errors, however I haven't found anything suitable that would lend a strong hand in this situation.

Thanks for all the help so far! Once again, I would appreciate any and all help on this as well.

3
pleas add the code for the moment your player finishes with playing the video as well :) - Sebastian Flückiger
Edited to include finished-movie code per Sebastian's request - Joseph

3 Answers

2
votes

Are you sure that everything gets removed from the superview? Also, you might try replacing

 MPMoviePlayerController *movieDone = [notification object];

with

 MPMoviePlayerController *movieDone = (MPMoviewPlayerController *)[notification object];

and also add

movieDone = nil;

To make sure that your MPMoviePlayerController is completely removed from the superView, try pressing a button on your view (created before adding the MPMoviePlayerController) after the video's finished playing and see if it fires. The navigation controller must present your MPMoviewPlayerController modally or make a push. If it is modally presented, try dismissing it when the the playback's finished.

1
votes

The cause of the problem was the use of 'Autolayout' in Storyboard. I'm not 100% sure why it would cause it problem after playing a movie and not before. However I fixed it by either:

A: removing Autolayout

or

B: playing with the constraint functions until it ended up working. (Changing the height of the UIImageView to 0 and changing the Equals: Default to have the lowest priority possible.)

0
votes

Try setting the SetUserInteractionEnabled of self and/or self.scrollview to YES in the moviePlayBackDidFinish method. Also, check the size of the scroll view's ContentSize property, to check if the size is bigger than your actual screen size to see if that's causing the scroll view's functionality to break.