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)...
Related
I'm working on an iPhone project in Xcode 4.3 with SQlite3, the connection between the SQlite and Xcode is done, now I want to display my data into a table views (three views) and its read only!
so I have the main table view, select raw --> take to 2nd view and load other data from the DB select raw --> take to the details view to display long text and image!
Any help appreciated.
AppDelegate.h
#import "AppDelegate.h"
#import "MasterViewController.h"
#implementation AppDelegate
#synthesize window = _window;
#synthesize navigationController = _navigationController;
- (void)dealloc
{
[_window release];
[_navigationController release];
[super dealloc];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
NSString *dbPath = [documentsDir stringByAppendingPathComponent:#"cities.sqlite"];
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL success = [fileManager fileExistsAtPath:dbPath];
if (success) {
NSLog(#"we have the database");
} else {
NSLog(#"we have no database");
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"cities.sqlite"];
BOOL moved = [fileManager copyItemAtPath:defaultDBPath toPath:dbPath error:nil];
if (moved) {
NSLog(#"database copied");
}
}
MasterViewController *masterViewController = [[[MasterViewController alloc] initWithNibName:#"MasterViewController" bundle:nil] autorelease];
self.navigationController = [[[UINavigationController alloc] initWithRootViewController:masterViewController] autorelease];
self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible];
return YES;
}
MasterViewController.h
#import <UIKit/UIKit.h>
#import <sqlite3.h>
#class DetailViewController;
#interface MasterViewController : UITableViewController {
NSMutableArray *cities;
}
#property (strong, nonatomic) DetailViewController *detailViewController;
#end
MasterViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
students = [[NSMutableArray alloc] init];
countries = [[NSMutableArray alloc] init];
// Do any additional setup after loading the view, typically from a nib.
self.navigationItem.leftBarButtonItem = self.editButtonItem;
UIBarButtonItem *addButton = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:#selector(insertNewObject:)] autorelease];
self.navigationItem.rightBarButtonItem = addButton;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
NSString *dbPath = [documentsDir stringByAppendingPathComponent:#"cities.sqlite"];
sqlite3 *database;
if (sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK) {
const char *sqlStatement = "select * from cities_info";
sqlite3_stmt *compileStatement;
if (sqlite3_prepare_v2(database, sqlStatement, -1, &compileStatement, NULL) == SQLITE_OK) {
while (sqlite3_step(compileStatement) == SQLITE_ROW) {
NSLog(#"one record");
NSString *cityName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compileStatement, 1)];
[cities addObject:cityName];
}
NSLog(#"cities: %#",cities);
}
} else {
NSLog(#"error in database");
}
}
Blockquote
I suggest a light wrapper over SQLite - see https://github.com/JohnGoodstadt/EasySQLite
This will allow:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return _personTable.rows.count;
}
AND
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
...
NSArray* row= _personTable.rows[indexPath.row];
cell.textLabel.text = row[[_personTable colIndex:#"lastname"]];
...
Set this up by using an iVar representing a SQL Table:
self.personTable = [_db ExecuteQuery:#"SELECT firstname , lastname , age , salary FROM person"];
And a DB Connection iVar passing in your SQL file name:
self.db = [DBController sharedDatabaseController:#"DataTable.sqlite"];
First of all, I suggest using FMDB, which is an Objective-C wrapper around sqlite3. Secondly, I'd create a custom Data Access Object with a shared instance, like so:
#interface MyDatabaseDAO : NSObject
#property (nonatomic, strong) FMDatabase *database;
#end
#implementation MyDatabaseDAO
#synthesize database = _database;
+ (MyDatabaseDAO *)instance {
static MyDatabaseDAO *_instance = nil;
#synchronized (self) {
if (_instance == nil) {
_instance = [[self alloc] init];
}
}
return _instance;
}
- (id)init {
self.database = [FMDatabase databaseWithPath:myDatabasePath];
[self.database open];
}
- (void)dealloc {
[self.database close];
}
#end
This DAO must have 3 access methods: one for each data object in the database. Because you weren't specific, I made these objects without any specific properties.
- (NSArray *)retrieveAllFirstViewItems {
NSMutableArray *items = [NSMutableArray array];
FMResultSet *resultSet = [FMDBDatabase.database executeQuery:#"SELECT * FROM myFirstViewItemTable"];
while ([resultSet next]) {
// extract whatever data you want from the resultset
NSString *name = [resultSet stringForColumn:#"name"]
[items addObject:name];
}
[resultSet close];
return items;
}
- (MySecondViewItem *)retrieveSecondViewItemFromIndexPath:(NSIndexPath *)indexPath {
FMResultSet *resultSet = [FMDBDatabase.database executeQuery:#"SELECT * FROM mySecondViewItemTable WHERE pid = ?", [indexPath indexAtPosition:0]];
if ([resultSet next]) {
// extract whatever data you want from the resultset
NSString *name = [resultSet stringForColumn:#"name"]
MySecondViewItem *mySecondViewItem = [[MySecondViewItem alloc]
initWithName:name withPID:[indexPath indexAtPosition:0]];
[resultSet close];
return mySecondViewItem;
} else {
return nil;
}
}
- (MyThirdViewItem *)retrieveThirdViewItemFromIndexPath:(NSIndexPath *)indexPath {
FMResultSet *resultSet = [FMDBDatabase.database executeQuery:#"SELECT * FROM mySecondViewItemTable WHERE pid = ?", [indexPath indexAtPosition:1]];
if ([resultSet next]) {
// extract whatever data you want from the resultset
NSString *name = [resultSet stringForColumn:#"name"]
MyThirdViewItem *myThirdViewItem = [[MyThirdViewItem alloc]
initWithName:name withPID:[indexPath indexAtPosition:1]];
[resultSet close];
return myThirdViewItem;
} else {
return nil;
}
}
Since it's read-only, these are all the required methods. In your first UITableView, just implement method:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
MySecondViewItem *mySecondViewItem = [[MyDatabaseDAO instance] retrieveSecondViewItemFromIndexPath:indexPath];
//instantiate a view from this item and use [UINavigationController pushViewController:animated:] to navigate to it
}
All that's left is just to show your data objects in views somehow. I sugget doing as much of the data retrieval as possible in the Data Access Object so that the view controllers can read the properties of the data objects without having to worry about the backend.
That's all there is to it! I hope this helped
I am doing an iPad app, were i will have UITabelview and a Button and UiTextview in same screen. My task is that if i select some row in UITableview and press button the text has to be appeared on the UITextview.
I filled few methods but it didn't work can any one let me know what exactly i can do to complete this task successfully.
Please find my code below for your reference...it may help you to explain my problem.
#import <UIKit/UIKit.h>
#import "table1.h"
#import "textView.h"
#interface searchOne : UIViewController
{
IBOutlet UITableView *firstTable;
table1 *tableOne;
textView * text1;
int row;
}
#property(nonatomic,retain)IBOutlet UIButton * search;
#property (nonatomic,retain) IBOutlet UITextView *txt;
#property(nonatomic, assign) int row;
-(IBAction)resPage:(id)sender;
#end
#import "searchOne.h"
#import "textView.h"
#implementation searchOne
#synthesize search;
#synthesize txt, row;
- (void)viewDidLoad {
[super viewDidLoad];
if (tableOne == nil) {
tableOne = [[table1 alloc] init];
}
[firstTable setDataSource:tableOne];
tableOne.view = tableOne.tableView;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
row = [indexPath row];
}
-(IBAction)resPage:(id)sender{
NSString *str = txt.text;
row = [str intValue];
NSLog(#"get clicked");
self.view =txt;
}
/*
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
// [self setTxt:nil];
[super viewDidUnload];
}
#end
DB:
#import <Foundation/Foundation.h>
#interface db : NSObject{
NSInteger ID;
NSString * name;
}
#property (nonatomic, retain) NSString * name;
#property(nonatomic, readwrite) NSInteger ID;
-(id)initWithID: (NSInteger)i andName:(NSString *)n;
#end
#implementation db
#synthesize name,ID;
-(id)initWithID: (NSInteger)i andName:(NSString *)n{
self=[super init];
if(self)
{
self.ID = i;
self.name = n;
}
return self;
}
#end
Tabel view:
#import <UIKit/UIKit.h>
#import "sqlite3.h"
#import "db.h"
#interface table1 : UITableViewController<UITableViewDataSource>{
NSString *databaseName;
NSString * databasePath;
NSMutableArray * tableOne;
}
#property(nonatomic, retain) NSMutableArray * tableOne;
-(void)checkAndCreateDatabase;
-(void)readDataFromDatabase;
#end
#import "table1.h"
#import "db.h"
#implementation table1
#synthesize tableTwo;
#pragma mark - View lifecycle
- (void)viewDidLoad
{
databaseName=#"nobel10.db";
NSArray *documentPaths= NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString * documentDir = [documentPaths objectAtIndex:0];
databasePath=[documentDir stringByAppendingPathComponent:databaseName];
[self checkAndCreateDatabase];
[self readDataFromDatabase];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
#pragma mark - TableView Data Source methods
-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [tableTwo count]; }
// Row display. Implementers should *always* try to reuse cells by setting each cell's reuseIdentifier and querying for available reusable cells with dequeueReusableCellWithIdentifier:
// Cell gets various attributes set automatically based on table (separators) and data source (accessory views, editing controls)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell= nil;
cell = [tableView dequeueReusableCellWithIdentifier:#"mycell"];
if (cell == nil) {
cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"mycell"];}
db * temp =(db *)[self.tableTwo objectAtIndex:indexPath.row];
cell.textLabel.text=temp.name;
return cell;
}
-(void)checkAndCreateDatabase{
BOOL success;
NSFileManager *fileManager=[NSFileManager defaultManager];
success=[fileManager fileExistsAtPath:databasePath];
if(success)
return;
NSString *databasePathFromApp = [[[NSBundle mainBundle]resourcePath] stringByAppendingPathComponent:databaseName];
[fileManager copyItemAtPath:databasePathFromApp toPath:databasePath error:nil];
}
-(void)readDataFromDatabase{
sqlite3 *database;
tableTwo=[[NSMutableArray alloc]init];
if(sqlite3_open([databasePath UTF8String], &database)== SQLITE_OK){
const char *sqlStatement = "SELECT * FROM country";
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL)==SQLITE_OK){
while (sqlite3_step(compiledStatement)==SQLITE_ROW) {
NSInteger pId = sqlite3_column_int(compiledStatement, 0);
NSString *stringName=[NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 1)];
db *info =[[db alloc]initWithID:pId andName:stringName];
[tableTwo addObject:info];
}
}
sqlite3_finalize(compiledStatement);
}
sqlite3_close(database);
}
#end
UITextView:
#import <UIKit/UIKit.h>
#import "sqlite3.h"
#import "db.h"
#interface textView : UIViewController<UITextViewDelegate>{
NSString *databaseName;
NSString * databasePath;
NSMutableArray *textOne;
NSString *description;
}
#property(nonatomic, retain) NSMutableArray *textOne;
#property (nonatomic, retain) NSString *description;
-(void)checkAndCreateDatabase;
-(void)readDataFromDatabase;
-(id)initWithDescription:(NSString *)d;
#end
#import "textView.h"
#implementation textView
#synthesize textOne, description;;
#pragma mark - View lifecycle
- (void)viewDidLoad
{
databaseName=#"nobel10.db";
NSArray *documentPaths= NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString * documentDir = [documentPaths objectAtIndex:0];
databasePath=[documentDir stringByAppendingPathComponent:databaseName];
[self checkAndCreateDatabase];
[self readDataFromDatabase];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
#pragma mark - TableView Data Source methods
// Row display. Implementers should *always* try to reuse cells by setting each cell's reuseIdentifier and querying for available reusable cells with dequeueReusableCellWithIdentifier:
// Cell gets various attributes set automatically based on table (separators) and data source (accessory views, editing controls)
-(void)checkAndCreateDatabase{
BOOL success;
NSFileManager *fileManager=[NSFileManager defaultManager];
success=[fileManager fileExistsAtPath:databasePath];
if(success)
return;
NSString *databasePathFromApp = [[[NSBundle mainBundle]resourcePath] stringByAppendingPathComponent:databaseName];
[fileManager copyItemAtPath:databasePathFromApp toPath:databasePath error:nil];
}
-(void)readDataFromDatabase{
sqlite3 *database;
textOne=[[NSMutableArray alloc]init];
if(sqlite3_open([databasePath UTF8String], &database)== SQLITE_OK){
const char *sqlStatement = "SELECT name,item_country.id,text.item FROM country,item_country,text WHERE country.name ='India' AND country.id = item_country.id AND text.item =item_country.item ";
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL)==SQLITE_OK){
while (sqlite3_step(compiledStatement)==SQLITE_ROW) {
NSInteger pId = sqlite3_column_int(compiledStatement, 0);
NSString *stringName=[NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 1)];
db *info =[[db alloc]initWithID:pId andName:stringName];
[textOne addObject:info];
}
}
sqlite3_finalize(compiledStatement);
}
sqlite3_close(database);
}
-(id)initWithDescription:(NSString *)d{
self.description = d;
return self;
}
#end
PLease help me i am new to iPad development and struck here..
A quick and dirty way is just to remove the UITextView, and add it back in when you select the row. See if that works.
I realize this is not the question you asked, but depending on your needs, you might want to use Core Data instead. It abstracts the .sqlite database from you and does some pretty cool things in terms of memory usage, modelling objects and relationships and so on.
I am trying to do some basic table retrieval from sqlite and I keep stumbling over some memory leak I cannot figure out, especially since it appears only with one of two equivalent lines.
What I do is simple :
-Create an object (category) to hold my sqlite DB line
-Have a method that queries sqlite and returns an array of these objetcs
I put all the code here (stripped it down a bit to simplify but the I have the memory leak with this very code).
category.h:
#interface Category : NSObject {
int catId;
NSString *description;
int order;
NSString *iconName;
}
#property(nonatomic, readwrite, assign) int catId;
#property(nonatomic, retain) NSString *description;
#property(nonatomic, readwrite, assign) int order;
#property(nonatomic, retain) NSString *iconName;
#end
category.m:
#import "Category.h"
#implementation Category
#synthesize catId;
#synthesize description;
#synthesize order;
#synthesize iconName;
#end
Method to retrieve array:
-(NSMutableArray *)getAll {
NSString *query = "select id, description, catorder, image from category order by catorder";
sqlite3_stmt *statement;
NSMutableArray *categoryArray = [[NSMutableArray alloc] init];
if (sqlite3_prepare_v2([[Database sharedDatabase] instance], [query UTF8String], -1, &statement, nil) == SQLITE_OK) {
while (sqlite3_step(statement) == SQLITE_ROW) {
int dbId = sqlite3_column_int(statement, 0);
char *dbDescription = (char *)sqlite3_column_text(statement, 1);
int dbOrder = sqlite3_column_int(statement, 2);
char *dbIcon = (char *)sqlite3_column_text(statement, 3);
NSString *desc = [[NSString alloc] initWithUTF8String:dbDescription];
NSString *icon = [[NSString alloc] initWithUTF8String:dbIcon];
Category *category = [[Category alloc] init];
category.catId=dbId;
category.description = desc;
//category.description = #"Test";
category.order = dbOrder;
category.iconName = icon;
//category.icon = #"test.png";
[desc release];
[icon release];
[categoryArray addObject:category];
[category release];
}
sqlite3_finalize(statement);
}
[categoryArray autorelease];
return categoryArray;
}
This line leaks
NSString *icon = [[NSString alloc] initWithUTF8String:dbIcon];
This line doesn't
NSString *desc = [[NSString alloc] initWithUTF8String:dbDescription];
Here what instruments shows :
and when I drill down :
You don't have a dealloc method. You need to have this in your Category.m file:
-(void)dealloc
{
[description release];
[iconName release];
[super dealloc];
}
Also, I'm pretty sure you can't have a property named "description". That's a reserved method name.
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.....
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;
}