app crash after allocation of 10 mb memory - objective-c

We are facing crash in my app. I check on instrument that after allocation of 10 mb app get crash at any point(not any fix instance).
I am allocating approax 1000 label every time i click on any button in a for loop and release it after work done please help. In instrument there is no memory leaks but still app crash after allocationg 10 mb of memory.
this is a code i am applying on click of a button
is this a right way??????
-(IBACTION) btnShow
{
for (UIView *obj in scrollview.subviews)
{
[obj removeFromSuperview];
}
int x;
int y=0;
for (int j=0; j<12; j++) {
x=0;
// Do any additional setup after loading the view, typically from a nib.
for (int i=0; i<1000; i++) {
UILabel * lblUsage=[[UILabel alloc] initWithFrame:CGRectMake(x, y, 75, 45)];
lblUsage.text=[NSString stringWithFormat:#"%d",i];
lblUsage.textColor=[UIColor lightGrayColor];
lblUsage.numberOfLines=2;
lblUsage.font = [UIFont systemFontOfSize:14.0];
lblUsage.textAlignment=UITextAlignmentCenter;
lblUsage.backgroundColor=[UIColor colorWithPatternImage:
[UIImage imageNamed:#"labelBox.png"]];
lblUsage.layer.borderColor = [UIColor blackColor].CGColor;
lblUsage.layer.borderWidth = 0.5;
[scrollview addSubview:lblUsage];
[lblUsage release];
x+=75;
}
y+=40;
}
scrollview.contentSize=CGSizeMake(x, 1000);
}

you receive memory warning in the above code
memory warning level 1 is first warning where you should remove unnecessary view to clean up memory
memory warning level 2 is the limit.. remove something now or your app will quit within few seconds.
memory warning level 3 is sent when the system has decided to quit your app! due to memory usage

Sorry, but you'll just have to take a completely different aproach - which will
make your code much more complex. There's no way you could get around by creating
12.000 labels with pattern background.
initially you would create only those labels that are shown on screen and one or
two rows (and columns) of those that could soon appear on screen while the user is scrolling
then you'll do most of your work in viewDidScroll by creating and disposing of lables on the fly.
here your code should decide which labels can be disposed of (when they are far enough from visible screen)
and which have to be created because they could appear soon on screen (depends on current location of content.
offset)
Take a look at ScrollViewSuite as example for tiling. It's not exactly what you're looking
for but it should give you a kickstart.

Related

New scene is created from its frame size but it keeps getting smaller each time. Why?

I am writing a game in which the user must prevent falling objects (rocks) to pass the button of the screen using some plates, each click make a plate at that position but he can only have 5 plates at each time and clicking on sixth point vanished the first plate while creating a new one.
That was a brief on how my game mechanics work.
Here is the part of my code that counts falling objects(sprites) using physics and if they became more than 10 a game over message will be shown and the code restarts the game, a new game. to have a new game I need to
-(void)didSimulatePhysics
{
[self enumerateChildNodesWithName:#"rock" usingBlock:^(SKNode *node, BOOL *stop) {
if (node.position.y < 0)
{
ScoreNum++;
[node removeFromParent];
score.text = [NSString stringWithFormat:#"%# %li",ScoreMSG,(long)ScoreNum];
if (ScoreNum > 10)
{
score.fontSize = 40;
score.position = CGPointMake(CGRectGetMidX(self.frame),CGRectGetMidY(self.frame));
score.text = #"Game Over!";
SKScene *spaceshipScene = [[GameScene alloc] initWithSize:CGRectMake(0, 0,CGRectGetMaxY(self.frame),CGRectGetMaxX(self.frame)).size];
printf("%f %f",CGRectGetMidX(self.frame),CGRectGetMidX(self.frame));
SKTransition *doors = [SKTransition doorsOpenVerticalWithDuration:0.25];
[self.view presentScene:spaceshipScene transition:doors];
ScoreNum = 0;
}
}
}];
}
GameScene is subclassed from SKScene like this
#import <SpriteKit/SpriteKit.h>
#interface GameScene : SKScene
#end
The code works find but the plates (all of the sprites on the screen) gets squeezed from sides
The following picture shows the results, first time, second time and third time, I needed 10 reputation to include 3 pictures so I had to merge them all into one picture, Here it is.
https://www.imageupload.co.uk/images/2015/08/30/123.png
Sorry, looks like I can not embed an image since I have not enough reputation!
Why each my scene squeezes?
Looks like you set a scaleMode in your viewController.viewDidLoad that handles your game scene, nothing wrong with your physics code (in your question).
look for something like this scene.scaleMode = SKSceneScaleModeAspectFill usually SKScenes are automatically scaled based on the screen size of the device and it is upto SKScene to provide you a scene.
Your scenes in your pictures shows that scenes have a complete and full cover but they are scaled.
It is kind of hard to handle sprite size while do not controling scale. I suggest to get ride of every Scale Mode and remark them all and control the scale your self.
if you are not going to zoom in/out as I believe it is the case in your game you just need to reset the scenes scale to 1 each time after each scene transition.

Objective C: Code freezes when loading series of images

My first post to the forums but I have been using answers posted here for the last several months and find the answers incredibly useful! I'm still learning objective c and still learning some basics.
My code is several hundred lines right so I don't want to the post the whole code. The basic premise of the code is to load a series of random images to random locations on the screen.
When I was trying to figure out how to deal with this idea I made a simple test version that would add one balloon when a button is pressed and then when you hit pop balloons delete all the balloon images that were created.
This balloon code worked just fine, and then I added this same concept into my main code. However now when I use it only a larger scale the code would freeze at 99% cpu usage and 18.5 MB memory. The code never failed but would sit frozen. The larger version is basically just adding multiple balloons when a button is pressed instead of one. Sometimes as many as 15 images.
Is there any reason a code of this style would not work on a larger scale? Or how do you go about problem solving an issue when the code freezes and no error is given.
.h file
#interface ViewController : UIViewController
{
// Holds an array of images of the balloons
NSMutableArray *BalloonArray;
// Holds an array file names of the balloon PNG files
NSMutableArray *BalloonNames;
}
-(void)AddBalloon:(id)sender;
-(void)PopBalloons:(id)sender;
#end
.m file
#interface ViewController ()
#end
#implementation ViewController
-(void)viewDidLoad
{
// Allocates memory for the array
BalloonArray = [[NSMutableArray alloc] init];
// Allocates memory and inputs the names of the images
BalloonNames = [NSMutableArray arrayWithObjects:[UIImage imageNamed:#"pink.png"],[UIImage imageNamed:#"blue.png"],[UIImage imageNamed:#"green.png"], nil];
[super viewDidLoad];
}
-(void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
-(void)AddBalloon:(id)sender
{
int x; // x position of the balloon image created
int y; // y position of the balloon image created
int i; // Random index value to pull a random balloon image out
// Random number generator for the x and y position
x = arc4random_uniform(230) + 30;
y = arc4random_uniform(400) + 150;
// Random index value from 0 to 2
// Random based on how many images there are to chose from
i = arc4random_uniform(3);
// Uses the image from the index value previously randomnized
UIImage *Balloon = [BalloonNames objectAtIndex:i];
// Places the UIImage in a UIImageView
UIImageView *BalloonView = [[UIImageView alloc] initWithImage:Balloon];
// Sizes the image to the correct size
BalloonView.frame = CGRectMake(0, 0, 50, 100);
// Centers the image using the x and y coordinates
BalloonView.center = CGPointMake(x,y);
// Adds the image view to the view
[self.view addSubview:BalloonView];
// Adds the image view to the array
[BalloonArray addObject:BalloonView];
}
-(void)PopBalloons:(id)sender
{
// Removes each image in the array out of the main view
for(UIImageView *Test in BalloonArray)
{
[Test removeFromSuperview];
}
// Removes all object from the array
[BalloonArray removeAllObjects];
}
#end
Make the method -(void)AddBalloon:(id)sender to run on a Separate Thread. Perhaps you can use [NSThread detachNewThreadSelector:#selector(myThreadMainMethod:) toTarget:self withObject:nil];. Have a look at Apple Documentation

Received memory warning but the live bytes are only 5 to 10MB [duplicate]

This problem has completely stumped me. This is for iOS 5.0 with Xcode 4.2
What's going on is that in my app I let user select images from their photo album and I save those images to apps document directory. Pretty straight forward.
What I do then is that in one of the viewController.m files I create multiple UIImageViews and I then set the image for the image view from one of the picture that user selected from apps dir. The problem is that after a certain number of UIImage sets I receive a "Received memory warning". It usually happens when there are 10 pictures. If lets say user selected 11 pictures then the app crashes with Error (GBC). NOTE: each of these images are at least 2.5 MB a piece.
After hours of testing I finally narrowed down the problem to this line of code
[button1AImgVw setImage:image];
If I comment out that code. All compiles fine and no memory errors happen. But if I don't comment out that code I receive memory errors and eventually a crash. Also note it does process the whole CreateViews IBAction but still crashes at the end. I cannot do release or dealloc since I am running this on iOS 5.0 with Xcode 4.2
Here is the code that I used. Can anyone tell me what did I do wrong?
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self CreateViews];
}
-(IBAction) CreateViews
{
paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask ,YES);
documentsPath = [paths objectAtIndex:0];
//here 15 is for testing purposes
for (int i = 0; i < 15; i++)
{
//Lets not get bogged down here. The problem is not here
UIImageView *button1AImgVw = [[UIImageView alloc] initWithFrame:CGRectMake(10*i, 10, 10, 10)];
[self.view addSubview:button1AImgVw];
NSMutableString *picStr1a = [[NSMutableString alloc] init];
NSString *dataFile1a = [[NSString alloc] init];
picStr1a = [NSMutableString stringWithFormat:#"%d.jpg", i];
dataFile1a = [documentsPath stringByAppendingPathComponent:picStr1a];
NSData *potraitImgData1a =[[NSData alloc] initWithContentsOfFile:dataFile1a];
UIImage *image = [[UIImage alloc] initWithData:potraitImgData1a];
// This is causing my app to crash if I load more than 10 images!
// [button1AImgVw setImage:image];
//If I change this code to a static image. That works too without any memory problem.
button1AImgVw.image = [UIImage imageNamed:#"mark-yes.png"]; // this image is less than 100KB
}
NSLog(#"It went to END!");
}
This is the error I get when 10 images are selected. App does launch and work
2012-10-07 17:12:51.483 ABC-APP[7548:707] It went to END!
2012-10-07 17:12:51.483 ABC-APP [7531:707] Received memory warning.
App crashes with this error when there are 11 images
2012-10-07 17:30:26.339 ABC-APP[7548:707] It went to END!
(gbc)
This situation (memory warnings and application quitting while attempting to load multiple full resolution UIImages into a view) has attempted to burn me a couple times in my iOS programming career.
You need to make a shrinked down copy of your original image before doing the "setImage" call.
For my own code, I use the "UIImage+Resize" category, the details for which can be found here.
Resize your image to something smaller before inserting into your view, then make sure the full resolution image is released (or set to nil if on ARC) and you should have a happier time of things.
Here is how I do it in my own code:
CGSize buttonSize = CGSizeMake(width, height);
// it'd be nice if UIImage took a file URL, huh?
UIImage * newImage = [[UIImage alloc] initWithContentsOfFile: pathToImage];
if(newImage)
{
// this "resizedimage" image is what you want to pass to setImage
UIImage * resizedImage = [newImage resizedImage: buttonSize interpolationQuality: kCGInterpolationLow];
}

Speed up ios function

I really need help with this!
I'm building a map containing loads of tiles.. like 200x200 small 50px tiles. These tiles resides in an UIScrollView so that I can drag myself around the map! Works really nice right? Well it's super slow since there are too many subviews in the map.
Right, so I load the subviews as I scroll then! Problem is, that takes some time too, makes the scrolling a bit laggy/slow. Can you help me improve this function? I'm out of ideas. Found the Grand Central Dispatch but I'm not sire how to use it.
Here's my code
-(void)loadMapTiles {
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply(1, queue,
^(size_t row) {
int radiusX = 11;
int radiusY = 7;
int y = currentCoord.y-radiusY;
for(int x = currentCoord.x-radiusX; x < currentCoord.x+radiusX+1; x++) {
int currTag = mapSize.width*(y-1)+x;
if(![mapScroller viewWithTag:currTag]) {
UIImageView *mapTile = [[UIImageView alloc] initWithFrame:CGRectMake(50*x, 50*y, 50, 50)];
int mapNo = (rand() % 20) + 1;
if(mapNo > 11) {
mapNo = 1;
}
mapTile.image = [UIImage imageNamed:[NSString stringWithFormat:#"desert_map%d_50.gif", mapNo]];
//Tag the mapTile so that we can find it again!
[mapTile setTag:currTag];
[mapContentView addSubview:mapTile];
[mapTile release];
}
if(x == currentCoord.x+radiusX && y < currentCoord.y+radiusY) {
x = currentCoord.x-radiusX-1;
y++;
}
}
//Remove the other tiles outside the radius!
for (UIView *mapTile in [mapContentView subviews]) {
if(mapTile.frame.origin.x / 50 < currentCoord.x-radiusX || mapTile.frame.origin.x / 50 > currentCoord.x+radiusX || mapTile.frame.origin.y / 50 < currentCoord.y-radiusY || mapTile.frame.origin.y / 50 > currentCoord.y+radiusY) {
[mapTile removeFromSuperview];
}
}
});
}
And the function to call the map-building function above:
-(void)scrollViewDidScroll:(UIScrollView *)myScrollView {
CGPoint newCoord = CGPointMake((int)(myScrollView.contentOffset.x + myScrollView.frame.size.width/2) /50, (int)(myScrollView.contentOffset.y + myScrollView.frame.size.height/2) /50);
if(newCoord.x != currentCoord.x || newCoord.y != currentCoord.y) {
currentCoord = newCoord;
[self loadMapTiles];
}
}
You'll want to have a look at CATiledLayer. It lets you do what you want in a nice way regardless of how big your map is. It also supports having different images for different zoom levels.
I'm no obj-c developer but...
At a talk I was at a while ago on mobile web development, they recommend to re-use memory rather than allocate and free it.
Instead of creating a new UIImageView for every tile, could you have enough of them pre-allocated to for the whole screen and just change the images in them as the map is scrolled?
Maybe you should try using CoreGraphics and layers instead of scrollview to draw map and scroll it.
Look at WWDC 2010 video "Designing apps with scrollviews" and the corresponding sample code "PhotoScroller" there you will learn the big trick of "view reuse" in scrollViews.
WWDC 2011 video of similar name is a continuation of the same trick.
"Views that are no longer in the visible area should be reused and repositioned for displaying new stuff"
Adding and removing subviews while scrolling is bound to cause slow downs. Instead you should just reposition the non visible ones and show new stuff.
Other usual causes of scrolling problems are
layer.cornerRadius
layer.shadow (without setting shadowPath)
any opacity on subviews.
Always profile your code on device using core animation.

Animated UIImageView which should recognize taps on it (at every location the UIImageView is at)

I'm making an iPhone App which involves balloons (UIImageViews) being spawned from the bottom of the screen and moving up to the top of the screen.
The aim is to have the UIImageViews set up so that a tap gesture on a balloon causes the balloons to be removed from the screen.
I have set up the GestureRecognizer and taps are being recognized.
The problem I am having is that the animation method I am using does not provide information about where the balloon is being drawn at a specific point in time, and treats it as already having reached the final point mentioned.
This causes the problem of the taps being recognized only at the top of the screen(which is the balloon's final destination).
I have pasted my code for animation here:
UIViewAnimationOptions options = UIViewAnimationOptionBeginFromCurrentState|UIViewAnimationOptionAllowUserInteraction;
[UIView animateWithDuration:2.0 delay:0.0 options:options animations:^{
balloonImageView.center = p;
} completion:^(BOOL finished) {
if (finished) {
balloonImageView.hidden= TRUE;
balloonImageView.image=nil;
}
I keep track of where an image is by giving a unique tag to a UIImageView and checking if gesture.view.tag = anyBalloonObject.tag and if it does I destroy the balloon.
My basic question is, is there another animation tool I can use? I understand that I can set a balloon's finish point to slightly higher than where it is on screen until it reaches the top but that seems like it is very taxing on memory.
Do you have any recommendations? I looked through the Core Animation reference, and didn't find any methods that suited my needs.
In addition will the Multi-threading aspects of UIViewAnimation affect the accuracy of the tap system?
Thank You,
Vik
You shouldnt animate game-objects (objects you interact with while they are moving) like that.
You should rather use a NSTimer to move the ballons.
-(void)viewDidLoad {
//Set up a timer to run the update-function
timer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(update) userInfo:NULL repeats:YES];
}
-(void) update {
for (int i = [balloonArray count] - 1; i >= 0; i--) { //Loop through an array containing all your balloons.
UIImageView *aBalloon = [balloonArray objectAtIndex:i]; //Select balloon at the current loop index
aBallon.center = CGPointMake(aBallon.center.x, aBalloon.center.y + 1); //Change the center of that balloon, in this case: make it go upwards.
}
}
Here is what you need to declare in .h:
NSTimer *timer;
NSMutableArray *ballonArray;
//You should use properties on these also..
You will have to create a spawn method which adds balloons to the screen AND to the array.
When you have done that, it's simple to implement the touch methods, You can just loop trough the balloons and check:
//You need an excact copy of the loop from earlier around this if statement!
If (CGRectContainsPoint(aBalloon.frame, touchlocation)) { //you can do your own tap detection here inthe if-statement
//pop the balloon and remove it from the array!
}
Hope that isnt too scary-looking, good luck.