Can't get custom object from NSMutableArray (IPHONE SDK) - iphone

I have a problem with a NSMutableArray... After I fill the NSMutableArray in my function (readRoutes) I can't extract the objects.... Inside the readRoutes function I can... I can't figure where is the problem..
First the NSMutableArray is fill with Route objects in the readRoutes method...(Inside RoutesListView file) (I need to fill after TableView cells with these Route objects...)
This is the Route.h file :
#interface Route : NSObject {
NSString *routeId;
NSString *routeDirection;
NSString *routeName;
NSString *routeCode;
}
#property (nonatomic,retain) NSString *routeId;
#property (nonatomic,retain) NSString *routeDirection;
#property (nonatomic,retain) NSString *routeName;
#property (nonatomic,retain) NSString *routeCode;
-(id)initWithName:(NSString *)name direction:(NSString *)d routeId:(NSString *)rid code:(NSString *)c;
#end
The Route.m file:
#import "Route.h"
#implementation Route
#synthesize routeId;
#synthesize routeDirection;
#synthesize routeName;
#synthesize routeCode;
-(id)initWithName:(NSString *)name direction:(NSString *)d routeId:(NSString *)rid code:(NSString *)c{
self.routeId=rid;
self.routeName=name;
self.routeDirection=d;
self.routeCode=c;
return self;
}
#end
Now this is the RoutesListView.h file (a UITableViewController)
#import <UIKit/UIKit.h>
#import "Route.h"
#interface RoutesListView : UITableViewController <UITableViewDelegate,UITableViewDataSource> {
NSMutableArray *routeArray;
NSString *dbName;
NSString *dbPath;
}
#property (nonatomic,retain) NSMutableArray *routeArray;
#property (nonatomic,retain) NSString *dbName;
#property (nonatomic,retain) NSString *dbPath;
-(void)readRoutes;
#end
Inside the RoutesListView.m file :
#import "RoutesListView.h"
#import "Route.h"
#import <sqlite3.h>
#implementation RoutesListView
#synthesize routeArray;
#synthesize dbName,dbPath;
#pragma mark -
#pragma mark View lifecycle
- (void)viewDidLoad {
dbName = #"data.db";
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
dbPath = [documentsDir stringByAppendingPathComponent:dbName];
routeId =[[NSMutableArray alloc] init];
//routeArray
NSMutableArray * array = [[NSMutableArray alloc] init];
self.routeArray = array;
[array release];
[self readRoutes];
[super viewDidLoad];
}
INSIDE THE readRoutes method when I fill the NSMutableArray (The method work fine...):
while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
// Read the data from the result row
NSString *aId = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 0)];
NSString *aDirection =[NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 1)];
NSString *aName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 2)];
NSString *aCode = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 3)];
Route *maRoute = [[Route alloc] initWithName:aName direction:aDirection routeId:aId code:aCode];
// I fill the NSMutableArray here...
[routeArray addObject:maRoute];
[maRoute release];
[aId release];
[aDirection release];
[aName release];
[aCode release];
}
FINALLY WHEN I SET THE CELL TEXTLABEL...IT CRASH! :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell...
NSUInteger row = [indexPath row];
Route *myRoute = (Route *)[routeArray objectAtIndex:row];
cell.textLabel.text = myRoute.routeName;
[myRoute release];
return cell;
}
Help me to understand... I lost my hair on that...
Thanks
Maxime

You are over releasing several objects which will usually cause your application to crash. Also your init function is not properly implemented inside of your Route.m file. Make the following changes.
#import "Route.h"
#implementation Route
#synthesize routeId;
#synthesize routeDirection;
#synthesize routeName;
#synthesize routeCode;
-(id)initWithName:(NSString *)name direction:(NSString *)d routeId:(NSString *)rid code:(NSString *)c{
//Must call supers implementation of init
self = [super init];
if(self)
{
self.routeId=rid;
self.routeName=name;
self.routeDirection=d;
self.routeCode=c;
}
return self;
}
#end
Next you are over releasing objects inside of readRoutes
while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
// Read the data from the result row
NSString *aId = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 0)];
NSString *aDirection =[NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 1)];
NSString *aName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 2)];
NSString *aCode = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 3)];
Route *maRoute = [[Route alloc] initWithName:aName direction:aDirection routeId:aId code:aCode];
// I fill the NSMutableArray here...
[routeArray addObject:maRoute];
[maRoute release]; //This is right you called alloc/init
[aId release]; //This is wrong never retained,copy or alloc/init
[aDirection release];//Dont release here either
[aName release]; //Dont release
[aCode release]; //Dont release
}
And finally you are over releasing the route inside of the following code
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell...
NSUInteger row = [indexPath row];
Route *myRoute = (Route *)[routeArray objectAtIndex:row];
cell.textLabel.text = myRoute.routeName;
[myRoute release]; //Do not release route here
return cell;
}

