Animating imageview takes time for first time - iphone

I am animating the ImageViews then the user taps a button. I have more than 40
images. The code I have used is
arr3 = [[NSArray alloc]initWithObjects:[UIImage imageNamed:#"Aperture_00000.png"],
[UIImage imageNamed:#"Aperture_00001.png"],
[UIImage imageNamed:#"Aperture_00002.png"],
...
[UIImage imageNamed:#"Aperture_00023.png"], nil];
imgv.animationImages = arr3;
imgv.animationDuration=2.0f;
imgv.animationRepeatCount =1;
The method to start the animation is:
-(void)animate {
[imgv startAnimating];
}
But it takes a lot of time when the user presses the button for the first time. What could be the solution for this?

The reason is following code:
arr3 = [[NSArray alloc]initWithObjects:[UIImage imageNamed:#"Aperture_00000"],[UIImage imageNamed:#"Aperture_00001"],[UIImage imageNamed:#"1.png",#"2.png",#"3png",#"4.png",#"5.png",#"6.png",#"7.png",#"8.png",#"9.png",#"10.png",#"11.png",#"12.png",#"13.png",#"14.png",#"15.png",];
What you can do is load this array somewhere else.
Note : This is a very memory consuming way of loading the images. Your app will definitely crash after you visit this class 2-3 times. Instead of this use some alternative. The easiest alternative I can suggest is load a image on UIImageView and change the image periodically. It'll give you animation effect.

I would suggest you rather doing it programmatically you should create animated gif image from the images. Here is online tool you can set speed and other parameters
http://picasion.com/
and use
https://github.com/arturogutierrez/Animated-GIF-iPhone
UIImageView category to display that gif image in that case you can save your CPU time.
Unhide the imageView when you want to play animation and hide when you want to stop.
I would suggest to give that at least a try.

Related

How to know/test when an animation has finished playing

I am starting an animation via a button press. Here is the code for the button:
-(IBAction)startAnimation:(id)sender{
stick.animationImages = [NSArray arrayWithObjects:
[UIImage imageNamed:#"photo 1.JPG"],
[UIImage imageNamed:#"photo 2.JPG"],
[UIImage imageNamed:#"photo 3.JPG"],
[UIImage imageNamed:#"photo 4.JPG"],
[UIImage imageNamed:#"photo 5.JPG"],nil];
[stick setAnimationRepeatCount:200];
stick.animationDuration = 0.5;
[stick startAnimating];
}
and when the animation is done, i want to have a button appear, to play another animation on the screen. How can i test or see when my animation is done playing? Thanks in advance!
You haven't told us what stick is, but it looks like a UIImageView. You can only call isAnimating to check whether the animation is still running but you don't get any notification and there's no delegate either. You can calculate the stop time (200 * 0.5) and thus set up a timer (add a little safety margin). This won't be 100% correct but it might be "good enough".
If you called your animation using blocks, you could use a completion block.
Here is a tutorial you can refer to which shows a couple different ways to call animation routines on iOS. This tutorial also shows what you can do for completion if you don't feel like using blocks (namely UIView's setAnimationDidStopSelector method).

ScrollView with large images scrolls too slowly

When I am scrolling images frequently in a UIScrollView then after some images, the next image takes time to load... it's not taking too much time but looks odd.
Suppose I have 27 images in a scrollView. When I start to scroll these images, for 1 or 2 images it scrolls smoothly but when I scroll again to see the 3rd image it takes time to load. Then when I start the images scrolling again from the 3rd image, it behaves like before.
I can't load all 27 images at a time or my app crashes.
When I slowly scroll the scrollview then I don't have this problem.
My code is below:
//Taking image view for 27 images;
int x=0;
for(int i = 1; i<=27; i++) {
imageView = [[UIImageView alloc] init];
imageView .frame = CGRectMake(x,0,768,1024);
imageView.tag=i;
imageView.image=nil;
imageView.userInteractionEnabled=YES;
[contentView addSubview:imageView];
x+=768;
}
//setContentOffset of the scrollView -->ContentView
[contentView setContentOffset: CGPointMake((imageNumber-1)*768, 0) animated: YES];
//desire image which i want to see from the start of the scrollview
pageNumber=imageNumber;
int pageBefore=pageNumber-1;
int pageAfter=pageNumber+1;
//Views for image
for( UIImageView * views in [contentView subviews]){
if(views.tag==pageNumber){
if(views.image==nil){
NSLog(#"entering");
views.image=[UIImage imageNamed:[ NSString stringWithFormat:#"%d.jpg",pageNumber]];
[views.image release];
}
}
if(views.tag==pageBefore){
if(views.image==nil){
views.image=[UIImage imageNamed:[ NSString stringWithFormat:#"%d.jpg",pageBefore]];
[views.image release];
}
}
if(views.tag==pageAfter){
if(views.image==nil){
views.image=[UIImage imageNamed:[ NSString stringWithFormat:#"%d.jpg",pageAfter]];
[views.image release];
}
}
My alarm bells rang when I saw this;
imageView .frame = CGRectMake(x,0,768,1024);
Apart from the space before .frame, are you saying that your images are 768x1024? That's HUGE and I suspect your problems are memory ones rather than code ones.
Be aware that in particular, using UIImage imageNamed: is likely to cause grief with such large images as that method caches the images in memory. You may wish to consider using alternative methods that load the image from a file each time.
You should try use the EGOImageView, it has caching build in which might help with your performance issues. You can implement a placeholder image to show the user that an image is being prepared for viewing. The image will load in another thread before being displayed, giving you smoother scrolling performance. The EGOImageView is part of the EGOImageLoading library.
https://github.com/tastefulworks/EGOImageLoading
As an alternative you could create your own lazy loading mechanism to increase scrolling performance. E.g. once a user stops scrolling for a second, start loading the image, otherwise display placeholder image if not yet the correct image is cached.
Edit: when thinking more about this issue, I realize caching won't help much (since you already load image from disk), but the asynchronous loading of images should help with the scroll performance, so make use of NSThread or NSOperation to load the image in a background thread, then notify the main thread that the image is loaded and ready for display.

Memory Management

I need a clarification from all of you,That is I am implementing an iPad application. In that I tried to download and animate the images. The image count should be more than 100,000.The code I used to download and adding to the view is as follows.
UIImageView* imageView=[[UIImageView alloc]initWithFrame:CGRectMake(0, 0,100,100)];
NSData *receivedData=nil;
receivedData = [NSData dataWithContentsOfURL:[NSURL URLWithString:#"http://path/prudently/iphone/image_s/e545afbf-4e3e-442e-92f9-a7891fc3ea9f/test.png"]];
imageView.image = [[UIImage alloc] initWithData:receivedData] ;
[subView addSubview:imageView];
[imageView release];
But I am getting exception after I successfully added more than 8000 image to my subview. I am getting exception at getting data from the url. And one more thing I am not releasing the subview because once I downloaded them I need to animate the subview.
Please give me your suggessions
Thank you,
Sekhar Bethalam.
100,000 images would seem a lot for desktop applications, let alone a smart phone like an iPhone. Is there not another approach you can take to solve this problem that wouldn't need such a high resource count?
You can write the URL , images or something to a cached file, and divide some pages to animate the images...
When the user press a page link , application read and animate the images of this page, images of the page which user don't use need not display.
The only way you are going to accomplish this is to dynamically create and destroy the UIImageViews as they are needed on the screen. The iPhone/iPad/iAnything are incapable of doing what you want because of the limited memory available on the device.

Adding UIImage with the same image multiple times and removing it all in one code

Im having a bit of trouble right now adding the same image multiple times and removing it all at one time after the gamelooop.
I manage to add the image by creating 1 UIImageview for every image but i know thats its not the practical way memory wise since im allocating a lot of uiimageview with the same image.
I use this code to load the image:
UIImageView *imgView1 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"correct.png"]];
UIImageView *imgViewn = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"correct.png"]];
CGRect imgRect = CGRectMake((touch.x-20), (touch.y-20), 40, 40);
[imgView1 drawInRect:imgRect];
[imgViewn drawInRect:imgRect];
[imgView1 release]
[imgViewn release]
Basically i use this to add image base on the location of the usertouch made on the subview (with image). If the users set of touches are correct this is where the game loops and show another image for the user to touch.
But after the new image load the "correct.png" image which is added on the previous touch is still on view.
Can someone show me a correct way to do this coz im kinda new to programming but i know that im gonna have a memory problem later if i keep on allocating image every time a user touch the screen.
Thanks in advance.
If you're trying to merely move an image (or series of images) through each run of the gameloop, rather than creating and removing them all each time, perhaps create the series of N images only once.
When the touches or gameloop begins, draw the images in the rectangles you're calculating from the touch event, and then when the loop is over, set the hidden property on the object to YES or NO (not sure exactly what your objective is).
It's hard to give you code without more details on what you're doing, but the basic idea is this:
When you first start the program/view, create your N images, and set imageView.hidden = YES;
On each loop, call the [imageView drawInRect:imgRect] method for each image, and set imageView.hidden = NO;.
When the view/program is done, call the [imageView release] method on each object.

How to pause a UIImageView animation

I have an animation that I'm displaying using a UIImageView:
imageView.animationImages = myImages;
imageView.animationDuration = 3;
[imageView startAnimating];
I know I can stop it using stopAnimating, but what I want is to be able to pause it. The reason is that when you call stop, none of your animation images are displayed, whereas I would like the last one that is up at the time when I hit a button to stay up.
I have tried setting the duration to a much larger number, but that causes all the images to disappear as well. There must be a really basic way to do this?
This code will pause an animated object at its current position in the animation process. If you record other variables like the time or progress or whatever you need, it should be fairly trivial to resume the animation again.
UIView *viewBeingAnimated = //your view that is being animated
viewBeingAnimated.frame = [[viewBeingAnimated.layer presentationLayer] frame];
[viewBeingAnimated.layer removeAllAnimations];
//when user unpauses, create new animation from current position.
Hmmm...since no one seems to know I guess it's not possible.
I went ahead and wrote my own UIView, with a UIImageView subview, that uses an NSTimer to switch between images. The advantage of this is that I can pause and resume the timer at my leisure, and performance doesn't seem to be an issue.
#oddmeter just a little edit:
animatedView.animationImages = images; //images is your array
[animatedView startAnimating];
//Then when you need to pause;
[animatedView stopAnimating]; //Important!!
animatedView.image = [images objectAtIndex: 0];
This should do the trick: https://developer.apple.com/library/ios/#qa/qa2009/qa1673.html
It basically tells you what you need to do to pause/resume any CALayer based animation.
If you feel uncomfortable using CALayer methods on UIImageView controlled animation, you could always just make the UIImage array based animation yourself. The code needed is very short, you can take it from here: http://rssv2.blogspot.com/2011/04/animating-series-of-images-with-calayer.html
Another option is to set the image property as well as the animationImages property. Doing this will display the static image when the UIImageView has its animations stopped.
Assuming your class is a subclass of UIImageView and have an NSMutableArray of images, do the following:
self.animationImages = images;
//yes, I'm skipping the step to check and make sure you have at least one
//element in your array
self.image = [images objectAtIndex: 0];
Maybe you can take a screenshot of the last animated image and display that?