Frame with 50 png in iPhone - iphone

I have a ViewController with 16 buttons. Each button loads a popover that show 50 frames renders in moving.
What is the best form to do it?
I know that imageWithName is bad because it load all images in cache, and for this reason im doing it with:
myAnimatedView.animationImages=[NSArray arrayWithObjects:
[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:#"%#0000",nombrePieza]ofType:#"png"]],
[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:#"%#0001",nombrePieza]ofType:#"png"]],
[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:#"%#0002",nombrePieza]ofType:#"png"]],
...
...
... [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:#"%#0050",nombrePieza]ofType:#"png"]],nil];
But when i load about 10 times the popover with differents frames, i have a leak of memory only on my device, but not in the simulator.
For this reason, i want know which is the best form to do it?
With a video? or with CAAnimation?
Thanks for help.

You better use a timer in this case, not to have memory problems
...
page = 1;
imageAnim = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];
[[self view] addSubview:imageAnim];
tim = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(avv) userInfo:nil repeats:YES];
...
- (void)avv {
UIImage *img = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:#"SplashAnimation %03d", page] ofType:#"png"]];
[imageAnim setContentMode:UIViewContentModeScaleToFill];
[imageAnim setImage:img];
page++;
if(page > maxNumberFrame) {
[tim invalidate];
}
}
This is an example to get ideas

imageNamed does not cause a leak in itself (although some previous discussions suggest it may have had bugs in pre iOS 4).
However, imageNamed will cache your images so that you don't load them for every instance if the image that you show. In your case, if you load the animation 10 times, I think you will see that each image gets loaded only once. Your current solution will force your images to be loaded every time.
Most importantly, the imageNamedmethod will transparantly handle the Retina version of the images, which you would have to do manually otherwise.
From the documentation:
This method looks in the system caches for an image object with the specified name and returns that object if it exists. If a matching image object is not already in the cache, this method loads the image data from the specified file, caches it, and then returns the resulting object.

Related

objective - C : Loading image from URL?

Sorry for question title. I can not find a suitable title.
I have UITableView content images from url when i open the UITableView the View did not show until the images loaded and that takes along time.
I get the images from JSON by php.
I want to show the table and then images loading process.
This is code from my app:
NSDictionary *info = [json objectAtIndex:indexPath.row];
cell.lbl.text = [info objectForKey:#"title"];
NSString *imageUrl = [info objectForKey:#"image"];
cell.img.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:imageUrl]]];
[cell.img.layer setBorderColor: [[UIColor blackColor] CGColor]];
[cell.img.layer setBorderWidth: 1.0];
return cell;
Sorry my english is weak.
Perform the web request on a separate thread, to not block the UI. Here is an example using NSOperation. Remember to only update the UI on the main thread, as shown with performSelectorOnMainThread:.
- (void)loadImage:(NSURL *)imageURL
{
NSOperationQueue *queue = [NSOperationQueue new];
NSInvocationOperation *operation = [[NSInvocationOperation alloc]
initWithTarget:self
selector:#selector(requestRemoteImage:)
object:imageURL];
[queue addOperation:operation];
}
- (void)requestRemoteImage:(NSURL *)imageURL
{
NSData *imageData = [[NSData alloc] initWithContentsOfURL:imageURL];
UIImage *image = [[UIImage alloc] initWithData:imageData];
[self performSelectorOnMainThread:#selector(placeImageInUI:) withObject:image waitUntilDone:YES];
}
- (void)placeImageInUI:(UIImage *)image
{
[_image setImage:image];
}
You have to use NSURLConnection and NSURLRequest. First create and show your empty table view (maybe with placeholder images, that are stored locally in the app). Then you start sending requests. These requests will run in the background and you (the delegate) will be notified when a request is completed. After that you can show the image to the user. Try not to load all the images at once if you have a lot of them. And don't load the ones that are invisible to the user, only load those if he scrolls down.
There is a UITableView lazy image loading example that Apple provided: https://developer.apple.com/library/ios/#samplecode/LazyTableImages/Introduction/Intro.html
Hopefully it's what you were looking for
This is among very common thing we do in our application.
You simply can have store the URLs in a persistent store e.g array or db & can get the images using Operation queue to download faster. You can set the priorities, cancel operations at anytime etc. Also, the application respond time will be quicker.

iPhone showing Different to the Simulator

.
Hello,
First of all, this question may seem similar to my last, but it isn't. For reference if you must compare it is here Previous Question
Now I have developed an app and it runs perfectly on the iPhone Simulator. It does not use anything the Simulator cannot handle.
I have a button, generated in code and it appears on my mac in the simulator, but not on the 2 tested devices. 1) iPhone4 and the 2) iPod Touch 4th Gen.
How is that possible?
-(void)popUpMenu
{
UIImage *image = [UIImage imageNamed:#"Menu01#2x.png"];
UIImage *selectedImage = [UIImage imageNamed:#"Menu02#2x.png"];
UIImage *toggledImage = [UIImage imageNamed:#"Done01#2x.png"];
UIImage *toggledSelectedImage = [UIImage imageNamed:#"Done02#2x.png"];
NSArray *buttons = [NSArray arrayWithObjects:b1, b2, b3, b4, b5, nil];
RNExpandingButtonBar *bar = [[RNExpandingButtonBar alloc] initWithImage:image selectedImage:selectedImage toggledImage:toggledImage toggledSelectedImage:toggledSelectedImage buttons:buttons center:center];
// RNExpandingButtonBar *bar = [[UIButton buttonWithType:UIButtonTypeRoundedRect] initWithArray:buttons];
[bar setHorizontal:NO];
[bar setExplode:NO];
[self.view addSubview:bar];
[self setBar:bar];
}
The array is a set of buttons that appear from this. The link to the Github is:
Github - RNExpandingButtonBar
Then I use this code in viewDidLoad method to display the button
[self popUpMenu];
Cheers Jeff
Check the case of the image names in your code and in your workspace, the device is case sensitive and OSX by default is not. Thats why it is working in your simulator and not on your device.

How to know when UIimageView finished loading?

In my view controller, how can I know when a certain UIImageView has finished loading (large jpeg from documents directory)? I need to know so that I can then swap a placeholder low-res imageview with this hi-res imageview. Do I need to create a custom callback to know this? Any way is fine.
By the way, here is a snippet of code where I load the image:
NSString *fileName = [NSString stringWithFormat:#"hires_%i.jpg", currentPage];
NSString *filePath = [NSString stringWithFormat:#"%#/BookImage/%#", [self documentsDirectory], fileName];
hiResImageView.image = [[[UIImage alloc] initWithContentsOfFile:filePath] autorelease];
UIImageView isn't doing any loading at all. All the loading is being done by [[UIImage alloc] initWithContentsOfFile:filePath], and your thread is blocked while the file is loaded (so the load is already complete by the time that call finally returns).
What you want to do is something like this:
- (void)loadImage:(NSString *)filePath {
[self performSelectorInBackground:#selector(loadImageInBackground:) withObject:filePath];
}
- (void)loadImageInBackground:(NSString *)filePath {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
UIImage *image = [[UIImage alloc] initWithContentsOfFile:filePath];
[self performSelectorOnMainThread:#selector(didLoadImageInBackground:) withObject:image waitUntilDone:YES];
[image release];
[pool release];
}
- (void)didLoadImageInBackground:(UIImage *)image {
self.imageView.image = image;
}
You would set up self.imageView to display the low-res image and then call loadImage: to load the high-res version.
Note that if you call this repeatedly before didLoadImageInBackground: gets called from earlier calls, you may cause the device to run out of memory. Or you might have the image from the first call take so much longer to load than image from the second call that didLoadImageInBackground: gets called for the second image before it gets called for the first. Fixing those issues is left as an exercise for the reader (or for another question).

Free memory after iphone animation

My app crashes due to memory building up after every animation.
Here is my sample code:
-(IBAction) shoot: (id)delegate{
[gun setImage:[UIImage imageNamed:#"animation_machin_guns_320x480_7.png"]];
UIImage *frame1 = [UIImage imageNamed:#"animation_machin_guns_320x480_1.png"];
UIImage *frame2 = [UIImage imageNamed:#"animation_machin_guns_320x480_2.png"];
UIImage *frame3 = [UIImage imageNamed:#"animation_machin_guns_320x480_3.png"];
UIImage *frame4 = [UIImage imageNamed:#"animation_machin_guns_320x480_4.png"];
UIImage *frame5 = [UIImage imageNamed:#"animation_machin_guns_320x480_5.png"];
UIImage *frame6 = [UIImage imageNamed:#"animation_machin_guns_320x480_6.png"];
UIImage *frame7 = [UIImage imageNamed:#"animation_machin_guns_320x480_7.png"];
gun.animationImages = [[NSArray alloc] initWithObjects:frame1, frame2, frame3, frame4, frame5, frame6, frame7,nil];
gun.animationDuration = 1;
gun.animationRepeatCount = 1;
[gun startAnimating];
[frame1 release];
[frame2 release];
[frame3 release];
[frame4 release];
[frame5 release];
[frame6 release];
[frame7 release];}
Releasing the frames doesn't seem to do the magic.
I tried using this http://kosmaczewski.net/projects/iphone-image-cache/ for image caching but i guess I don't know how to use it properly since the memory builds up faster than using imageNamed.
Replace [[NSArray alloc] initWithObjects:xxx]; with [NSArray arrayWithObjects:xxx];.
Currently, the array object is being retained twice (once effectively by alloc and once by gun.animationImages = xxx), but only released once (when the gun object is released, or the animationImages property is set to something new), meaning it will never be released.
The arrayWithObjects method returns an autoreleased object, meaning it doesn't need to be manually released by you.
If I were you I would think about only animating parts of the screen or perhaps compressing the images into low quality jpgs or something along those lines.

iPhone app memory leak with UIImage animation? Problem testing on device

I have an animation which works fine in the simulator but crashes on the device. I am getting the following error...
Program received signal: “0”.
The Debugger has exited due to signal 10 (SIGBUS)
A bit of investigating suggests that the UIImages are not getting released and I have a memory leak. I am new to this so can someone tell me if this is the likely cause? If you could also tell me how to solve it then that would be amazing.
The images are 480px x 480px and about 25kb each. My code is below...
NSArray *rainImages = [NSArray arrayWithObjects:
[UIImage imageNamed:#"rain-loop0001.png"],
[UIImage imageNamed:#"rain-loop0002.png"],
[UIImage imageNamed:#"rain-loop0003.png"],
[UIImage imageNamed:#"rain-loop0004.png"],
[UIImage imageNamed:#"rain-loop0005.png"],
[UIImage imageNamed:#"rain-loop0006.png"],
//more looping images
[UIImage imageNamed:#"rain-loop0045.png"],
[UIImage imageNamed:#"rain-loop0046.png"],
[UIImage imageNamed:#"rain-loop0047.png"],
[UIImage imageNamed:#"rain-loop0048.png"],
[UIImage imageNamed:#"rain-loop0049.png"],
[UIImage imageNamed:#"rain-loop0050.png"],
nil];
rainImage.animationImages = rainImages;
rainImage.animationDuration = 4.15/2;
rainImage.animationRepeatCount = 0;
[rainImage startAnimating];
[rainImage release];
Thanks
I'm pretty sure you're crashing because [NSArray arrayWithObjects:] returns an auto-released object which you're storing to rainImage. Then at the bottom you're releasing rainImage again, thus over releasing it.
The root of the problem is that you are running out of main memory because you have too many decompressed images in memory, see my answer to uiimage-animation-causing-app-to-crash-memory-leaks for the reason you should not be using UIImageView.animationImages.