1
votes

I am trying to add a movie player in my cell.

Code:

- (MPMoviePlayerViewController*)setUp
{
    MPMoviePlayerViewController *player = [[MPMoviePlayerViewController alloc] initWithContentURL:url];

//.. setting frame etc
//not starting the player; no fancy set up, everything default.

    return player;
}

In cellForRowAtIndexPath:

    if (cell == nil)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
        cell.tag = indexPath.row;

        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul);
        dispatch_async(queue, ^(void)
        {
            MPMoviePlayerViewController *player = [self setUp];
            if (player)
            {
                dispatch_async(dispatch_get_main_queue(), ^
                {
                    if (cell.tag == indexPath.row)
                    {
                        [cell.contentView addSubview:player.view];
                        [cell setNeedsLayout];
                    }
                });
            }
        });
    }

If I added it to only only cell, there is no problem, if I added it to more than one let say 10 or 20, I always get this crash.

Error:

* Assertion failure in -[MPMoviePlayerControllerNew _moviePlayerDidBecomeActiveNotification:], /SourceCache/MediaPlayer_Sim/MobileMusicPlayer-2526.83/SDK/MPMoviePlayerController.m:1351

* Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'movie player has wrong activation state (1)'

Full trace:

0 CoreFoundation 0x01dcf1e4 __exceptionPreprocess + 180

1 libobjc.A.dylib 0x0191c8e5 objc_exception_throw + 44

2 CoreFoundation
0x01dcf048 +[NSException raise:format:arguments:] + 136

3 Foundation 0x014fc4de -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 116
4 MediaPlayer 0x00017450 -[MPMoviePlayerControllerNew _moviePlayerDidBecomeActiveNotification:] + 235
5 Foundation 0x015ef049 57-[NSNotificationCenter addObserver:selector:name:object:]_block_invoke + 40
6 CoreFoundation 0x01e2af04 __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER
+ 20
7 CoreFoundation 0x01d82efb _CFXNotificationPost + 2859
8 Foundation 0x01528e41 -[NSNotificationCenter postNotificationName:object:userInfo:] + 98
9 MediaPlayer 0x0001a085 -[MPMoviePlayerControllerNew _postNotificationName:object:userInfo:] + 133
10 MediaPlayer 0x00019ff1 -[MPMoviePlayerControllerNew _postNotificationName:object:] + 67
11 MediaPlayer 0x000197b2 -[MPMoviePlayerControllerNew _ensureActive] + 199
12 MediaPlayer 0x00014962 -[MPMoviePlayerControllerNew prepareToPlay] + 85
13 MediaPlayer 0x00012ccd -[MPMoviePlayerController prepareToPlay] + 42
14 MediaPlayer 0x00082c77 -[MPMoviePlayerViewController loadView] + 335
15 UIKit 0x006fb0d3 -[UIViewController loadViewIfRequired] + 78
16 UIKit 0x006fb5d9 -[UIViewController view] + 35
17 MyTableView 0x0000381f -[MyTableViewTableViewController prepareStreams] + 159
18 MyTableView 0x00004115 __72-[MyTableViewTableViewController tableView:cellForRowAtIndexPath:]_block_invoke + 53 19 libdispatch.dylib 0x044c17b8 _dispatch_call_block_and_release + 15
20 libdispatch.dylib 0x044d64d0 _dispatch_client_callout + 14
21 libdispatch.dylib
0x044c4eb7 _dispatch_root_queue_drain + 291
22 libdispatch.dylib 0x044c5127 _dispatch_worker_thread2 + 39
23 libsystem_pthread.dylib 0x04805dab _pthread_wqthread + 336
24 libsystem_pthread.dylib 0x04809cce start_wqthread + 30 ) libc++abi.dylib: terminating with uncaught exception of type NSException

I have tried all the solutions I could have found on SO, but none works. I am not even starting the player in the cells. Has been taking me for hours. Started out as a fun project that turned out to be headache. But I really like to know why and what's wrong here.

2

2 Answers

0
votes

Include below two line inside main queue:-

 dispatch_async(dispatch_get_main_queue,()^{

   MPMoviePlayerViewController *player = [self 
    setUp];
        if (player)
        {
0
votes

Don't do what you're doing - you're not recycling the movie player controller. The other answer here isn't going to solve your problem, it's just hiding it by making you run everything on the main queue.

Currently every time your app requests a cell, you create a new MPMoviePlayerViewController instance. This is bad because it defeats the purpose of a UITableView, which is to recycle its views. Instead, you should create a UITableViewCell subclass with a movie player controller inside of it. That way you only have to instantiate it once, and not every time the cell is scrolled onto the screen. Your current approach is really inefficient, and is going to result in all kinds of bad behavior.

The other thing you should probably look at is the class itself - you're using MPMoviePlayerViewController, but that class is specifically designed to be presented as a view controller in full screen. If you're embedding it inside a table view cell you shouldn't use it. Instead, you should use MPMoviePlayerController and embed its view in your table view.