play multiple videos smoothly in CollectionView like Facebook - objective-c

I'm trying to implement an AVPlayer into each row of a Collection cell but I don't find any good documentation.Any idea where I can find some?

Try this code
self.moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"something" ofType:#"mp4"]]];
[self.moviePlayer.view setFrame:CGRectMake(0, 0, 320, 320)];
[self.moviePlayer play];
[self.view addSubview:self.moviePlayer.view];
self.movieplayer is an instance of MPMoviePlayerController (not MPMoviePlayerViewController). In my experience it's important to declare it as a property (like so: #property (strong, nonatomic) MPMoviePlayerController *moviePlayer;) rather than a simple ivar, because sometimes it just doesn't work if it's an ivar
setting the frame is also important, because if we don't set it, the video will not appear at all. The frame can be anything as long as what you define is within the bounds of your view
Important: As above, when defining the URL use NSURL's URLWithString method if you want to access the file through a network and use NSURL's fileUrlWithPath if you have the file locally!

Related

UIView cant be accessed from different method

I declare a a uiview in my header file of a uiviewcontroller like so:
#property (strong, nonatomic) UIView *loadLoading;
And initiate itin viewdidload:
loadLoading = [[UIView alloc] initWithFrame:self.view.bounds];
loadLoading.backgroundColor = [UIColor blueColor];
[self.view addSubView:loadLoading];
This works fine. But at another point in my program i want to remove this subview. But for some reason, it doesnt get removed.
NSLog(#"%#",loadLoading.backgroundColor);
[loadLoading removeFromSuperview];
(I know it gets to that point and loadLoading is accessible because the log does work.
If you are getting the NSLog(#"%#",loadLoading.backgroundColor); worked.
Then this code [self.loadLoading removeFromSuperview]; should be work, else there is some weird bug.
Here is another approach:
Add a tag to the view when you add it to the parentView.
loadLoading = [[UIView alloc] initWithFrame:self.view.bounds];
[loadLoading setTag:7];
Use that tag to remove it from the parentView.
[[self.view viewWithTag:7] removeFromSuperView];
Found the issue.
I didnt provide enough details in my question. I was calling this method from notificationcenter, which loads on a different thread. So i had to first do performSelectorOnMainThread which worked
Try:
[self.loadLoading removeFromSuperview];

Unable to play local video from iPhone

I'm having trouble playing a video on the iPhone. I have a file in the app bundle and I am trying to play it in a MPMoviePlayerController but it is just displaying a black screen. This is the following code:
-(UIView*)createVideoPlayerOfWidth:(CGFloat)width
{
// The width for one of these can be half of the max width
//CGFloat widthAndHeight = width / 2.0f;
// TODO: Create a video player
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"myVideo" ofType:#"mov"]];
MPMoviePlayerController *playerController = [[MPMoviePlayerController alloc] initWithContentURL:url];
[playerController prepareToPlay];
[playerController setShouldAutoplay:NO];
[playerController setScalingMode:MPMovieScalingModeAspectFit];
[playerController setControlStyle:MPMovieControlStyleEmbedded];
[playerController setRepeatMode:MPMovieRepeatModeNone];
// Resize the thumbnail of the video
[[playerController view] setFrame:CGRectMake(0, 0, width, width)];
return [playerController view];
}
It is returning a valid URL (pathForResource would return nil if it couldn't find the file). I am displaying it to the screen by just adding a subView (the view returned by the function) to a scroll view. I've been trying to solve this for ages now and am getting nowhere. Any help is much appreciated.
Thanks!
Make sure you are retaining a reference to the MPMoviePlayerController instance:
If this is an ARC project, then playerController will be destroyed when createVideoPlayerOfWidth returns, and your video probably won't play. You should store the player in a strong instance variable or property.
You could add something like this to the top of your view controller file:
#interface MyViewController ()
#property (nonatomic,retain) MPMoviePlayerController *player;
#end
And insert this after you create the MPMoviewPlayerController instance:
self.player = playerController;
If you're not using ARC, this is probably not the problem, but you should still keep a reference in an instance variable, so that you can release it later.

Generate a website screen capture in ios

As the question says, on a iOS device if a user inputs a URL in uitextfield I want to generate a thumbnail capture of this URL. How can this be achieved? Unfortunately I don't have a clue where to start from.
Of course one way I can do this is to send this URL to backend & get the image screenshot from there. I know how one can do this kinda stuff using python or php. But I want to avoid the extra round trip to my backend servers.
I want something like - (uiimage *)screenCapture:(nsurl *)url
As per your question i think you'll want to manipulate the generated screenshot afterwards. You'll add a UIWebView programmatically to load the needed URL then take a snapshot of the loaded web page then remove the UIWebView
Here are the steps
a UIImageView to your viewController and connect it to your viewController class
#property (weak, nonatomic) IBOutlet UIImageView *image_Thumbnail;
having the URL in a variable named "webPageUrlString" add the following lines
UIWebView* webView = [[UIWebView alloc] initWithFrame:self.view.frame];
webView.backgroundColor = [UIColor redColor];
NSURL *websiteUrl = [NSURL URLWithString:**webPageUrlString**];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:websiteUrl];
[webView loadRequest: urlRequest];
webView.delegate = self;
[self.view addSubview:webView];
right now you have requested to load the URL but can't render the snapshot unless the web page is fully loaded,so you'll need to wait for the web page loading notification.In order to that you must subscribe to the webView delegate in the header file like that
#interface ViewController : UIViewController<UIWebViewDelegate>
Now you'll implement the "webViewDidFinishLoad" and take the snapshot you want then hide and remove the webView.
-(void)webViewDidFinishLoad:(UIWebView *)webView{
viewImage = [[UIImageView alloc] initWithFrame:self.view.frame];
viewImage.backgroundColor = [UIColor greenColor];
UIGraphicsBeginImageContext(webView.bounds.size);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
viewImage.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[webView setAlpha:0];
[webView removeFromSuperview];
[self.view addSubview:viewImage];
}
Now you have the screenshot you want in the property called "viewImage" and you can do what ever you want with it ;)

Can't access UIView in external method

I'm new to Objective-C, so the way I'm going about this might be ludicrous, but here goes:
I have a login form in my iPhone application. When the user has entered their credentials, they hit Done in the top right corner, which triggers an IBAction and a custom progress indicator pops up. I've created this indicator by using a class containing an instance method named showProgressIndicator. showProgressIndicator creates and returns a UIView, which I then add to my view like so:
ProgressIndicatorElement *ProgressIndicator = [[ProgressIndicatorElement alloc] init];
box = [ProgressIndicator showProgressIndicator];
[self.view addSubview:box];
I have of course declared box as a UIView in my header file. The progress indicator pops up beautifully and in the meantime I'm doing a behind-the-scenes URL request that, when finished, calls another method in my view controller named receivedServerResponse. Now, what I want to do is to remove the progress indicator, which is why I'm doing this:
- (void)receivedServerResponse {
[box removeFromSuperview];
}
But nothing happens at all. I'm not getting any errors or warnings, and the code is being highlighted just as if everything was running smoothly. I've tried retaining the indicator in my IBAction, but that doesn't help either.
Hope you can help out!
Updated:
Here is the showProgressIndicator method:
- (UIView *)showProgressIndicator {
box = [[UIView alloc] initWithFrame:CGRectMake(85, 190, 210, 140)];
box.backgroundColor = [UIColor colorWithRed:0.0 / 255 green:0.0 / 255 blue:0.0 / 255 alpha:.6];
box.layer.cornerRadius = 8;
UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
spinner.layer.frame = CGRectMake((box.layer.bounds.size.width - spinner.layer.bounds.size.width)/2, 20, spinner.layer.bounds.size.width, spinner.layer.bounds.size.height);
[spinner startAnimating];
[box addSubview:spinner];
UILabel *titleInBox = [[UILabel alloc] initWithFrame:CGRectMake(0, 65, 150, 20)];
titleInBox.font = [UIFont boldSystemFontOfSize:16];
titleInBox.textColor = [UIColor whiteColor];
titleInBox.textAlignment = UITextAlignmentCenter;
titleInBox.backgroundColor = [UIColor clearColor];
titleInBox.text = #"Authorizing...";
[box addSubview:titleInBox];
return box;
}
Second update:
#Deepak just pointed out in the comments that I might be running two different instances of my view controller, which actually seems to be the case. In the external class that handles the aforementioned URL request, I get back to the view controller's receivedServerResponse method by doing this:
- (void)requestFinished:(ASIHTTPRequest *)request {
NSString *responseString = [request responseString];
SignInViewController *viewController = [[SignInViewController alloc] init];
[viewController receivedServerResponse];
}
Without spreading myself too thin (probably too late ;)), ASIHTTPRequest is set up so that if you call one method that performs an asynchronous URL request, a predefined method called requestFinished (above) is called, which is why I've had to call my view controller this way, because I can't access the returned value in an easier way (that I know of).
Creating a new instance of SignInViewController is not the correct way. It only seems correct to maintain a weak reference (assigned property) of the SignInViewController object. Say your class is RequestHandler.
#interface RequestHandler: [..] {
}
#property (nonatomic, assign) SignInViewController * signInViewController;
#end
#implementation RequestHandler
#synthesize signInViewController;
[..]
- (void)requestFinished:(ASIHTTPRequest *)request {
NSString *responseString = [request responseString];
[signInViewController receivedServerResponse];
}
#end
So when you're creating a RequestHandler object within the SignInViewController instance, you do,
RequestHandler * requestHandler = [[RequestHandler alloc] init];
requestHandler.signInViewController = self;
[..]
Note, you can also look at delegation and notifications.
I think part of the problem may be with memory management. If showProgressIndicator does not return an autoreleased object, try releasing box after adding it as a subview, like so:
[self.view addSubview:box];
[box release];
box may not disappear if box is not deallocated when removed from the superview.
My other recommendation is that instead of doing it the way you are doing, creating a view, adding it, and then trying to removing it, you might want to try adding box as a subview when the login view is created and setting its hidden property to YES then unhiding it later when necessary.
Based on your update: You have some memory management issues in showProgressIndicator. Whenever you alloc an object, you should release it. In this case, release all of your variables after adding them as subviews as I mentioned above. box however should be returned as an autoreleased object since showProgressIndicator does not know when it will need to be released. For that you should replace return box; with return [box autorelease];
You need to send the activity indicator a stopAnimating message when you want the animation to stop. There's no need to remove it from its superview; instead, simply make sure that its hidesWhenStopped property is set to YES.
How about adding box view on window in appDelgate? Give a tag to your boxView and in the remove method get the boxView back by using tag. For example if you give tag 99
- (void)receivedServerResponse {
UIView *box = [window viewWithTag:99];
[box removeFromSuperview];
}
also you don't need to declare an instance variable in header file. and you can access progress indicator anywhere in the application.
Without spreading myself too thin (probably too late ;)), ASIHTTPRequest is set up so that if you call one method that performs an asynchronous URL request, a predefined method called requestFinished (above) is called, which is why I've had to call my view controller this way, because I can't access the returned value in an easier way (that I know of).
ASIHTTPRequest calls -requestFinished: on the object you set as the request's delegate. You should design your classes such that this delegate object either has a reference to the view controller you want it to act on or has some means of notifying that view controller to take action.
The easiest solution might be to make the controller the request's delegate.

