SpriteKit memory management preload cached and fps issue - ios

My question is pretty simple, according to the apple docs you have the ability to preload textures into RAM prior to presenting a scene like so:
SKTextureAtlas * atlas = [SKTextureAtlas atlasNamed:#"effect_circle_explode"];
SKTextureAtlas * atlas2 = [SKTextureAtlas atlasNamed:#"box_explodes"];
SKTextureAtlas * atlas3 = [SKTextureAtlas atlasNamed:#"fence_new"];
SKTextureAtlas * atlas4 = [SKTextureAtlas atlasNamed:#"swipe"];
SKTextureAtlas * atlas5 = [SKTextureAtlas atlasNamed:#"coin"];
SKTextureAtlas * atlas6 = [SKTextureAtlas atlasNamed:#"two_times"];
SKTextureAtlas * atlas7 = [SKTextureAtlas atlasNamed:#"three_times"];
SKTextureAtlas * atlas8 = [SKTextureAtlas atlasNamed:#"gus"];
[SKTextureAtlas preloadTextureAtlases:#[atlas, atlas2, atlas3, atlas4, atlas5, atlas6, atlas7, atlas8] withCompletionHandler:^{
[moron_logo removeFromSuperview];
moron_logo = NULL;
stuff.hidden = NO;
store.hidden = NO;
scroll_view.userInteractionEnabled = YES;
[self present_game_view];
}];
Now would there be any negative effect if later on through out gameplay you also call a preload to the same atlas like so:
-(void)load
{
SKTextureAtlas * atlas = [SKTextureAtlas atlasNamed:#"effect_circle_explode"];
SKTextureAtlas * atlas2 = [SKTextureAtlas atlasNamed:#"coin"];
[SKTextureAtlas preloadTextureAtlases:#[atlas, atlas2] withCompletionHandler:^{
explode_textures = [[NSMutableArray alloc] init];
int numImages = (int)atlas.textureNames.count;
for (int i=0; i <= numImages/2-1; i++)
{
NSString *textureName = [NSString stringWithFormat:#"effect_circle_explode_%d.png", i];
SKTexture *temp = [atlas textureNamed:textureName];
[explode_textures addObject:temp];
}
explodeAnimation = [SKAction animateWithTextures:explode_textures timePerFrame:.05];
idle_textures = [[NSMutableArray alloc] init];
int numImages2 = (int)atlas.textureNames.count;
for (int i=0; i <= numImages2/2-1; i++)
{
NSString *textureName = [NSString stringWithFormat:#"coin_%d.png", i];
SKTexture *temp = [atlas2 textureNamed:textureName];
[idle_textures addObject:temp];
}
idleAnimation = [SKAction animateWithTextures:idle_textures timePerFrame:.05];
[self animate:0];
}];
}
Now if I do not preload the texture again the game will actually crash once in awhile not all the time if I just directly inserted the textures into the SKAction. The crash is an exec_bad_access on the Sprite::update(double) call, so my assumption is that somehow the textures from the first preload were removed from RAM and thats why I preload every single time I create a new node now. It seems to have fixed that error. This leads to another problem though when it comes to performance and hence the reason why I am asking this.
The game runs fine on the 5S and the 5 but as soon you touch an iPod touch 5th gen it barely can go over 15 FPS. I ran instruments and this is what is eating up all the CPU time:
Could this be related to my constant call of the preloadatlas call? Does anyone know why this would be eating my processor time up so badly on older devices? Thanks so much and hopefully someone else might be having a similar problem and this will help them out once I make my way to bottom of it.
Thanks in advance.

Preloading atlases every time you create a new sprite is generally a bad idea.
Your actual problem seems to be that you preload the atlases but you don't keep them around. Unless the atlas variables are global.
As soon as the method that does the preloading returns, the atlas objects are now longer referenced and will be removed from memory automatically. Sprite Kit internally implements a caching system so you won't notice it right away but eventually one or more of the atlases will be gone.
Keep a strong reference to each atlas in your scene so that the atlases remain in memory, and stop preloading at runtime. Whether this helps with fps I don't know.

Related

Save generated SKTexture to file

I've now filed a bug for the issue below. Anyone with a good
workaround?
I try to save an SKTexture to file, and load it back again, but I don't succeed. The following code snippet can be copied to GameScene.m in the Xcode startup project.
I use textureFromNode in generateTexture, and that seems to be the root cause of my problem. If I use a texture from a sprite, the code works, and two spaceships are visible.
This code worked in iOS 8 but it stopped working in Xcode7 & iOS 9. I just want to verify that this is a bug before I file a bug report. My worry is that I do something wrong with NSKeyedArchiver.
It happens both in simulator and on device.
#import "GameScene.h"
#implementation GameScene
// Generates a texture
- (SKTexture *)generateTexture
{
SKScene *scene = [[SKScene alloc] initWithSize:CGSizeMake(100, 100)];
SKShapeNode *shapeNode = [SKShapeNode shapeNodeWithRectOfSize:CGSizeMake(50, 50)];
shapeNode.position = CGPointMake(50, 50);
shapeNode.strokeColor = SKColor.redColor;
shapeNode.lineWidth = 10;
[scene addChild:shapeNode];
SKTexture *texture = [self.view textureFromNode:scene];
//SKTexture *texture = [SKSpriteNode spriteNodeWithImageNamed:#"Spaceship"].texture; // This works!
return texture;
}
// Just generate a path
- (NSString *)fullDocumentsPath
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *yourFileName = [documentsDirectory stringByAppendingPathComponent:#"fileName"];
return yourFileName;
}
- (void)didMoveToView:(SKView *)view
{
self.scaleMode = SKSceneScaleModeResizeFill;
// Verify that the generateTexture method indeed produces a valid texture.
SKSpriteNode *s1 = [SKSpriteNode spriteNodeWithTexture:[self generateTexture]];
s1.position = CGPointMake(100, 100);
[self addChild:s1];
// Start with saving the texture.
NSString *fullName = [self fullDocumentsPath];
NSError *error;
NSFileManager *fileMgr = [NSFileManager defaultManager];
if ([fileMgr fileExistsAtPath:fullName])
{
[fileMgr removeItemAtPath:fullName error:&error];
assert(error == nil);
}
NSDictionary *dict1 = [NSDictionary dictionaryWithObject:[self generateTexture] forKey:#"object"];
bool ok = [NSKeyedArchiver archiveRootObject:dict1 toFile:fullName];
assert(ok);
// Read back the texture and place it in a sprite. This sprite is not shown. Why?
NSData *data = [NSData dataWithContentsOfFile:fullName];
NSDictionary *dict2 = [NSKeyedUnarchiver unarchiveObjectWithData:data];
SKTexture *loadedTexture = [dict2 objectForKey:#"object"];
SKSpriteNode *s2= [SKSpriteNode spriteNodeWithTexture:loadedTexture];
NSLog(#"t(%f, %f)", loadedTexture.size.width, loadedTexture.size.height); // Size of sprite & texture is zero. Why?
s2.position = CGPointMake(200, 100);
[self addChild:s2];
}
#end
Update for Yudong:
This might be a more relevant example, but imagine that the scene consists of 4 layers, with lots of sprites. When the game play is over I want to store a thumbnail image of the end scene of the match. The image will be used as a texture on a button. Pressing that button will start a replay movie of the match. There will be lots of buttons with images of old games so I need to store each image on file.
-(SKTexture*)generateTexture
{
SKScene *scene = [[SKScene alloc] initWithSize:CGSizeMake(100, 100)];
SKSpriteNode *ship = [SKSpriteNode spriteNodeWithImageNamed:#"Spaceship"];
ship.position = CGPointMake(50, 50);
[scene addChild:ship];
SKTexture *texture = [self.view textureFromNode:scene];
NSLog(#"texture: %#", texture);
return texture;
}
The solution/work around:
Inspired by Russells code I did the following. It works!
CGImageRef cgImg = texture.CGImage;
SKTexture *newText = [SKTexture textureWithCGImage:cgImg];
I've done a lot of experimenting/hacking with SKTextures. My game utilizes SKTextures. It is written in Swift. Specifically, I've had many problems with textureFromNode and textureFromNode:crop: and creating SKPhysicsBodies from textures. These methods worked fine in ios 8, but Apple completely broke them when they released ios 9.0. In ios 9.0, the textures were coming back as nil. Those nil textures broke SKPhysicsBodies from the textures.
I recently worked on serialization/deserialization of SKTextures.
Some key ideas/clues you might investigate are:
Run ios 9.2. Apple Staff mentioned a lot of issues have been fixed. https://forums.developer.apple.com/thread/17463 I've found ios 9.2 helps with SKTextures but didn't solve every issue especially the serialization issues.
Try PrefersOpenGL (set it to "YES" as a Boolean custom property in your config). Here is a post about PrefersOpenGL in the Apple Dev Forums by Apple Staff. https://forums.developer.apple.com/thread/19683 I've observed that ios 9.x seems to use Metal by default rather than OpenGL. I've found PrefersOpenGL helps with SKTexture issues but still doesn't make my SKShaders work (written in GLSL).
When I tried to serialize/deserialize nodes with SKTextures on ios 9.2, I got white boxes instead of visible textures. Inspired by Apple SKTexture docs that say, "The texture data is loaded when:
The size method on the texture object is called.
Another method is called that requires the texture’s size, such as creating a new SKSpriteNode object that uses the texture object.
One of the preload methods is called (See Preloading the Texture Data.)
The texture data is prepared for rendering when:
A sprite or particle that uses the texture is part of a node tree that is being rendered."
... I've hacked a workaround that creates a secondary texture from the CGImage() call:
// ios 9.2 workaround for white boxes on serialization
let img = texture!.CGImage()
let uimg = UIImage(CGImage: img)
let ntex = SKTexture(image: uimg)
let sprite = SKSpriteNode(texture: ntex, size: texture!.size())
So now my SKSpriteNodes created this way seem to serialize/deserialize fine. BTW, just invoking size() or creating an SKSpriteNode with the original texture does not seem to be enough to reify the texture into memory.
You didn't ask about textureFromNode:crop: but I'm adding observations anyway just in case it helps you: I've found this method in ios 8 worked (although the crop parameters were very tricky and seemed to require normalization with UIScreen.mainScreen().scale) In ios 9.0, this method didn't work at all (returned nil). In ios 9.2 this method now works (it now returns a non-nil texture) however subsequent creation of nodes from the texture do not need the size normalization. And furthermore, to make serialization/deserialization work, I found you ultimately have to do #3 above.
I hope this helps you. I imagine I've struggled more than most with SKTextures since my app is so dependent on them.
I tested your code in Xcode 7 and found texture returned in generateTexture was null. That's the reason why you can't load anything from the file, and you even haven't saved anything.
Try to use NSLog to log the description of your texture or sprite. E.g. add this line in generateTexture:
NSLog(#"texture: %#", texture);
What you will get in console:
texture: '(null)' (300 x 300)
And same for s1 and dict1 in your code:
s1: name:'(null)' texture:[ '(null)'
(300 x 300)] position:{100, 100} scale:{1.00, 1.00} size:{100, 100}
anchor:{0.5, 0.5} rotation:0.00
dict1: {
object = " '(null)' (300 x 300)"; }
You may do these tests on both iOS 8 and iOS 9 and you will probably get different results.
I'm not sure why you add the SKShapeNode to a scene and then save the texture from the scene. One workaround is to set texture for your SKShapeNode, and your code should work fine.
shapeNode.fillTexture = [SKTexture textureWithImageNamed:#"Spaceship"];
SKTexture *texture = shapeNode.fillTexture;
return texture;
Update:
It's quite annoying that textureFromNode doesn't works as expected in iOS 9. I tried to solve it by trial and error but no luck at last. Thus, I asked you if you would consider make a snapshot of the whole screen and set it as your thumbnail. Here's the progress I made today and hope you will get inspired from it.
I created a scene which contained SKLabelNode and SKSpriteNode in didMoveToView. After I clicked anywhere on screen, snapshot would be invoked and the down-scaled screenshot would be saved in the document folder. I used the code here.
- (UIImage *)snapshot
{
UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, 0.5);
[self.view drawViewHierarchyInRect:self.view.bounds afterScreenUpdates:YES];
UIImage *snapshotImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return snapshotImage;
}
Since the thumbnail is saved as UIImage therefore loading it back for the sprite's texture should be done easily. A sample project demonstrates the whole process and it works on both iOS 8 and 9.

Card dealing, playing

Problem
I've never made a card game before, and I'm having quite some difficulty at the moment.
However, I've managed to create the deck and such.
-(NSMutableArray *)arrayWithDeck:(id)sender
{
[sender removeAllObjects];
NSArray *faces = [[NSArray alloc] initWithObjects:#"A",#"2",#"3",#"4",#"5",#"6",#"7",#"8",#"9",#"10",#"J",#"Q",#"K", nil];
NSArray *suits = [[NSArray alloc] initWithObjects:#"h",#"d",#"c",#"s", nil];
for (int i = 0; i < 52; i++) {
NSString *cardToAdd = [NSString stringWithFormat:#"%#%#", faces[i % 13], suits[i / 13]];
[sender addObject:cardToAdd];
}
return sender;
}
Then deal the cards to the players ( just to one player at the moment )
-(void) dealPlayersWithPlayers: (int) players withDealtCards: (int) dealt {
if (players == 2){
__block float add = 0;
for (int i = 0; i < dealt; i++) {
add = add + ((self.frame.size.width / 100) * 10);
NSString *imageName = [NSString stringWithFormat:#"%#", deck[i]];
NSString *bundle = [[NSBundle mainBundle] pathForResource:imageName ofType:#"png"];
UIImage *image = [[UIImage alloc] initWithContentsOfFile:bundle];
SKTexture *texture = [SKTexture textureWithImage:image];
cardDisplay = [SKSpriteNode spriteNodeWithTexture:texture];
cardDisplay.size = CGSizeMake(104, 144);
cardDisplay.anchorPoint = CGPointMake(0.5, 0.5);
cardDisplay.position = CGPointMake(-self.frame.size.width/2.5 + add, -218);
cardDisplay.zPosition = 1;
cardDisplay.userInteractionEnabled = NO;
cardDisplay.name = [NSString stringWithFormat:#"card"];
[self addChild:cardDisplay];
}
}
}
Then when touchesBegan, on a card it animates to the centre of the screen, i.e a pre-phase for a "lay cards" button. However, I'm really struggling to figure a way to keep track of the card pressed. I.e, is the card Js, Ah, 8c or whatever it could be so it can obviously be used, However the SKSpriteNode.name is already taken for the detection on touchesBegan.
Another issue I'm having is when the cards are layed. They are messing up the z-index. However, an easy fix for this could be to just keep incrementing the z-index but is it the best way of doing it? My example here shows what I'm talking about.
I would say the fact that you have them rendering and moving up you are off to a great start.
My recommendation though would be to look at a MVC (Model View Controller) approach to the problem. Keep the info for cards played and what the player has for cards in a separate object from your view. That way when you touch your card you can have your controller work with your model to identify it and decide what happens next. It will be very hard to manage the game if you are relaying only on the SKSpriteNode and looking at its name with no pointer to it to compare to anything.
As far as sorting your z index your model would know which card was added first in your hand and your controller can then inform the view the appropriate position and z index.
At the very least I would consider subclassing SKSpriteNode and make a CardSpriteNode at least then you don't have to look at the sprite name for touch and could just check to see if it is a CardSpriteNode.
if ([node isKindOfClass:[CardSpriteNode class]])
//handle touch logic if a card
MVC is a simple concept and I would look at some write ups on that. Everyone has a slightly different approach to what can see what, but all agree on keeping the information separate.
Hope that helps.

ios Loading texture from atlas not working

I have an atlas with a bunch of tiles and i am trying to load them into memory using SKTexture and SKTextureAtlas but it is not working. I use the following code to load them:
NSString *atlasName = [NSString stringWithFormat:#"Tiles"];
SKTextureAtlas *tileAtlas = [SKTextureAtlas atlasNamed:atlasName];
NSInteger numberOfTiles = tileAtlas.textureNames.count;
backgroundTiles = [[NSMutableArray alloc] initWithCapacity:numberOfTiles];
for (int y = 0; y < 5; y++) {
for (int x = 0; x < 9; x++) {
int tileNumber = y*9 + x + 1;
NSString *textureName = [NSString stringWithFormat:#"tile%d.png",tileNumber];
SKSpriteNode *tileNode = [SKSpriteNode spriteNodeWithTexture:[tileAtlas textureNamed:textureName]];
CGPoint position = CGPointMake((0.5 + x)*_tileSize - _levelWidth/2,(0.5 - y - 1)*_tileSize + _levelHeight/2);
tileNode.position = position;
tileNode.zPosition = -1.0f;
tileNode.blendMode = SKBlendModeReplace;
[(NSMutableArray *)backgroundTiles addObject:tileNode];
}
}
Then i use this code to add them to my scene:
- (void)addBackgroundTiles
{
for (SKNode *tileNode in [self backgroundTiles]) {
[self addChild: tileNode];
}
}
The problem is it doesnt load the correct texture for a tile or find the texture at all.
What I end up with is this (ignore the blue circle): http://i.stack.imgur.com/g39BF.png
Here is my tile atlas: http://snk.to/f-ctp5yhpz
EDIT: I am using NameChanger(www.mrrsoftware.com/MRRSoftware/NameChanger.html) to rename all my tiles, can it be that program that messes up my pngs? as far as i can see they are in the correct order after i have renamed them.
Solution
Editing my answer to point out that the solution is in the comments below this answer.
It turned out that the issue was caused by Xcode not rebuilding the atlas after the image files were renamed outside of Xcode (presumably by the file changed OP mentioned).
By cleaning and rebuilding the project, all the texture atlases were built again, and OPs code started working.
Original answer
Two things to double-check:
Is your .atlas added to your project as a folder or a group? It must be a folder (blue icon in Xcode, instead of yellow).
After adding Tiles.atlas to your project, you must also enable atlas generation in Xcode settings.
See here for a similar issue: How to create atlas for SpriteKit. I linked to Apple documentation on incorporating texture atlases into your projects which has a detailed step-by-step instruction on enabling atlas generation.
Why the double for loops?
Are you saving the backgroundTiles array as a property?
I've had this occur recently and the only fix that worked was:
[SKSpriteNode spriteNodeWithTexture:[SKTexture textureWithImageNamed:#"someTile.png"]]; The textureWithImageNamed always gets the right one.
So try:
SKSpriteNode *tileNode = [SKSpriteNode spriteNodeWithTexture:[SKTexture textureWithImageNamed:textureName]];

Animating a Sprite in Cocos2D and Spritebuilder

in the project i'm working on I have multiple characters you can play as (in this case I will refer to them as drones). In my gamescene I have all the physics setup through _drone. A .CCB file created with spritebuilder. Previously I had this file animated through spritebuilder, but now with the addition of multiple drones to choose from I need to set it to display and cycle through the appropriate frames. I've been looking all day for things related to this and most answers I see are for cocos2d v2.0 or when I get something that has no errors showing in Xcode, it doesn't apply it to my _drone class. What I'm looking to do is something like this: [_drone setSpriteFrame:[CCSpriteFrame frameWithImageNamed:#"DefectiveDroneSpriteSheet/Drone1.png"]]; As this sets the frame for _drone to what I want. However I don't know how to make this cycle between the frames.
I found an answer on here recently that showed how to do it:
NSMutableArray *animationFrames = [NSMutableArray array];
for(int i = 1; i <= FRAMES; ++i)
{
CCSpriteFrame *spriteFrame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName: [NSString stringWithFormat:#"animationFrame%d.png", i]]; //
}
//Create an animation from the set of frames you created earlier
CCAnimation *animation = [CCAnimation animationWithSpriteFrames: animationFrames delay:delay];
//Create an action with the animation that can then be assigned to a sprite
CCActionAnimate *animationAction = [CCActionAnimate actionWithAnimation:animation];
CCActionRepeatForever *repeatingAnimation = [CCActionRepeatForever actionWithAction:animationAction];
[self runAction:repeatingAnimation];
Unfortunately this didn't work for me, but maybe I did something wrong. I seemed to have the most issue with the for loop/ a warning saying variable spriteFrame is never used, or something like that. The problem with this code is that after hours of messing with it and trying to find updated documentation I couldn't figure out how to do what my first example did, apply it directly to _drone. So with all that said... what should I do about solving this? Is there another easier way that i'm overlooking?
Thanks for your time, much appreciated!
edit for Guru:
Hello, thanks for responding. This is what my for loop looks like currently that is throwing me 4 warnings.
for(int i = 1; i <= 2; ++i)
{
CCSpriteFrame *frame1 = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName: [NSString stringWithFormat:#"DefectiveDroneSpriteSheet/Drone1.png", i]]; //
CCSpriteFrame *frame2 = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName: [NSString stringWithFormat:#"DefectiveDroneSpriteSheet/Drone1.png", i]]; //
}
I get a warning "unused variable for frame 1 and frame 2" and "data argument not used by format string" for the 'i'. Also doing this, how do I make this animation apply to my _drone object? As the object is already placed in the scene through Spritebuilder?
Second Edit:
- (void)didLoadFromCCB {
NSMutableArray *animationFrames = [NSMutableArray array];
for(int i = 1; i <= 2; ++i)
{
CCSpriteFrame *spriteFrame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName: [NSString stringWithFormat:#"DroneSpriteSheets%d.png", i]]; //
[animationFrames addObject: spriteFrame];
}
//Create an animation from the set of frames you created earlier
CCAnimation *animation = [CCAnimation animationWithSpriteFrames: animationFrames delay:1.0f];
//Create an action with the animation that can then be assigned to a sprite
CCActionAnimate *animationAction = [CCActionAnimate actionWithAnimation:animation];
CCActionRepeatForever *repeatingAnimation = [CCActionRepeatForever actionWithAction:animationAction];
[_drone runAction:repeatingAnimation];
//-----------------------------------------------------------
Thats the relevant part of my code, i get this error:
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '* -[__NSArrayM insertObject:atIndex:]: object cannot be nil'
You are not adding frames in array:
for(int i = 1; i <= FRAMES; ++i)
{
CCSpriteFrame *spriteFrame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName: [NSString stringWithFormat:#"animationFrame%d.png", i]]; //
[animationFrames addObject: spriteFrame];
}

Sprite Kit - Animations & memory managment

I'm currently messing around with Sprite Kit on iOS to figure out if it would be a fitting framework to make relatively simple 2D game in.
Due to my ActionScript background, i am very comfortable working with Sprite Kit code-wise
But there is something i just can't figure out. Animated nodes with Texture Atlas as a resource are incredibly memory heavy. I've imported an atlas into my project (size of textures is about 35MB). Preloading textures into RAM seems ok but at the moment i run the actual animation, the heap size increases exponentinaly (from about 80MB to 780MB)
Here goes my code:
self.noahFrames = [[NSMutableArray alloc] init];
SKTextureAtlas *noahAtlas = [SKTextureAtlas atlasNamed:#"noahAnimati"];
int imgCount = noahAtlas.textureNames.count;
for (int i=1; i <= imgCount; i++) {
NSString *textureName = [NSString stringWithFormat:#"NoahMainMenuAnimation_%d", i];
SKTexture *temp = [noahAtlas textureNamed:textureName];
[self.noahFrames addObject:temp];
}
SKSpriteNode *noahNode = [self createSpriteWithName:#"noah" imagePath:#"Noah_main_menu_hd" positionXPath:#"MainMenu.Noah.x" positionYPath:#"MainMenu.Noah.y" scalePath:#"MainMenu.Noah.scale"];
[self addChild:noahNode];
//up to this point everything goes fine
[noahNode runAction:[SKAction repeatActionForever:
[SKAction animateWithTextures:self.noahFrames
timePerFrame:0.1f
resize:YES
restore:YES]] withKey:#"animatedNoah"];
So i guess my actual question is why does the application become that insanely memory heavy after calling the SKAction animation ? I must be missing something rather obvious ...
I do know that when a texture is loaded in graphic memory it's loaded without any compression, but I don't think that xcode monitors graphic memory, so it's really strange to me.
I usually load and execute animations just like you do and I don't have such memory behaviour, but i noticed it when testing on the simulator. Are you using iOS simulator for your tests? Does your application crash when you reach those memory levels?

Resources