When does Default.png get erased? - iphone

A Default.png in your application directory looks like a good way to get a zoom-in splash screen "for free". Zero LOC and everything happens before your applicationDidFinishLaunching gets called so your app launch feels snappy.
Unfortunately it erases itself a bit earlier than I would like: sometime after applicationDidFinishLaunching, but before I start drawing.
Does anyone know when it happens and I how can convince it to stay longer?

How do you start drawing? I think it goes away the first time the screen is drawn, which seems to be at the end of the first run loop.
You can create the effect of having it stay longer by showing an image view of Default.png. Something like (untested):
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 480.0)];
imageView.image = [UIImage imageNamed:#"Default.png"];
imageView.tag = 1234; // Must be a unique tag (int)
[window addSubview:imageView];
[imageView release];
//...
// When you want to hide/remove it:
UIView *defaultPng = [window viewWithTag:1234];
[defaultPng removeFromSuperview];
If you want it to be shown for some specific period of time, I imagine you'd use the second part of the code either in an NSTimer action method, or a method called using performSelector:withObject:afterDelay:. If the delay is unknown, you can use that code wherever you like.
Caveat: If your app is multithreaded, make sure it's called from the main thread. You can use performSelectorOnMainThread:withObject:waitUntilDone:.
Hope this helps.

Related

Animating imageview takes time for first time

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.

Issues setting up a back ground image and with UIImageView

On my iPhone app, I simply want to set a particular background image, which depends on whether it's an iPhone 5 or not.
So, I tried two approaches:
A) Using
self.view.backgroundColor = [UIColor colorWithPatternImage:backGroundimage];
B) Creating an UIImageView and setting up the image there. Code:
UIImageView *backgroundImageView = [[UIImageView alloc]initWithFrame:screenBounds];
[backgroundImageView setImage:[UIImage imageNamed:backGroundImage]];
[self.view addSubview:backgroundImageView];
But I am having issues with both of them:
Issues with Step A:
When I set the image through that way, I have to deal with the image scaling issues for different sizes of the screen. I use the following code to do the scalling:
UIGraphicsBeginImageContext(screenBounds.size);
[[UIImage imageNamed:backGroundImage] drawInRect:screenBounds];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
self.view.backgroundColor = [UIColor colorWithPatternImage:image];
Another issue from Step A is that the image appears quite blurry. It doesn't have the same sharpness to it.
Issues with Step B:
With this, the image looks really crisp and sharp - just the way it should look.
But when I switch to another view using the following code, strangely enough the UIImageView backgroundImageView still appears on the second one. The code I use to switch views is:
[self presentViewController:secondViewController animated:YES completion:nil];
I even tried [backgroundImageView removeFromSuperview], but that doesn't solve anything either.
So what am I doing wrong? And how can I set up a picture as my background which is dependent on the size of the iphone?
Plan B is a good plan. Presenting another view controller should and will definitely hide your image view. If it isn't happening, then it's a problem with the creation of secondViewController, unrelated to the background image on the presenting VC.
Before presenting secondViewController, log it:
NSLog(#"presenting %#", secondViewController);
I'll bet a dollar that it's nil. If I'm right, let's have a look at how you initialize secondViewController. That's the problem, unrelated to the background image view.
Okay, I finally fixed this issue, although the cause of this issue is still puzzling to me.
To fix this, I had to create an IBOutlet property for UIImageView and hook it up on the XIB file.
The reason I was programmatically creating the UIImageView is because the size of the UIImageView depends on what size iPhone they are using. But for the IBOutlet (let's call it as UIImageViewOutlet, I simply used [self.UIImageViewOutlet setFrame:] to get the size and location that I wanted.
I also discovered that one of the buttons that I was programmatically creating, was still visible in the secondViewController. I ended up creating an Outlet on the XIB file for that one as well and used setFrame on it to position it properly.
If anyone who knows the reason of this problem, I will be very grateful.

Quartz caching CGLayer

To quote from the CGLayer doc:
Quartz caches any objects that are reused, including CGLayer objects.
I am having problems with memory on large pages and am trying to implement a simple mechanism where views are released and recreated based on whether they are on/off screen.
Say for the sake of simplicity that I have a bunch of UIImages, created as the result of a network request, saved in an array somewhere. I create a UIImageView like so:
anImage = [anArray objectAtIndex:0];
UIImageView* imgView = [[UIImageView alloc] initWithImage:anImage];
[mainView addSubview:imgView]; // Quartz eats memory for view after first draw
[imgView release]; // owned by mainView now
[...] // wait a bit for draw cycle
[imgView removeFromSuperview]; // memory doesn't go down
When the imgView goes offscreen it is removedFromSuperview and released. Fine right? Nope- the CGLayer that exists in Quartz is not removed, because anImage still exists.
How can I get around this? The only way in this scenario is to create an image exactly the same behind Quartz's back with a different pointer address and delete the old image. And the only way to do this is to 'deep copy' the image (UIImage doesn't implement NSCoding) or to ask for it again over the network (slow).
What I am thinking is that I need to sqllite my images to a database and refetch them every time a view comes onscreen- but I would love to hear people's thoughts on this.
Here you increment imgView from 0 to 1.
UIImageView* imgView = [[UIImageView alloc] initWithImage:anImage];
In the next line, the mainView incrementes the reference count. (now it's 2)
[mainView addSubview:imgView]; // Quartz eats memory for view after first draw
Here, you release the imgView and the reference count goes back down to one.
[imgView release]; // owned by mainView now
I don't think your memory issues have anything to do with anImage. As long as imgView is a subview, it won't free that object, because it needs that object to draw to the screen.
What the following line means, is that if you programmatically draw to your CGLayer, Quartz with cache what you've drawn, so that you aren't constantly redrawing the same thing. It's not really related to adding subViews.
Quartz caches any objects that are reused, including CGLayer objects.

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?