MPMoviePlayerViewController Black Screen issue!

I have this code trying to run a video on the iPhone 4 Simulator.
The problem is that looks like it loads the player but half a second later loads a back screen on top of the whole application disabling touch and everything, and it looks like it does not play the video also, because I can't hear anything.
Any ideas?!
MPMoviePlayerViewController *mp =
[[MPMoviePlayerViewController alloc] initWithContentURL:videoUrl];
if (mp) {
mp.moviePlayer.scalingMode = MPMovieScalingModeFill;
mp.moviePlayer.movieSourceType = MPMovieSourceTypeFile;
[mp.moviePlayer play];
[self presentMoviePlayerViewControllerAnimated:mp];
[mp release];
}
I believe the problem is caused by releasing the MPMoviePlayerViewController. Simply retain the controller until you are done with it.
Prior to the "[mp release];" add this line to save the value away.
self.moviePlayerViewController = mp;
Then update your dealloc method to do the release:
- (void)dealloc {
[_moviePlayerViewController release], _moviePlayerViewController = nil;
[super dealloc];
}
Add the synthesize to the top of your .m file:
#synthesize moviePlayerViewController = _moviePlayerViewController;
Add the defination to the #interface of your .h file:
MPMovieViewController *_moviePlayerViewController;
Add the property to your .h file:
#property (readwrite, retain) MPMovieViewController *moviePlayerViewController;
You may need some headers in your header:
#import <MediaPlayer/MediaPlayer.h>
#import <MediaPlayer/MPMoviePlayerViewController.h>
You may also need to balance your "presentMoviePlayer" call with the dismiss somewhere:
[self dismissMoviePlayerViewControllerAnimated];
Phew, code everywhere. Anyway, if you are finished with the resource early, you may be able to release it sooner by using NotificationManager to watch for MPMoviePlayerPlaybackDidFinishNotification. There are many examples of that, so I won't repeat it.
Hope this helps.
This is the code I'm using:
MPMoviePlayerViewController *movieViewController = [[MPMoviePlayerViewController alloc] initWithContentURL:[NSURL URLWithString:contentUrl]];
movieViewController.moviePlayer.movieSourceType = MPMovieSourceTypeFile;
[self presentMoviePlayerViewControllerAnimated:movieViewController];
[movieViewController release];
It seems to work fine for me. Two notes:
Some simulators (like the current iOS 5.0) crash when playing a movie, but it works on a real device
if you leave out the movieSourceType part, a black screen is shown for about a second before the movie starts