Memory leak : How to stop? - database

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.

Related

Replace substring into a string using objective C

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;

How to choose an array (column) from a given file.txt? (stringByAppendingPathComponent) Xcode

I am trying to pick an array (column) from a given file that contains arrays of numbers e.g:
2012-09-02 16:27:15.010 SMA -0.818863 0.286575 0.206177 -0.108286 -0.231033 -0.303317
2012-09-02 16:27:15.017 SMA -1.024597 0.380875 0.456131 -0.282619 -0.123060 -0.048027
2012-09-02 16:27:15.023 SMA -0.754196 0.417053 1.165237 -0.010996 -0.078193 0.594972
2012-09-02 16:27:15.030 SMA -0.674835 0.486038 1.487640 0.061529 -0.008288 0.825637
here is my code, but it's giving nothing:
NSString* filePath = #"/Users/bahmadios/Documents/Xcode/selectArray/selectArray/Bus.txt";//file path...
NSString* fileRoot = [[NSBundle mainBundle]
pathForResource:filePath ofType:#"txt"];
// read everything from text
NSString* fileContents =
[NSString stringWithContentsOfFile:fileRoot
encoding:NSUTF8StringEncoding error:nil];
NSLog(#"%#", fileContents);
// first, separate by new line
NSArray* allLinedStrings =
[fileContents componentsSeparatedByCharactersInSet:
[NSCharacterSet newlineCharacterSet]];
NSLog(#"%#", allLinedStrings);
// then break down even further
NSString* strsInOneLine =
[allLinedStrings objectAtIndex:0];
NSLog(#"%#", strsInOneLine);
// choose whatever input identity you have decided. in this case ;
NSArray *array = [ strsInOneLine componentsSeparatedByString:#" "];
if (array.count > 3) {
NSLog(#"---- %#", array[3]);
and I am getting:
2014-05-20 23:26:52.226 selectArray[5734:907] ---- (null)
2014-05-20 23:26:52.227 selectArray[5734:907] (null)
2014-05-20 23:26:52.228 selectArray[5734:907] (null)
2014-05-20 23:26:52.228 selectArray[5734:907] (null)
2014-05-20 23:26:52.229 selectArray[5734:907] ---- (null)
What is wrong?
I'm not sure you need the line that creates strsInOneLine. The following works for me
NSString *filePath = ...;
NSString *fileContents = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
NSArray *lines = [fileContents componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
[lines enumerateObjectsUsingBlock:^(NSString *line, NSUInteger idx, BOOL *stop) {
NSArray *components = [line componentsSeparatedByString:#" "];
if (components.count > 3) {
NSLog(#"---- %#", components[3]);
}
}];

Can't animate my NSMutableArray from AppDelegate

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];

ARC Memory allocation with CCParticleSystemQuad

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.

how to read a file from documents directory

i hav to read the file with name myname.plist from documents directory .....i want to store the content of the file to string....
Something like this should do:
/* Find the documents directory. */
NSArray *paths = NSSearchPathForDirectoriesInDomains(
NSDocumentsDirectory, NSUserDomainMask, YES/*expand tilde*/);
NSAssert([paths count] > 0,
#"%s: No user document directory found!", __func__);
NSString *documentsDir = [paths objectAtIndex:0U];
/* Build the file path. */
NSString *name = [#"myname" stringByAppendingPathExtension:"plist"];
NSString *path = [documentsDir stringByAppendingPathComponent:name];
/* Read in the file content. */
NSError *error = nil;
NSStringEncoding enc;
NSString *content = [NSString
stringWithContentsOfFile:path
usedEncoding:&enc
error:&error];
if (!content) {
NSLog(#"%s: Error reading content of \"%#\": %#", __func__, path, error);
}

Resources