Related

problem with NSMutableArray

i declared a NSMutable array and assigned some values to it .
.h
NSMutableArray *imageDetailsFromCategory;
#property (nonatomic, retain) NSMutableArray *imageDetailsFromCategory;
.m
#synthesise imageDetailsFromCategory
in ViewDidLoad:
imageDetailsFromCategory = [[NSMutableArray alloc]init];
//assigning object to Array..working fine.showing two images.
imageDetailsFromCategory = [self getImageDetailsFromCategory:generatedString];
i had one problem that solved now. i have a problem that is i am passing this array to StaticCategoryWithMultiImagePopOver class.
StaticCategoryWithMultiImagePopOver *staticCategoryWithMultiImagePopOver = [[StaticCategoryWithMultiImagePopOver alloc] init];
[staticCategoryWithMultiImagePopOver setParentImageDetailsArray:imageDetailsFromCategory];
in StaticCategoryWithMultiImagePopOver.h
NSMutableArray *nsmResult;
#property (nonatomic,retain)NSMutableArray *nsmResult;
.m
#synthesize nsmResult
-(void)setParentImageDetailsArray:(NSMutableArray *)imageDetailsFromCategoryFromParent{
nsmResult=[[NSMutableArray alloc] init];
nsmResult=[imageDetailsFromCategoryFromParent retain];
}
the passed array hold a class object with some string variables at each index.
so i am getting this through the code:
- (UITableViewCell *)tableView:(UITableView *)tableView15 cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView15 dequeueReusableCellWithIdentifier:CellIdentifier];
// if (cell == nil) {
// cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
// }
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
NSFileManager *fileManager = [NSFileManager defaultManager];//create instance of NSFileManager
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); //create an array and store result of our search for the documents directory in it
NSString *documentsDirectory = [paths objectAtIndex:0];
SymbolTalkEntry *symbolTalkEntry = [[SymbolTalkEntry alloc]init];
symbolTalkEntry =[nsmResult objectAtIndex:indexPath.row];
NSString *imageNme = symbolTalkEntry.fileName; // *this line*
the above line is getting error.
array shows the count but the objects are out of scope..cant get the values ...
can any one tell me how can i access it...may i know what is the problem with me...
cellForRowAtIndexPath(its working fine)
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView15 cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView15 dequeueReusableCellWithIdentifier:CellIdentifier];
// if (cell == nil) {
// cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
// }
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
NSFileManager *fileManager = [NSFileManager defaultManager];//create instance of NSFileManager
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); //create an array and store result of our search for the documents directory in it
NSString *documentsDirectory = [paths objectAtIndex:0];
SymbolTalkEntry *symbolTalkEntry = [[SymbolTalkEntry alloc]init];
symbolTalkEntry =[nsmResult objectAtIndex:indexPath.row];
NSString *imageNme = symbolTalkEntry.fileName;
[symbolTalkEntry release];
//Display image from app bundle
NSString *path = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.png",imageNme]];
cell.imageView.image= [UIImage imageWithContentsOfFile:path];
return cell;
}
-(NSInteger)number
This
nsmResult=[[NSMutableArray alloc] init];
nsmResult=[imageDetailsFromCategoryFromParent retain];
and this
SymbolTalkEntry *symbolTalkEntry = [[SymbolTalkEntry alloc]init];
symbolTalkEntry =[nsmResult objectAtIndex:indexPath.row];
are memory leaks.
About your problem: the object you get by
symbolTalkEntry =[nsmResult objectAtIndex:indexPath.row];
seems not to have a property fileName.
I think you should read a good book about Objective-C and Cocoa.
Actually it's the problem of the class which is inside the array.
I changed my class as this:
#import <Foundation/Foundation.h>
#interface SymbolTalkEntry : NSObject {
int categoryId;
NSString *runModeType;
NSString *sceneCategory;
NSString *fileName;
int isDefault;
int sortX;
int pathId;// 0 for appbundle 1 for document directry
}
#property (nonatomic, retain)NSString *runModeType;;
#property (nonatomic, retain)NSString *sceneCategory;
#property (nonatomic, retain)NSString *fileName;
-(id)init;
-(void) setCategoryId:(int) ctgId;
-(int)categoryId;
-(void) setRunModeType:(NSString *)rmType;
-(NSString *) runModeType;
-(void) setSceneCategory:(NSString *)scCategory;
-(NSString *) sceneCategory;
-(void) setFileName:(NSString *)Flname;
-(NSString *) fileName;
-(void) setIsDefault:(int) isDeft;
-(int)isDefault;
-(void) setSortX:(int) srtX;
-(int)sortX;
-(void) setPathId:(int) srtX;
-(int)pathId;
#end
[5:05:00 AM] Shamsudheen TK: #import "SymbolTalkEntry.h"
#implementation SymbolTalkEntry
#synthesize runModeType;
#synthesize sceneCategory;
#synthesize fileName;
-(id) init{
categoryId = 0;
runModeType = #"";
sceneCategory =#"";
fileName = #"";
isDefault = 0;
sortX =0;
pathId =0;
return self;
}
-(void) setCategoryId:(int) ctgId{
categoryId = ctgId;
}
-(int)categoryId{
return categoryId;
}
-(void) setRunModeType:(NSString *)rmType{
if (runModeType != rmType) {
[runModeType release ];
runModeType = [rmType retain];
}
}
-(NSString *) runModeType{
return runModeType;
}
-(void) setSceneCategory:(NSString *)scCategory{
if (sceneCategory != scCategory) {
[sceneCategory release];
sceneCategory = [scCategory retain];
}
}
-(NSString *) sceneCategory{
return sceneCategory;
}
-(void) setFileName:(NSString *)Flname{
if (fileName != Flname) {
[fileName release];
fileName = [Flname retain];
}
}
-(NSString *) fileName{
return fileName;
}
-(void) setIsDefault:(int) isDeft{
isDefault = isDeft;
}
-(int)isDefault{
return isDefault;
}
-(void) setSortX:(int) srtX{
sortX =srtX;
}
-(int)sortX{
return sortX;
}
-(void) setPathId:(int) srtX{
pathId = srtX;
}
-(int)pathId{
return pathId;
}
-(void)dealloc{
[categoryId release];
[runModeType release];
[sceneCategory release];
[fileName release];
[isDefault release];
[sortX release];
[pathId release];
}
#end
and set the values using the set methods that I wrote (eg: [classobj setCategoryId:1]).
now out of scope is solved.....

