I use ARC for memory management.
Before the begining of the game I use a preload scene in which I load a lot of CCParticleSystemQuad object that I'll use in my game. All is going well in this part, here is my code :
//
// ReadySteadyGo.m
//
// Created by Nik on 23/05/13.
// Copyright 2013 __MyCompanyName__. All rights reserved.
//
#import "ReadySteadyGoLayer.h"
#import "QuickStartLayer.h"
#implementation ReadySteadyGoLayer
// Helper class method that creates a Scene with the ReadySteadyLayer as the only child.
+(CCScene *) scene{
// 'scene' is an autorelease object.
CCScene *scene = [CCScene node];
// 'layer' is an autorelease object.
ReadySteadyGoLayer *layer = [ReadySteadyGoLayer node];
// add layer as a child to scene
[scene addChild: layer];
// return the scene
return scene;
}
#synthesize particleExplosion;
// on "init" you need to initialize your instance
-(id) init
{
// always call "super" init
if( (self=[super init]) ) {
compteur = 3;
plus10LablesArray = [[NSMutableArray alloc] initWithCapacity:400];
whiteParticlesArray = [[NSMutableArray alloc] initWithCapacity:500];
bombParticlesArray = [[NSMutableArray alloc] initWithCapacity:50];
self.particleExplosion = [[CCParticleSystemQuad alloc] init];
bombExplosion = [[CCParticleSystemQuad alloc] init];
plus10Label = [[CCLabelTTF alloc] init];
displayCompteur = [[CCLabelTTF alloc] init];
self.particleExplosion = [CCParticleSystemQuad particleWithFile:#"whiteExplosion.plist"];
bombExplosion = [CCParticleSystemQuad particleWithFile:#"explosion.plist"];
}
[self schedule:#selector(initAll)];
[self schedule:#selector(compt)];
return self;
}
-(void)initAll{
// Create a new NSOperationQueue instance.
operationQueue = [[NSOperationQueue alloc] init];
// Create a new NSOperation object using the NSInvocationOperation subclass.
// Tell it to run the counterTask method.
NSInvocationOperation *operation1 = [[NSInvocationOperation alloc] initWithTarget:self
selector:#selector(initWhiteParticles)
object:nil];
NSInvocationOperation *operation2 = [[NSInvocationOperation alloc] initWithTarget:self
selector:#selector(initBombParticles)
object:nil];
NSInvocationOperation *operation3 = [[NSInvocationOperation alloc] initWithTarget:self
selector:#selector(initPlus10Labels)
object:nil];
// Add the operation to the queue and let it to be executed.
[operationQueue addOperation:operation1];
[operationQueue addOperation:operation2];
[operationQueue addOperation:operation3];
[self unschedule:#selector(initAll)];
}
- (void)compt{
CGSize winSize = [CCDirector sharedDirector].winSize;
if (compteur == 3){
displayCompteur = [CCLabelTTF labelWithString:[NSString stringWithFormat:#"%i...", compteur] fontName:#"Helvetica" fontSize:120];
displayCompteur.position = ccp(winSize.width/2, winSize.height/2);
[self addChild:displayCompteur z:1000];
compteur--;
[self unschedule:#selector(compt)];
[self schedule:#selector(boucle) interval:1.0f];
}
else if (compteur == 2){
displayCompteur.string = [NSString stringWithFormat:#"%i..", compteur];
compteur--;
[self schedule:#selector(compt) interval:1.0f];
}
else if (compteur == 1){
displayCompteur.string = [NSString stringWithFormat:#"%i.", compteur];
compteur--;
[self schedule:#selector(compt) interval:1.0f];
}
else if (compteur == 0){
displayCompteur.string = #"GO";
displayCompteur.fontSize = 25;
compteur--;
[self schedule:#selector(compt) interval:1.0f];
}
else{
[self unschedule:#selector(compt)];
[[CCDirector sharedDirector] pushScene:[QuickStartLayer scene:plus10LablesArray:whiteParticlesArray: bombParticlesArray]];
}
}
- (void)initWhiteParticles{
int index = 0;
for (index = 0; index < 500; index++) {
self.particleExplosion = [CCParticleSystemQuad particleWithFile:#"whiteExplosion.plist"];
[whiteParticlesArray performSelectorOnMainThread:#selector(addObject:) withObject:self.particleExplosion waitUntilDone:NO];
}
}
- (void)initBombParticles{
int index = 0;
for (index = 0; index < 50; index++) {
bombExplosion = [CCParticleSystemQuad particleWithFile:#"explosion.plist"];
[bombParticlesArray performSelectorOnMainThread:#selector(addObject:) withObject:bombExplosion waitUntilDone:NO];
}
}
- (void)initPlus10Labels{
int index = 0;
for (index = 0; index < 400; index++) {
plus10Label = [CCLabelTTF labelWithString:#"+10" fontName:#"Helvetica" fontSize:20];
[plus10LablesArray performSelectorOnMainThread:#selector(addObject:) withObject:plus10Label waitUntilDone:NO];
}
}
#end
The problem is when I check in Instruments (allocations) I can see [CCParticleSystemQuad alloc memory] increasing each time. After 15 min of using my game, it crashes...
When I use on of my particle I do this :
explosion = [_whiteParticlesArray objectAtIndex:nextWhiteParticle];
nextWhiteParticle++;
explosion.position = ccp(posX, posY);
[particleToDelete addObject:explosion];
[self addChild: explosion];
I created a function to clean the particles which is :
- (void)cleanParticles{
for (int i = 0; i < [particleToDelete count]; i++) {
id object = [particleToDelete objectAtIndex:i];
[particleToDelete removeObject:object];
[self removeChild:object cleanup:YES];
}
}
At the end of the game here is what I do :
[self unschedule:#selector(countDown:)];
[self unschedule:#selector(addAllSprites:)]
[self unschedule:#selector(displayScore:)];
[self unschedule:#selector(cleanParticles)];
[self unschedule:#selector(cleanLabels)];
[_whiteParticlesArray removeAllObjects];
[_bombParticlesArray removeAllObjects];
[_plus10LabelsArray removeAllObjects];
[self removeChild:_spriteSheet cleanup:YES];
So I remove all objects, and ARC is supposed to clean the memory of those objects right ? The problem is that it does not.
Thank you for your help guys :).
Edit 1:
I am really stuck ... I remove all my objects which are in my NSMutableArray but ARC does not deallocate them. Someone for help ?
Thx
That one seems obvious. You have all particles stored in _whiteParticlesArray, right? So as long as the particles are still in that array, they will be retained by the array and remain in memory.
When you remove all objects and memory usage does not change (significantly) in Instruments you may be having other leaks too. One thing you should check in Instruments is how many of the particle objects are alive. And be sure to verify that the scene instance itself is deallocated after changing scenes.
Btw, it's not very effective to create hundreds of particle systems in advance. Do you have a performance problem when you create the particles when needed? If not, create them on the fly. Keep in mind that each particle system itself uses around 500 bytes so 500 particle systems amount to roughly 250 KB just for the class instances.
You can still preload the textures, which is the most important part. All you need to do is to create one of each particle type that uses an embedded texture, or use texture cache to preload the textures of particle system plists without embedded textures.
Related
I am trying to draw a figure in C, and I have succeded in doing that, but I'm wondering if the way I'm doing it is making it hard for me to what I want to do next (making the figure move/bounce).
I have made a for loop in main that iterates through an array of coordinates which then again call a function that draws lines between them and fills it with color. What I'm wondering about is if this for loop is the best way to do this?
I have made this for loop in main:
for(i = 0; i < SPHERE_NUMTRIANGLES; i++){
object = CreateObject(screen,&sphere_model[i],SPHERE_NUMTRIANGLES);
object->model->scale = 0.1f;
DrawObject(object);
}
The sphere_model im trying to draw contains of many coordinates on the form:
#define SPHERE_NUMTRIANGLES 478
triangle_t sphere_model[] = {
{
.x1=-1,
.y1=-500,
.x2=-1,
.y2=-489,
.x3=-1,
.y3=-500,
.fillcolor=0xeeeeee,
.scale=1.0
},
The CreateObject gets the model from the for loop
// Create new object
object_t *CreateObject(SDL_Surface *screen, triangle_t *model, int numtriangles)
{
object_t *object;
object = NULL;
object = malloc(sizeof(object_t));
object->model = malloc(sizeof(triangle_t) * numtriangles);
object->screen = screen;
object->ttl;
object->speedx = 0;
object->speedy = 1;
object->model = model;
object->model->scale;
object->model->tx = 100;
object->model->ty = 100;
return object;
}
and finally the DrawObject just calls a function that draws the triangles
void DrawObject(object_t *object)
{
DrawTriangle(object->screen,object->model);
}
The sphere_model is in sphere_data.h and the CreateObject function is in triangle.c
I'm supposed to create multiple figures and add the created figures to a list after this, but I'm currently trying to just make one. (This is homework, but I'm hoping I can get some help here, I'm struggling a bit)
...hard for me to what I want to do next (making the figure move/bounce).
What i see is that you allocate objects, draw them and then forget them (I do not see you deallocate the memory). Then, if you want to draw the model again at a different place, you will have to go through the loop again, creating objects, drawing them (and forgetting them).
Maybe it would be better to remember the objects created so you can later just change their coordinates before redrawing them. As an example:
typedef struct LIST {
struct LIST *next;
object_t *object;
};
struct LIST *pObjectList, *pList;
// create objects, draw them and save in list
pObjectList= pList= calloc(1,sizeof(struct LIST));
for(i = 0; i < SPHERE_NUMTRIANGLES; i++){
object = CreateObject(screen,&sphere_model[i],SPHERE_NUMTRIANGLES);
object->model->scale = 0.1f;
DrawObject(object);
pList->object= object;
pList= pList->next= calloc(1,sizeof(struct LIST));
}
// offset the model with 50 pixels
pList= pObjectList;
while (pList->object) {
pList->object.x1 += 50; pList->object.y1 += 50;
pList->object.x2 += 50; pList->object.y2 += 50;
pList->object.x3 += 50; pList->object.y3 += 50;
pList= pList->next;
}
// redraw
pList= pObjectList;
for(i = 0; i < SPHERE_NUMTRIANGLES; i++, pList= pList->next)
{
DrawObject(pList->object);
}
I am trying to replace my custom IP address with the existing URL IP address. How can replace the my IP address with the existing IP. Please find the code snippet below
- (IBAction)btnSubmit:(UIButton *)sender {
NSString *ipAdd = [_txtIPAddress text];
NSLog(#"My entered IP Address is %#", ipAdd);
NSLog(#"Current pointing server value is %#", [ConnManager activeEndpoint]);
NSLog([App appDelegate].isConfigured ? #"Yes" : #"No");
NSArray *listItems = [[ConnManager activeEndpoint] componentsSeparatedByString:#"/"];
ConnManager *conn = [[ConnManager alloc] init];
NSMutableString *configuredUrl = nil;
[configuredUrl setString:#""];
for ( NSInteger i =0; i < listItems.count; i++) {
if(i != 2) {
NSMutableString * arrayElement = [(NSMutableString*)listItems objectAtIndex:i];
NSMutableString *str = [NSMutableString stringWithFormat: #"%#/", arrayElement];
[configuredUrl appendString:str];
} else {
NSMutableString *configstr = [NSMutableString stringWithFormat: #"%#", ipAdd];
NSLog(#"ConfigString %#", configstr);
//How to replace the my ip address with the array index[2]
configuredUrl = [configuredUrl stringByAppendingFormat:configstr];
NSLog(#"Configured Url after apppending %#", configuredUrl);
Thanks in advance
Try this shorter version, it replaces everything after the line
NSLog([App appDelegate].isConfigured ? #"Yes" : #"No");
NSMutableArray *listItems = [[[ConnManager activeEndpoint] pathComponents] mutableCopy];
listItems[2] = ipAdd;
NSString *configuredUrl = [NSString pathWithComponents:listItems];
NSLog(#"%#", configuredUrl);
or, if activeEndpoint is an URL, still easier
NSURL *url = [NSURL URLWithString:[ConnManager activeEndpoint]];
NSString *configuredURL = [[[NSURL alloc] initWithScheme:[url scheme] host:ipAdd path:[url path]] absoluteString];
It is often easier to leave the parsing of URLs to a system class. If you can, I would suggest using NSURLComponents. For example:
NSURLComponents *URLComponents =
[NSURLComponents componentsWithString:[ConnManager activeEndpoint]];
URLComponents.host = [_txtIPAddress text];
NSString *configuredURL = URLComponents.string;
I'm creating an array in my AppDelegate and then want to use it in another view controller (repeat continuously until I close the view). It populates the array, but doesn't seem to animate. I've searched and made edits for days. Any help would be appreciated!
AppDelegate.h
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (nonatomic, retain) NSMutableArray *sharedArray1;
#end
AppDelegate.m
#import "Scene1.h"
#synthesize sharedArray1;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
int ii;
for (ii = 1; ii<70;) {
[sharedArray1 addObject:[UIImage imageWithData:[NSData dataWithContentsOfFile:[[NSBundle mainBundle]pathForResource:[NSString stringWithFormat:#"RadarCircle_Active%i.png", ii] ofType:nil]]]];
NSLog(#"Log RadarCircle_Active i: %i",ii);
ii = ii + 1; // increment by 1
}
return YES;
}
Scene1.m
#import "AppDelegate.h"
-(void)radarActive{
float duration1 = 5.5;
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
activeRadarImage.animationImages = appDelegate.sharedArray1;
activeRadarImage.animationDuration = duration1;
// activeClawImage.animationRepeatCount = count;
[activeRadarImage startAnimating];
}
As #architectpianist said you need to allocate first and try changing
[sharedArray1 addObject:[UIImage imageWithData:[NSData dataWithContentsOfFile:[[NSBundle mainBundle]pathForResource:[NSString stringWithFormat:#"RadarCircle_Active%i.png", ii] ofType:nil]]]];
to
[sharedArray1 addObject:[UIImage imageWithData:[NSData dataWithContentsOfFile:[[NSBundle mainBundle]pathForResource:[NSString stringWithFormat:#"RadarCircle_Active%i", ii] ofType:#"png"]]]];
Or u can do it this way
NSString *imageName = [NSString stringWithFormat:#"RadarCircle_Active%i.png", ii];
UIImage *image = [UIImage imageNamed:imageName];
NSLog(#"image : %#", image);
[sharedArray1 addObject:image];
Check out the NSLog.
Hope it helps.
Looks to me like you need to set sharedArray1 to something before you start adding objects to it.
Try adding this before you start the loop:
self.sharedArray1 = [[NSMutableArray alloc] init];
I am using NSObject class to get all the data from a database. When I call that function it will show a memory leak where I assign a string using stringWithFormat. I think when we use this method we should not have to release that string so why does it show a memory leak?
Thanks in advance. :)
- (void) Allnote
{
[app.NoteArray removeAllObjects];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"Notes.sqlite"];
if (sqlite3_open([path UTF8String], &database) == SQLITE_OK)
{
NSString *querySQL = [NSString stringWithFormat:#"SELECT * From note" ];
const char *sql = [querySQL UTF8String];
sqlite3_stmt *searchStatement;
if (sqlite3_prepare_v2(database, sql, -1, &searchStatement, NULL) == SQLITE_OK)
{
while (sqlite3_step(searchStatement) == SQLITE_ROW)
{
noteClass *noteObj = [[noteClass alloc]init];
noteObj.noteTitle = [NSString stringWithUTF8String:(char *)sqlite3_column_text(searchStatement, 0)]; // at this place
noteObj.noteContent = [NSString stringWithUTF8String:(char *)sqlite3_column_text(searchStatement, 1)]; // at this place
NSNumber *noteId = [NSNumber numberWithInt:sqlite3_column_int(searchStatement, 2)];
noteObj.noteId = [NSString stringWithFormat:(#"%#"),noteId]; // at this place
files=noteObj.noteTitle;
filescont=noteObj.noteContent;
[app.NoteArray addObject:noteObj];
[noteObj release];
}
}
sqlite3_finalize(searchStatement);
}
sqlite3_close(database);
}
See, stringWithFormatis a factory method means that it has autorelease in its definition, that's why u r getting memory issue. But, that is not an issue.its 100% perfect.
If you aren't apply a format, then why use stringWithFormat
NSString *querySQL = [NSString stringWithFormat:#"SELECT * From note" ];
Is the same as:
NSString *querySQL = #"SELECT * From note";
And you are correct, you do not have te release them.
I am responding in addition to Surya Kant's answer.
It was not a problem with that. But still if you want to avert the issue, please do onething.
Instead of the following line,
noteObj.noteTitle = [NSString stringWithUTF8String:(char *)sqlite3_column_text(searchStatement, 0)]; // at this place
do as follows
NSString *noteTit = [[NSString alloc] initWithUTF8String:(char *)sqlite3_column_text(searchStatement, 0)];
noteObj.noteTitle = noteTit;
[noteTit release];
Similarly do it for others.
How can i get mouse coordinates in C under Mac?
I'm not avare of any fully only C implementation, but in the foundation framework of OSX (10.5+) there is a function called "HIGetMousePosition". You should be able to integrate this with your C program.
http://allancraig.net/index.php?option=com_content&view=article&id=137:getting-mouse-coordinates&catid=39:objective-c&Itemid=86 shows this example implementation:
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
HIPoint point;
HICoordinateSpace space = 2;
HIGetMousePosition(space, NULL, &point);
printf("%.2f %.2f", point.x, point.y);
[pool drain];
return 0;
}