Thursday, April 02, 2015

iOS MPMoviePlayerController Crashes when prepareToPlay is Called Without Adding to a View

TL;DR Call something like [self.view addSubView:moviePlayer.view] before [moviePlayer prepareToPlay]
Versions: OS X  10.10.2 Xcode 6.2 iOS SDK 8.2 

I just inherited some code previously compiled against iOS SDK 6.0, ran fine through iOS 7, but crashes on iOS 8.x. Here’s the crasher:

NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"impact_of_needs_goal_planning@1x" ofType:@"mp4"]];
self.moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:url];
self.moviePlayer.shouldAutoplay = NO;
[self.moviePlayer setControlStyle:MPMovieControlStyleNone];
[self.moviePlayer.view setFrame:CGRectMake(0.0, 0.0, 1024.0, 748.0)];
[self.moviePlayer.view setTag:7];

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(movieDidLoad:) name:MPMoviePlayerLoadStateDidChangeNotification object:self.moviePlayer];
[self.moviePlayer prepareToPlay];

App was crashing on the last line, [self.moviePlayer prepareToPlay]; every time it was called.

This is a guess (because installing an iOS 7 simulator is taking forever), but it looks like iOS 7 and below didn't care because the app was working fine. iOS 8 crashes.

The solution is adding the moviePlayerController to a parent view before calling [self.moviePlayer prepareToPlay];, like this:
[self addSubview:self.moviePlayer.view];

Given this is The Right Thing To Do™, I'm actually surprised it ever worked!

Update

Turns out this was not the cause of the crash, which I have yet to nail down. This change did seem to temporarily solve the crash, but alas it is something to do with NSNotifications :’(