4

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.

Joseph
  • 145
  • 1
  • 9

3 Answers3

2

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.

Andrei Filip
  • 1,145
  • 15
  • 33
  • 1
    Seeing his code his is neither pushing it or adding it modally. It's a subview to the scrollview. So I might expect that indeed the MPMoviePlayer's view is still on top of the scrollview. Just like Andrei said, check if the buttons that are behind the movie player's frame still respond after closing the view. – bmeulmeester Oct 25 '12 at 10:24
  • Excellent suggestion. I made the changes that you suggested, Andrei, however the scroll is still locked post video. What is even more interesting is that the button that plays the movie is still fully functional after playing a movie. – Joseph Oct 25 '12 at 16:08
  • I ended up changing the movieplayer method and appended it to the original post to reflect the change. It more or less fixed the original problem, but a new set of errors have appeared. – Joseph Oct 25 '12 at 18:27
  • 1
    What delegate method is called after finishing the video play? it seems that your scroll view's insets are modified after play. you might change that when the video finishes playing so you will not have to scroll all the way to the top before playing the video. Also, you could search your project for the nslog that displays that error and see what's wrong in there... – Andrei Filip Oct 26 '12 at 09:10
  • I believe I have discovered the cause of the original problem of the scrolling not working after a movie has played. When I set the size of the ImageView in the storyboard, it will scroll to that point after the movie has finished. My guess is that it is forgetting what the size of the image is. I am curious about how to "remind" the UIView programmatically. Any help would be greatly appreciated. – Joseph Nov 10 '12 at 07:28
  • Another interesting wrinkle. No matter what I set self.scrollView.contentSize to, it will always default to what is set for the UIImageView size in the storyboard after the movie is played. Is there any way to override that? Thank you for all of your help so far. Nearly debugged! – Joseph Nov 10 '12 at 07:42
  • I can only guess that the view gets recreated when the movie is done playing so it goes back to the size it was originally set in your storyboard.(do you receive any memory warnings when playing the movie?) Why not set the correct contentSize directly from the storyboard? – Andrei Filip Nov 12 '12 at 14:49
1

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.)

Joseph
  • 145
  • 1
  • 9
0

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.

bmeulmeester
  • 1,117
  • 12
  • 26
  • Thank you for your reply. Unfortunately utilizing 'self.scrollView.userInteractionEnabled = YES' did not solve the problem. After inserting a breakpoint and inspecting the scrollView.contentSize variable, it appears that it is appropriatly sized after playing a movie. – Joseph Oct 25 '12 at 08:02