I have an app with a news feed screen, like the one in the facebook app. For this, I have made a custom cell, which has a contentView which is a UIView. This contentView gets initialized for displaying text, an image or video. This is done in the class for the custom cell. For the video, I'm trying to add MPMoviePlayerViewController as a subview to the cell's contentView:
MPMoviePlayerViewController *player = [[MPMoviePlayerViewController alloc] initWithContentURL:nil];
player.view.frame = self.contentView.frame;
player.view.tag = kVideoView;
[self.contentView addSubview:player.moviePlayer.view];
Then, when I load that cell in the tableviewcontroller, I want to give it contentURL, like this:
MPMoviePlayerViewController *controller = (MPMoviePlayerViewController *)[cell viewWithTag:kVideoView];
controller.moviePlayer.contentURL = [NSURL URLWithString:postInfo.uri];
return;
This crashes the app with an error:
-[MPMovieView moviePlayer]: unrecognized selector sent to instance
How do I fix this?
As you are adding player.moviePlayer.view to content view.
So while retrieving you will get reference to player.moviePlayer.view only not MPMoviePlayerViewController.
My suggestion is don't create multiple MPMoviePlayerViewController instance. You can add some UIButton or UIImageView on cell with snapshot of particular video. And while playing only you can create MPMoviePlayerViewController instance and play your video
Related
I have a YTPlayerView inside of my subclass of UITableViewCell. In my UIViewController I call [cell.youtubeView loadWithVideoId:f.videoID]; from my tableViewDelagate willDisplayCell method. The problem is that when I have many cells in my tableView some of them stay white instead of the YouTube content!
Youtube API recommends when reusing the YTPlayerView to load the content by calling
[cell.youtubeView cueVideoById:f.videoID startSeconds:0 suggestedQuality:kYTPlaybackQualityHighRes]; instead. Unfortunately, this method doesn't load YouTube content at all.
Anybody came across the same issue? Any known solution?
I was thinking to load first time the content with loadWithVideoId and then cueVideoById but that didn't work.
I had this problem using YTPlayerView instances in UIColectionViewCell instances. Ultimately what I had to do was stop the video in didEndDisplayingCell ([self.playerView stopVideo]). Then in prepareForReuse (or optionally in cellForRowAtIndexPath), nil out your playerView, and in cellForRowAtIndexPath re-init the player and load the video by id.
I used YTPlayerView in UICollectionView(Similar to your case).
In my case, YTPlayerView got black when it was drawn in reused UICollectionViewCell(load properly on firstly initiated cell).
YTPlayerView got black is because -loadWithVideoId:playerVars: is called twice before the firstly invoked method is complete.
I checked white YTPlayerView is for not loaded video, so I recommend checking -loadWithVideoId: or similar methods called properly in somewhere.
Swift 3
I had the same issue. My problem was that the method load(withVideoId: videoId) was called several times (because of the cellForRow called several times while scrolling).
I solved this by creating a Boolean and making sure the load(withVideoId: videoId) is called only once :
1) In the cell class, create a global Boolean
var isAlreadyPlaying : Bool = false
2) When you want to play your video, we set our boolean to avoid playing it several times :
func loadVideo() {
//Making sure we are not playing the video several time
if isAlreadyPlaying == false {
//Creating vars (optional)
let playerVars = ["playsinline": 1, "autoplay": 1, "autohide": 1, "controls" : 1, "showinfo" : 0, "modestbranding" : 1, "rel" : 0]
// Launching the video
youtTubeView?.load(withVideoId: videoId, playerVars : playerVars)
// Force to not play the video again
isAlreadyPlaying = true
}
}
Here is another approach, purists won't like it, but I couldn't find out how to properly free/re-init the YTPlayerView created in my custom UICollectionViewCell.
Considering you will only play one video at time, because two several instances of YTPlayer won't play simultaneously, you just have to hide reused cells with video's thumbnail. Simply put an UIImageView above the YTplayerView in your sublclass of UICollectionViewCell xib, and set the thumbnail in it:
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
//... load customcell xib, manage cellId etc.
// set video id that will be read by the custom cell
[cell setVideoId:cellVideoId];
// set above UIImage
NSData * thumbnailData = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString: videoThumbnailURL]];
UIImage * videoThumbnail = [UIImage imageWithData: thumbnailData];
[cell.thumbnailImage setImage:videoThumbnail];
return cell;
}
There, in custom UICollectionViewCell .m file you just need to implement a button that launch the video when clicked ...
- (IBAction)clickPlay:(id)sender {
if (videoId != nil){
[ccellYTPlayerView loadWithVideoId:videoId playerVars:playerVars];
// Hide thumbnail image to reveal the YTPlayerView
[thumbnailImage setHidden:true];
}
}
... and configure reusability of this custom cell, which works flawlessly for native obvjects :
-(void) prepareForReuse{
[super prepareForReuse];
// preparing UIImage to host another thumbnail
thumbnailImage.image = nil;
[thumbnailImage setHidden:false];
}
This way, YTplayers can appear in other cells, no one will see it because hidden by the thumbnail, and the sound produced is not a problem because user will assume that it comes from the original cell (which is not on screen anymore because of scrolling).
I know that's not really clean, but it helped me so far, YTPlayer instance is not so easy to recycle.
I want to add Video file in my iPad application.
I have use MPMoviePlayerController for this it work fine.
but i have one problem this controller is covering hole WINDOW of iPad.
I want my UIViewController should contain one textView, Navigation Bar, one Running Video file,
and four UIButton. Have can i achive this?
You can done this by add that MPMoviePlayer as subView of your view, means addSubview on your view with fix frame.
like this,
MPMoviePlayerController *player =
[[MPMoviePlayerController alloc] initWithContentURL: myURL];
[player prepareToPlay];
[player.view setFrame: myView.bounds]; // myView is your parent view which hold your player
[myView addSubview: player.view];
[player play];
For more references check this.
I want to add MPMoviePlayerController to a UIView.
first, I put a view in xib file, named youTubeView. youtubePlayer is the MPMoviePlayerController.
[youtubePlayer.view setFrame:youTubeView.frame];
[youTubeView addSubview:youtubePlayer.view];
[youtubePlayer play];
I want the view of youtubePlayer overlay on youTubeView. but the view of youtubePlayer goes wide, it just overlay a part of youTubeView. why ?
Try this
[youtubePlayer.view setFrame:youTubeView.bounds];
[youTubeView addSubview:youtubePlayer.view];
[youtubePlayer play];
Just assign the scaling mode for the movie like this youtubePlayer.scalingMode = MPMovieScalingModeFill;
This will solve your problem.
Happy Coding:)
I have an iPad app that has a movie preview view in the top half of the screen and thumbnails in the bottom half of the screen. When the user taps a thumbnail that movie starts playing in the movie preview view using a MPMoviePlayerViewController with control style MPMovieControlStyleEmbedded. The embedded style has the built in functionality of allowing the user to tap a fullscreen button to show the movie in fullscreen.
All of the above functionality works great but I want to always show a watermark over movies in the preview and fullscreen views. The watermark shows correctly in the preview view when I add a label to vcMoviePlayer.view but I cannot get that label to show over the movie in fullscreen mode after the fullscreen button has been pressed. I'm adding the label to vcMoviePlayer.view (making sure to bring the label to the front) when the movie player sends the MPMoviePlayerDidEnterFullscreenNotification but it still does not appear. Has anyone else seen this behavior? Does anyone know how to get a view to appear over a movie playing in fullscreen after the fullscreen button has been tapped? I've burned a lot of time trying to figure this out and any help is very very appreciated. Thanks!
I use this code and works on iOS 5 and iOS 6
UIWindow *window = [[UIApplication sharedApplication].windows objectAtIndex:0];
UIView * videoView = [[window subviews] lastObject];
UIView *customView = [[UIView alloc] initWithFrame:CGRectMake(0.0f,0.0f,100.0f,100.0f)];
[videoView addSubview:customView];
On iOS 5 you have to remove the customView on MPMoviePlayerWillExitFullscreenNotification
When in fullscreen mode, MPMoviePlayerController does not use the supplied superview anymore but directly displays itself on the current (key) window.
For finding something you can put your view/s on once the player is in fullscreen mode, do as follows:
UIWindow *window = [UIApplication sharedApplication].keyWindow;
if (!window)
{
window = [[UIApplication sharedApplication].windows objectAtIndex:0];
}
Now you can put your custom views on top of that window and it will be visible while MPMoviePlayerController is being in fullscreen mode.
UIView *customView = [[UIView alloc] initWithFrame:CGRectMake(0.0f,
0.0f,
100.0f,
100.0f)];
[window addSubview:customView];
For finding the right moment to add/remove your custom views, register the following notifications and do it within the registered handlers:
MPMoviePlayerDidEnterFullscreenNotification and MPMoviePlayerWillExitFullscreenNotification
I have successfully put a MPMoviePlayerController in a UIPopoverController by doing:
NSString *filenameString = [NSString stringWithString:[[helpVideosArray objectAtIndex:tagNumber] objectForKey:VIDEO_FILE_NAME]];
HelpVideoPopover *helpVideoPopover = [[HelpVideoPopover alloc] initWithVideoFilename:filenameString PreviewFrameView:self];
currentPopover = [[[[UIPopoverController alloc] initWithContentViewController:helpVideoPopover] retain] autorelease];
[currentPopover setPopoverContentSize:CGSizeMake(320, 240)];
[currentPopover presentPopoverFromRect:((UIButton*)sender).frame inView:previewView permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
currentPopover.passthroughViews = [NSArray arrayWithObject:((HelpVideoPopover*)[currentPopover contentViewController]).movieController.view];
The problem is that when the user wants to view the video fullscreen(and I allow that) that the popover view is on top of the fullscreen video. So my question is that is there another I'm supposed to be doing this. Or maybe when I display the popover I just use a blank one and overlay a movie player on top of it from the parent view controller? I would really like to keep the movie player logic inside the popover view controller though.
Without knowing the details of your application i would imagine you could do this in several ways.
You could either open the video in a fullscreen modal view - This would cover the popover.
If you're displaying the fullscreen video in the detail-view behind the popover, then you could do something as simple as just hiding the popover once the fullscreen video has been shown.