inserting NSURL or integer in NSDictionary

i have a class 'book.h' in which i have declared
Book.h
NSInteger WeatherID;
NSString *Description;
NSURL *PictureURL;
BookDetailview.h
#import <UIKit/UIKit.h>
#class Book, XMLAppDelegate;
#interface BookDetailViewController : UIViewController
{
IBOutlet UITableView *tableView;
XMLAppDelegate *appDelegate;
Book *aBook; //creating object of 'Book-class'
NSMutableDictionary *EmpDictionary;
NSMutableArray *EmpArray;
}
#property (nonatomic, retain) Book *aBook;
#property (nonatomic, retain) NSMutableArray *EmpArray;
#end
BookDetailView.m
(UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"creation of cell");
static NSString *CellIdentifier = #"Cell";
ImageCell *cell = (ImageCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; // creating cell from ImageCell.m
NSLog(#"calling image class");
if (cell == nil) {
cell = [[[ImageCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease]; // allocating with frame
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
NSLog(#"abook ...pictutre url......%#" , aBook.PictureURL);
EmpDictionary=[[NSMutableDictionary alloc]init];
[EmpDictionary setValue:aBook.Description forKey:#"Description"];
[EmpDictionary setValue:aBook.PictureURL forKey:#"PictureURL"];
[EmpDictionary setValue:aBook.WeatherID forKey:#"WeatherID"];
EmpArray=[[NSMutableArray alloc]init];
[EmpArray addObject:EmpDictionary];
NSDictionary *itemAtIndex = [self.EmpArray objectAtIndex:indexPath.row];
[cell setData:itemAtIndex]; //call to 'setData' meyhod to ImageCell.m
NSLog(#"set text of a cell");
return cell;
}
ImageCell.m
-(void)setData:(NSDictionary *)dic {
self.titleLabel.text = [dic objectForKey:#"Description"];
self.urlLabel.text = [dic objectForKey:#"PictureURL"];
self.itemID = (NSInteger)[dic objectForKey:#"WeatherID"];
NSLog(#"setting objects for keys");
// setting up the imageView now
self.imageView.image = [UIImage imageWithData: [NSData dataWithContentsOfURL: [NSURL URLWithString: [dic objectForKey:#"PictureURL"]]]];
NSLog(#"setting of image");
}
[dict setValue:value forKey:key];
[dict setObject:object forKey:key];
NSDictionary *dict1 = [[NSDictionary alloc] initWithObjectsAndKeys:
#"val1", #"key1", #"val2", #"key2", #"val3", #"key3",#"val4", #"key4",#"val5", #"key5",nil];

Leaks when adding-removing objects to a MutableArray

i have a memory leak in my app.
My app launches on a tableviewcontroller. i parse a json file to fill an array. Then this array is used to fill the tableview's cells.
I fill my array with objects (class).
I do:
[tab_Demandes removeAllObjects];
for (NSDictionary *demandeD in demandes)
{
Demande *dem =[[Demande alloc] init];
dem.demTitle=title;
dem.demId=Id;
dem.demCreated=created;
[tab_Demandes addObject:dem];
[dem release];
}
My array and tableview are filled at launch, no problem.
if i hit a table cell and then want to come back on the tableview my app crash on :
[tab_Demandes removeAllObjects];
If i dont do [dem release] i have leaks in instruments every time i reload tab_Demandes. RemoveAllObjects works but i have leaks.
Thx for any help as usual.
Wallou
++
Edit : here is where i made my cells. Maybe i mess up when creating the cells
Actually tab_Demandes is declared in the delegate with get/set to access it from other classes (where i load my tableviewcontroller).
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
CustomCellViewController *cell = (CustomCellViewController *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
// NSLog(#"Cell created");
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"CustomCellViewController" owner:nil options:nil];
for(id currentObject in topLevelObjects)
{
if([currentObject isKindOfClass:[CustomCellViewController class]])
{
cell = (CustomCellViewController *)currentObject;
break;
}
}
}
// Set up the cell...
TabsAppDelegate *appDelegate = (TabsAppDelegate*)[[UIApplication sharedApplication] delegate];
cell.lbl_demId.text=[NSString stringWithFormat:#"%#", [[[appDelegate tab_Demandes] objectAtIndex:indexPath.row ] demId]];
cell.lbl_demCopro .text=[NSString stringWithFormat:#"%#", [[[appDelegate tab_Demandes] objectAtIndex:indexPath.row] demIdCopro ]];
cell.lbl_demImmeuble.text=[NSString stringWithFormat:#"%#", [[[appDelegate tab_Demandes] objectAtIndex:indexPath.row] demIdImmeuble]];
cell.lbl_demLot.text=[NSString stringWithFormat:#"%#", [[[appDelegate tab_Demandes] objectAtIndex:indexPath.row] demIdLot]];
cell.lbl_demDescriptif.text=[NSString stringWithFormat:#"%#", [[[appDelegate tab_Demandes] objectAtIndex:indexPath.row] demTitle]];
//NSLog(#"statut demande : %#",[[tab_Demandes objectAtIndex:indexPath.row] demStatut]);
if ([[[[appDelegate tab_Demandes] objectAtIndex:indexPath.row] demStatut] isEqualToString: #"Validée"])
{
cell.lbl_ImageView.image=[UIImage imageNamed:#"VDEM2.png"];
}
if([[[[appDelegate tab_Demandes] objectAtIndex:indexPath.row] demStatut] isEqualToString: #"Initiée"])
{
cell.lbl_ImageView.image=[UIImage imageNamed:#"IDEM.png"];
}
if([[[[appDelegate tab_Demandes] objectAtIndex:indexPath.row] demStatut] isEqualToString: #"Terminée"])
{
cell.lbl_ImageView.image=[UIImage imageNamed:#"TDEM.png"];
}
if([[[[appDelegate tab_Demandes] objectAtIndex:indexPath.row] demStatut] isEqualToString: #"En coursée"])
{
cell.lbl_ImageView.image=[UIImage imageNamed:#"EDEM.png"];
}
return cell;
}
NEW EDIT:
Demandes.h:
#interface Demande : NSObject {
NSString *demId;
NSString *demStatut;
NSString *demTitle;
NSString *demCreated;
NSString *demIdCopro;
NSString *demIdImmeuble;
NSString *demIdLot;
NSString *demDescriptif;
NSString *demAuteur;
NSString *demIdAuteur;
NSString *demLoginAuteur;
}
#property (retain,nonatomic) NSString *demId;
#property (retain,nonatomic) NSString *demIdCopro;
#property (retain,nonatomic) NSString *demIdImmeuble;
#property (retain,nonatomic) NSString *demIdLot;
#property (retain,nonatomic) NSString *demDescriptif;
#property (retain,nonatomic) NSString *demStatut;
#property (retain,nonatomic) NSString *demTitle;
#property (retain,nonatomic) NSString *demCreated;
#property (retain,nonatomic) NSString *demAuteur;
#property (retain,nonatomic) NSString *demIdAuteur;
#property (retain,nonatomic) NSString *demLoginAuteur;
#end
Demandes.m:
import "Demande.h"
#implementation Demande
#synthesize demId,demIdCopro,demIdImmeuble,demIdLot,demDescriptif,demStatut,demTitle,demCreated,demAuteur,demIdAuteur,demLoginAuteur;
- (void)dealloc {
[demId release];
[demIdCopro release];
[demId release];
[demIdImmeuble release];
[demIdLot release];
[demDescriptif release];
[demStatut release];
[demTitle release];
[demCreated release];
[demAuteur release];
[demIdAuteur release];
[demLoginAuteur release];
[super dealloc];
}
#end
The code above is correct. I wondering if you don't over release objects that are in you array (i.e. during tableView:cellForRowAtIndexPath method). When calling removeAllObject, the method release every object it removes. If one object is already released and deallocated, you app will crash.
Proposed Optimization :
-Be sure that the cellIdentifier in the nib is well #"Cell"
-Replace
cell.lbl_demId.text=[NSString stringWithFormat:#"%#", [[[appDelegate tab_Demandes] objectAtIndex:indexPath.row ] demId]];
by
Demand* dem = [[[appDelegate tab_Demandes] objectAtIndex:indexPath.row ];
cell.lbl_demId.text=[NSString stringWithFormat:#"%#", [dem demId]];
to avoid querying the array too much time.
-Avoid placing your model in the appDelegate and create a singleton model object instead. This is a common beginner design mistake driven by the fact that the appDelegate is an easy object to customize and access to avoid passing you model to every objects.

NSMutbleArray - add/remove objects with properties - leaks

i have a leak issue in my app.
I'm trying to add and remove objects to a NSMutableArray.
Here is the class Demande :
#interface Demande : NSObject {
//attibuts de la classe demande
NSString *demId;
NSString *demStatut;
NSString *demTitle;
NSString *demCreated;
NSString *demIdCopro;
NSString *demIdImmeuble;
NSString *demIdLot;
NSString *demDescriptif;
NSString *demAuteur;
NSString *demIdAuteur;
NSString *demLoginAuteur;
}
#property (retain,nonatomic) NSString *demId;
#property (retain,nonatomic) NSString *demIdCopro;
#property (retain,nonatomic) NSString *demIdImmeuble;
#property (retain,nonatomic) NSString *demIdLot;
#property (retain,nonatomic) NSString *demDescriptif;
#property (retain,nonatomic) NSString *demStatut;
#property (retain,nonatomic) NSString *demTitle;
#property (retain,nonatomic) NSString *demCreated;
#property (retain,nonatomic) NSString *demAuteur;
#property (retain,nonatomic) NSString *demIdAuteur;
#property (retain,nonatomic) NSString *demLoginAuteur;
#end
#import "Demande.h"
#implementation Demande
#synthesize demId,demIdCopro,demIdImmeuble,demIdLot,demDescriptif,demStatut,demTitle,demCreated,demAuteur,demIdAuteur,demLoginAuteur;
- (void)dealloc {
[demId release];
[demIdCopro release];
[demId release];
[demIdImmeuble release];
[demIdLot release];
[demDescriptif release];
[demStatut release];
[demTitle release];
[demCreated release];
[demAuteur release];
[demIdAuteur release];
[demLoginAuteur release];
[super dealloc];
}
#end
What i try to do in MyTableViewController :
#interface MyTableViewController : UITableViewController {
IBOutlet UITableView *tableV;
NSMutableArray *tab_Demandes;
}
#end
#implementation MyTableViewController
- (void)requestDReloadDone:(ASIHTTPRequest *)request
{
NSData *responseData = [request responseData];
NSString *jsonString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
//NSLog(#"JSON: %#",jsonString);
NSDictionary *results = [jsonString JSONValue];
NSArray *demandes = [results objectForKey:#"Demandes"];
[tab_Demandes removeAllObjects]; // -------- CRASH HERE !!!, except the first time through the method because the array is empty
for (NSDictionary *demandeD in demandes)
{
//parse du JSON
NSString *titre = [demandeD objectForKey:#"Title"];
NSString *desriptif = [demandeD objectForKey:#"Description"];
NSString *Id = [demandeD objectForKey:#"Id"];
NSString *created = [demandeD objectForKey:#"Created"];
NSString *statut = [demandeD objectForKey:#"Statut"];
NSString *copropriete = [demandeD objectForKey:#"Copropriete"];
NSString *immeuble = [demandeD objectForKey:#"Immeuble"];
NSString *lot = [demandeD objectForKey:#"Lot"];
NSString *auteur = [demandeD objectForKey:#"Author"];
NSString *auteurId = [demandeD objectForKey:#"IdAuthor"];
NSString *auteurLogin = [demandeD objectForKey:#"Login"];
//Creation de l'objet
Demande *dem =[[Demande alloc] init];
dem.demTitle=titre;
dem.demId=Id;
dem.demCreated=created;
NSString *descriptifDecode = [desriptif stringByReplacingPercentEscapesUsingEncoding:
NSASCIIStringEncoding];
dem.demDescriptif=descriptifDecode;
dem.demIdCopro=copropriete;
dem.demIdImmeuble=immeuble;
dem.demIdLot=lot;
dem.demStatut=statut;
dem.demAuteur=auteur;
dem.demIdAuteur=auteurId;
dem.demLoginAuteur=auteurLogin;
[tab_Demandes addObject:dem];
[dem release];
}
[tableV reloadData];
[jsonString release];
}
On the first launch of the app my array tab_Demandes is empty so everything is fine [removeAllObjects] works as there are no objects in it.
When i reload the tab_Demandes i need to clear it. That's when the app crashes
I realised that if i do :
- (void)dealloc {
/*
[demId release];
[demIdCopro release];
[demId release];
[demIdImmeuble release];
[demIdLot release];
[demDescriptif release];
[demStatut release];
[demTitle release];
[demCreated release];
[demAuteur release];
[demIdAuteur release];
[demLoginAuteur release];
*/
[super dealloc];
}
in the Demande class i then can do
[tab_Demandes removeAllObjects]
in TableViewController.
But then i have the properties as leaked for each object Demande. It's like when i do [dem release] the properties are also rleased and when i want to do [removeAllObjects] from my tab_Demandes there are no properties to release and i get a Bad_Access.
If anyone has an idea ...
EDIT: cellForROw method:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
CustomCellViewController *cell = (CustomCellViewController *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
// NSLog(#"Cell created");
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"CustomCellViewController" owner:nil options:nil];
for(id currentObject in topLevelObjects)
{
if([currentObject isKindOfClass:[CustomCellViewController class]])
{
cell = (CustomCellViewController *)currentObject;
break;
}
}
}
// Set up the cell...
cell.lbl_demId.text=[NSString stringWithFormat:#"%#", [[tab_Demandes objectAtIndex:indexPath.row ] demId]];
cell.lbl_demCopro .text=[NSString stringWithFormat:#"%#", [[tab_Demandes objectAtIndex:indexPath.row] demIdCopro ]];
cell.lbl_demImmeuble.text=[NSString stringWithFormat:#"%#", [[tab_Demandes objectAtIndex:indexPath.row] demIdImmeuble]];
cell.lbl_demLot.text=[NSString stringWithFormat:#"%#", [[tab_Demandes objectAtIndex:indexPath.row] demIdLot]];
cell.lbl_demDescriptif.text=[NSString stringWithFormat:#"%#", [[tab_Demandes objectAtIndex:indexPath.row] demTitle]];
if ([[[tab_Demandes objectAtIndex:indexPath.row] demStatut] isEqualToString: #"Validée"])
{
cell.lbl_ImageView.image=[UIImage imageNamed:#"VDEM2.png"];
}
if([[[tab_Demandes objectAtIndex:indexPath.row] demStatut] isEqualToString: #"Initiée"])
{
cell.lbl_ImageView.image=[UIImage imageNamed:#"IDEM.png"];
}
if([[[tab_Demandes objectAtIndex:indexPath.row] demStatut] isEqualToString: #"Terminée"])
{
cell.lbl_ImageView.image=[UIImage imageNamed:#"TDEM.png"];
}
if([[[tab_Demandes objectAtIndex:indexPath.row] demStatut] isEqualToString: #"En coursée"])
{
cell.lbl_ImageView.image=[UIImage imageNamed:#"EDEM.png"];
}
return cell;
}
Where it tab_Demandes being intialized?
It's not enough to only declare it in the .h file, you must also tell the compiler to alloc and init it.
A simple fix might be replacing the line [tab_Demandes removeAllObjects]; with
if(!tab_Demandes) { // tab_Demandes is nil and has not previously been created
tab_Demandes = [[NSMutableArray arrayWithCapacity:10] retain];
} else {
[tab_Demandes removeAllObjects];
}
Don't forget to [tab_Demandes release] in your dealloc method

iPhone Application Exit when scrolling the UITableView

I have declared a NSMutableArray and I populated it with information from the database. The table displays information well. But when I scroll down, the application exits. Seems like its loosing the pointer to the array.
Here is the code for declaration of the array:
#interface RootViewController : UITableViewController <CLLocationManagerDelegate> {
sqlite3 *database;
NSMutableArray *storeList;
CLLocationManager *locationManager;
CLLocation *startingPoint;
}
#property (nonatomic, retain) NSMutableArray *storeList;
#property (nonatomic, retain) CLLocationManager *locationManager;
#property (nonatomic, retain) CLLocation *startingPoint;
- (void) createCopyOfDatabaseIfNeeded;
- (void) initializeStoreList;
- (void) getDistanceFromUserLocation;
Here I am initializing the array with object of type StoreInfo:
- (void) initializeStoreList{
self.storeList = [[NSMutableArray alloc] init];
//database is stored in the application bundle.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *dbPath = [documentsDirectory stringByAppendingPathComponent:kFileName];
if (sqlite3_open([dbPath UTF8String], &database)== SQLITE_OK) {
const char *sql = "select id, storename, ratings, lattitude, longitude from storeinformation";
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(database, sql, -1, &statement, NULL) == SQLITE_OK) {
while (sqlite3_step(statement) == SQLITE_ROW) {
NSInteger *_pk = (NSInteger *) sqlite3_column_int(statement, 0);
NSString *_storeName = [NSString stringWithUTF8String:(char*) sqlite3_column_text(statement, 1)];
NSString *_ratings = [NSString stringWithUTF8String:(char*) sqlite3_column_text(statement, 2)];
double _lattitude = [[NSString stringWithUTF8String:(char*) sqlite3_column_text(statement, 3)] doubleValue];
double _longitude = [[NSString stringWithUTF8String:(char*) sqlite3_column_text(statement, 4)] doubleValue];
StoreInfo *si = [[StoreInfo alloc] initWithBasicInformation:_pk storeName:_storeName ratings:_ratings lattitude:_lattitude longitude:_longitude];
[self.storeList addObject:si];
[si release];
}
}
sqlite3_finalize(statement);
} else {
sqlite3_close(database);
NSAssert1(0,#"Failed to open the database with message '%s'.", sqlite3_errmsg(database));
}
}
here is the constructor for StoreInfo object
-(id)initWithBasicInformation:(NSInteger *)_pk storeName:(NSString *) _storeName ratings:(NSString *) _ratings lattitude:(double) _lattitude longitude:(double) _longitude;
{
if (self = [super init]) {
self.primaryKey = _pk;
self.storeName = _storeName;
self.ratings = _ratings;
self.lattitude = _lattitude;
self.longitude = _longitude;
}
return self;
}
Here is the code for displaying the cell:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell.
StoreInfo *si = (StoreInfo *)[self.storeList objectAtIndex:indexPath.row];
cell.textLabel.text = si.storeName;
return cell;
}
The table displays alright first. But when I scroll down, this even gets fired and somehow it is not able to find reference to the si.storeName.
I have spent hours trying to debug the issue. Any help is greatly appreciated.
First of all, how have you defined the property for the problematic field?
Is it retain?
Secondly, Can you access any other property in si?
And finally, I see that there is a memory leak in self.storeList = [[NSMutableArray alloc] init]; - the object is retained twice (in init and in the property setter)...