How to retrieve column values into another tableview in iPhone? - iphone

I am very beginner to IOS,I have deposit table and expense table in my database I want to retrieve only deposit amount from deposit table and expense amount from expense table into two tableviews means one is for deposit amount tableview and another one is for expense amount tableview in single screen. the below is my dbmodelclass.h in this
#import <UIKit/UIKit.h>
#import <sqlite3.h>
#interface dbModelClass : UIViewController
{
NSMutableDictionary *readDic;
NSMutableArray *readArray;
}
+(NSString *)connectDb;
+(BOOL)createTable;
+(BOOL)createTable3;
+(int)saveData:(NSMutableArray *)data;
+(int)saveData2:(NSMutableArray *)data;
+(NSMutableArray *)getData;
#end
this is my dbmodelclass.m
#import "dbModelClass.h"
#import "Expences.h"
#implementation dbModelClass;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
// Custom initialization
}
return self;
}
- (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.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
+(NSString *)connectDb
{
NSArray *docDir=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *dbFolder=[docDir objectAtIndex:0];
NSFileManager *manager=[NSFileManager defaultManager];
if (![manager fileExistsAtPath:dbFolder])
{
[manager createDirectoryAtPath:dbFolder withIntermediateDirectories:YES attributes:nil error:nil];
}
NSString *dbPath=[dbFolder stringByAppendingPathComponent:#"fappDB.sqlite"];
if (![manager fileExistsAtPath:dbPath])
{
[manager copyItemAtPath:[[[NSBundle mainBundle]resourcePath]stringByAppendingPathComponent:#"fappDB.sqlite"] toPath:dbPath error:nil];
}
NSLog(#"%#",dbPath);
return dbPath;
}
+(BOOL)createTable
{
NSString *dbpath=[dbModelClass connectDb];
sqlite3 *dbObj;
if (sqlite3_open([dbpath UTF8String], &dbObj)==SQLITE_OK)
{
sqlite3_stmt *stmt=nil;
const char *sql="create table deposit(deposit_amount VARCHAR,remarks VARCHAR)";
sqlite3_prepare_v2(dbObj, sql, -1, &stmt, nil);
if (sqlite3_step(stmt)==SQLITE_DONE)
{
NSLog(#"tabel created successfull");
}
else
{
NSLog(#"tabel already created");
}
sqlite3_finalize(stmt);
sqlite3_close(dbObj);
}
return YES;
}
+(BOOL)createTable3;
{
NSString *dbpath=[dbModelClass connectDb];
sqlite3 *dbObj;
if (sqlite3_open([dbpath UTF8String], &dbObj)==SQLITE_OK)
{
sqlite3_stmt *stmt=nil;
const char *sql="create table expense2(expense_title VARCHAR,description VARCHAR,amount VARCHAR,paidcash VARCHAR,date VARCHAR,remarks VARCHAR)";
sqlite3_prepare_v2(dbObj, sql, -1, &stmt, nil);
if (sqlite3_step(stmt)==SQLITE_DONE)
{
NSLog(#"tabel created successfull");
}
else
{
NSLog(#"tabel already created");
}
sqlite3_finalize(stmt);
sqlite3_close(dbObj);
}
return YES;
}
+(int)saveData:(NSMutableArray *)data
{
sqlite3 *dbObj;
sqlite3_stmt *stmt=nil;
NSString *dbPath=[dbModelClass connectDb];
const char *sql=[[NSString stringWithFormat:#"insert into deposit(deposit_amount,remarks) values(\"%#\",\"%#\")",[data objectAtIndex:0],[data objectAtIndex:1]]UTF8String];
if (sqlite3_open([dbPath UTF8String], &dbObj)==SQLITE_OK)
{
sqlite3_bind_text(stmt, 1, [[data objectAtIndex:0]UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 2, [[data objectAtIndex:1]UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_prepare_v2(dbObj, sql, -1, &stmt, nil);
if (sqlite3_step(stmt)==SQLITE_DONE)
{
NSLog(#"data insertion stmnt executed properly");
}
else
NSLog(#"data insertion stmnt not executed");
sqlite3_finalize(stmt);
sqlite3_close(dbObj);
}
return sqlite3_last_insert_rowid(dbObj);
}
+(int)saveData2:(NSMutableArray *)data
{
sqlite3 *dbObj;
sqlite3_stmt *stmt=nil;
NSString *dbPath=[dbModelClass connectDb];
const char *sql=[[NSString stringWithFormat:#"insert into expense2(expense_title,description,amount,paidcash,date,remarks) values(\"%#\",\"%#\",\"%#\",\"%#\",\"%#\",\"%#\")",[data objectAtIndex:0],[data objectAtIndex:1],[data objectAtIndex:2],[data objectAtIndex:3],[data objectAtIndex:4],[data objectAtIndex:5]]UTF8String];
if (sqlite3_open([dbPath UTF8String], &dbObj)==SQLITE_OK)
{
sqlite3_bind_text(stmt, 1, [[data objectAtIndex:0]UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 2, [[data objectAtIndex:1]UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 3, [[data objectAtIndex:2]UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 4, [[data objectAtIndex:3]UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 5, [[data objectAtIndex:4]UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 6, [[data objectAtIndex:5]UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_prepare_v2(dbObj, sql, -1, &stmt, nil);
if (sqlite3_step(stmt)==SQLITE_DONE)
{
NSLog(#"data insertion stmnt executed properly");
}
else
NSLog(#"data insertion stmnt not executed");
sqlite3_finalize(stmt);
sqlite3_close(dbObj);
}
return sqlite3_last_insert_rowid(dbObj);
}
-(NSMutableArray *)getData
{
sqlite3 *dbobj;
NSString *dbpath =[dbModelClass connectDb];
readArray=[[NSMutableArray alloc]init];
if(sqlite3_open([dbpath UTF8String], &dbobj)==SQLITE_OK)
{
sqlite3_stmt *statement=nil;
//**** NSString *string=#"SELECT name FROM emptable";
NSString *string=#"SELECT *FROM deposit WHERE deposit_amount";
const char *query=[string UTF8String];
if(sqlite3_prepare_v2(dbobj, query, -1, &statement, NULL)==SQLITE_OK)
{
while (sqlite3_step(statement)==SQLITE_ROW)
{
readDic=[[NSMutableDictionary alloc] init];
[readDic setObject:[NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 0)] forKey:#"deposit_amount"];
// NSString *aName=[NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 0)];
// NSString *pwd=[NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 1)];
//[readDic setObject:[NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 1)] forKey:#"remarks"];
// [readArray addObject:aName];
// [readArray1 addObject:pwd];
[readArray addObject:readDic];
// NSLog(#"%#",readDic);
}
}
sqlite3_finalize(statement);
}
NSLog(#"%#",readArray);
sqlite3_close(dbobj);
return readArray;
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#end
This is my netviewcontroller.h
#import <UIKit/UIKit.h>
#interface NetViewController : UIViewController<UITableViewDataSource,UITableViewDelegate>//DepositTable *depositCo
{
IBOutlet UILabel *depositLabel,*expenseLabel,*netvalueLabel;
IBOutlet UITextField *netvalueText;
IBOutlet UITableView *depositTable,*expenseTable;
}
#property (strong, nonatomic) UINavigationController *navigationController;
#property(strong,nonatomic)UILabel *depositLabel,*expenseLabel,*netvalueLabel;
#property(strong,nonatomic)UITextField *netvalueText;
#property(strong,nonatomic)UITableView *depositTable,*expenseTable;
-(IBAction)netvalue:(id)sender;
#end
This my netviewcontroller.m
#import "NetViewController.h"
#import "dbModelClass.h"
#interface NetViewController ()
#end
#implementation NetViewController
#synthesize depositLabel,expenseLabel,netvalueLabel,depositTable,expenseTable,netvalueText;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
[dbModelClass connectDb];
[dbModelClass getData];
NSMutableArray *issuesArray = [[NSMutableArray alloc]init]; [dbModelClass financeappDB:#"SELECT * FROM deposit" resultsArray:issuesArray];
NSLog(#"contents count:%d",[issuesArray count]);
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(IBAction)netvalue:(id)sender
{
}
#end
Please help me

There are several solutions to your question.
The best solution is actually the easiest.
Master viewController with two embedded tableViewControllers, each presenting and managing one table from your database.
During viewDidLoad, you will create an instance of each tableViewController, set it's frame to locate on the desired coordinates of your master view and add it to the master view.
Now you can have a clean and simple delegate model for each table and if you keep the instance of each tableViewController available within the master view controller (allocate as properties), you will be able to communicate to each table from the master view.
The more complicated way is to add two tableView to the master view xib, wire them both up to the datasource and delegate methods in the master viewController and then test each call to the delegate methods to determine which tableView called the method. I've done it but it's a pain to maintain in the long run.

You are not doing things good :).
Why you ar creating an object witch inherits from a UIViewController to manager the DataBase, you can just create an object that inherits from NSObject.
In the getData methode you are asking the data just for the deposit table, you should pass parameters ( table name and amount) to your methode to know if you want data from deposit table or expense2 table.
And finally in the NetViewController class you can do :
...
[dbModelClass connectDb];
NSArray *depositData = [dbModelClass getDataWith....]; // here you fetch your database with deposit table and others param
NSArray * expenseData = [dbModelClass getDataWith....]; // Here you fetch your database with expensive table and others param
Edited answer :
You can do like this for example :
-(NSMutableArray *)getDataForTable:(NSString *)tableName withAmount:(NSString *)amountName
{
sqlite3 *dbobj;
NSString *dbpath =[dbModelClass connectDb];
readArray=[[NSMutableArray alloc]init];
if(sqlite3_open([dbpath UTF8String], &dbobj)==SQLITE_OK)
{
sqlite3_stmt *statement=nil;
//**** NSString *string=#"SELECT name FROM emptable";
NSString *string = [NSString stringWithFormat:#"SELECT *FROM %# WHERE %#",tableName,amountName];
const char *query=[string UTF8String];
if(sqlite3_prepare_v2(dbobj, query, -1, &statement, NULL)==SQLITE_OK)
{
while (sqlite3_step(statement)==SQLITE_ROW)
{
readDic=[[NSMutableDictionary alloc] init];
[readDic setObject:[NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 0)] forKey:#"deposit_amount"];
// NSString *aName=[NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 0)];
// NSString *pwd=[NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 1)];
//[readDic setObject:[NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 1)] forKey:#"remarks"];
// [readArray addObject:aName];
// [readArray1 addObject:pwd];
[readArray addObject:readDic];
// NSLog(#"%#",readDic);
}
}
sqlite3_finalize(statement);
}
Add this
-(NSMutableArray *)getDataForTable:(NSString *)tableName withAmount:(NSString *)amountName in the dbModelClass.h
and now you can call this methode in NetViewController by passing it the table name and the amount :
[dbModelClass connectDb];
NSArray * depositResult = [dbModelClass getDataWith:#"deposite" amountName:#"deposit_amount"];
// Do same thing for the other table by passing it the appropriate names.
PS : this code is not tested and you should refactor it, it's just to show you how to pass parameters for a methode

Related

Can't select rows after inserting into database

i've got a Problem when i try to get data from the Database after inserting some data. I can't select any row from the database.
There are entries in the database but i can not get any result.
I comment out this line in AppDelegate::application:didFinishWithOptions
[dbAccess importWithDelegate:result];
and everything works just fine. But i can't find a solution to this problem.
I hope you can help me.
DatabaseAccess-Class.
#import "KejithDatabaseAccess.h"
#import "KejithEntryQueryDelegate.h"
#interface KejithDatabaseAccess (){
sqlite3 *db;
NSString *writableDatabase;
sqlite3_stmt *statement;
}
#end
#implementation KejithDatabaseAccess
-(id)init
{
if((self = [super init]))
{
// initialize database and store in _db
}
return self;
}
-(void)initializeDatabase
{
[self createEditableDatabase];
// open the database connection
if(sqlite3_open([writableDatabase UTF8String], &db) == SQLITE_OK){
NSLog(#"Database: Connection was opened successfully");
} else {
// if something went wrong clean everything up
sqlite3_close(db);
NSAssert1(0, #"Database: Failed to open database connection. Error: '%s'", sqlite3_errmsg(db));
}
}
-(void)closeDatabase
{
if(sqlite3_close(db) != SQLITE_OK){
NSAssert1(0, #"Database: Failed to close database connection. Error: '%s'", sqlite3_errmsg(db));
}
}
-(void)createEditableDatabase
{
BOOL success;
NSError *error;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
// create writable database and store path for later use
writableDatabase = [documentsDir stringByAppendingPathComponent:#"main-rw.db"];
success = [fileManager fileExistsAtPath: writableDatabase];
// if writable database already exists return
if(success) return;
// the editable database does not exist
// copy the default DB to the application
// documents directory
NSString *defaultPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"main.db"];
success = [fileManager copyItemAtPath:defaultPath toPath:writableDatabase error:&error];
if(!success){
NSAssert1(0, #"Database: Failed to create writable database file: '%#'.", [error localizedDescription]);
}
}
-(NSMutableArray *)queryWithDelegate
{
[self initializeDatabase];
// do we have an delegate?
if(![self delegate])
return nil;
NSMutableArray *result = [[self delegate] query:db];
[self closeDatabase];
return result;
}
-(void)importWithDelegate:(NSMutableArray *)collection
{
[self initializeDatabase];
[[self delegate] import:collection into:db];
sqlite3_finalize(statement);
[self closeDatabase];
}
-(sqlite3 *)getWritableDatabase
{
return db;
}
#end
Database Delegate-Class
#import "KejithEntryQueryDelegate.h"
#import "KejithEntry.h"
#interface KejithEntryQueryDelegate ()
#property sqlite3 *database;
#end
#implementation KejithEntryQueryDelegate
#synthesize sql;
#synthesize statement;
-(id)init
{
if((self = [super init])){
[self initSQL];
}
return self;
}
-(void)initSQL
{
sql = "SELECT _id, entry_title, entry_description, entry_phone, entry_fax, entry_email, entry_website FROM entry";
}
-(NSMutableArray *)query:(sqlite3 *)database
{
// store database
[self setDatabase:database];
// initialize array to store found objects
NSMutableArray *entries = [[NSMutableArray alloc] init];
// prepare sql statement
int sqlResult = sqlite3_prepare_v2(database, sql, -1, &statement, NULL);
if(sqlResult == SQLITE_OK){
while(sqlite3_step(statement) == SQLITE_ROW){
// allocate object to store row
KejithEntry *entry = [[KejithEntry alloc] init];
// get data from columns
NSMutableString *title = [NSMutableString stringWithString:
[NSString stringWithUTF8String:(char *) sqlite3_column_text(statement, 1)]];
NSMutableString *description = [NSMutableString stringWithString:
[NSString stringWithUTF8String:(char *) sqlite3_column_text(statement, 2)]];
NSMutableString *phone = [NSMutableString stringWithString:
[NSString stringWithUTF8String:(char *) sqlite3_column_text(statement, 3)]];
NSMutableString *fax = [NSMutableString stringWithString:
[NSString stringWithUTF8String:(char *) sqlite3_column_text(statement, 4)]];
NSMutableString *email = [NSMutableString stringWithString:
[NSString stringWithUTF8String:(char *) sqlite3_column_text(statement, 5)]];
NSMutableString *website = [NSMutableString stringWithString:
[NSString stringWithUTF8String:(char *) sqlite3_column_text(statement, 5)]];
// set data in object
[entry setId:[NSNumber numberWithInt: sqlite3_column_int(statement, 0)]];
[entry setTitle:title];
[entry setDescription:description];
[entry setPhone:phone];
[entry setFax:fax];
[entry setEmail:email];
[entry setWebsite:website];
// put object into array
[entries addObject:entry];
}
// finalize the statement to release its resources
sqlite3_finalize(statement);
} else {
// log errors
NSLog(#"Database: Problem Occured in KejithEntryQueryDelegate.m");
NSLog(#"Database: Result Code: %d", sqlResult);
NSLog(#"Database: SQL-Error: %s", sqlite3_errmsg(database));
}
return entries;
}
-(void)import:(NSMutableArray *)collection into:(sqlite3 *)database
{
if([collection count] == 0)
return;
for(KejithEntry *entry in collection){
[self importEntry:entry into:database];
}
}
-(void)importEntry:(KejithEntry *)entry into:(sqlite3 *)database
{
sql = "INSERT INTO entry (entry_id, entry_title, entry_description, entry_phone, entry_fax, entry_email, entry_website, enty_latitude, entry_longitude, entry_category_id) \
VALUES \
(0,?,?,?,?,?,?,0,0,0);";
int sqlResult = sqlite3_prepare_v2(database, sql, -1, &statement, NULL);
sqlite3_bind_text(statement, 1, [[entry title] UTF8String], -1, SQLITE_STATIC);
sqlite3_bind_text(statement, 2, [[entry getDescription] UTF8String], -1, SQLITE_STATIC);
sqlite3_bind_text(statement, 3, [[entry phone] UTF8String], -1, SQLITE_STATIC);
sqlite3_bind_text(statement, 4, [[entry fax] UTF8String], -1, SQLITE_STATIC);
sqlite3_bind_text(statement, 5, [[entry email] UTF8String], -1, SQLITE_STATIC);
sqlite3_bind_text(statement, 6, [[entry website] UTF8String], -1, SQLITE_STATIC);
if(sqlite3_step(statement) != SQLITE_DONE){
NSLog(#">> Database: Failed to insert into Database");
NSLog(#"SQL Error Message: %s", sqlite3_errmsg(database));
}
sqlite3_finalize(statement);
}
#end
AppDelegate::application:didFinishWithLaunchingOptions
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
// create delegate for entry xml parsing
id delegate = [[KejithEntryXmlDelegate alloc] init];
KejithXmlParser *parser = [[KejithXmlParser alloc] initWithUrl:[[NSURL alloc] initWithString:entryXmlUrl]];
KejithDatabaseAccess *dbAccess = [[KejithDatabaseAccess alloc] init];
KejithEntryQueryDelegate *dbEntryDelegate = [[KejithEntryQueryDelegate alloc] init];
// set delegate to parse xml file
[parser setDelegate:delegate];
// set delegate to query data to/from database
[dbAccess setDelegate:dbEntryDelegate];
// get results of xml parsing
NSMutableArray *result = [parser parse];
NSLog(#"Count of ParseResult: %d", [result count]);
[dbAccess importWithDelegate:result];
NSLog(#"Count of DatabaseResult: %d", [[dbAccess queryWithDelegate] count]);
return YES;
}
Console-Output without [dbAccess importWithDelegate:result] commented out:
2013-12-08 15:59:44.035 staedteApp[30202:70b] Database: Connection was opened successfully
2013-12-08 15:59:44.048 staedteApp[30202:70b] Database: Connection was opened successfully
2013-12-08 15:59:44.049 staedteApp[30202:70b] Count of DatabaseResult: 0
Console-Output with [dbAccess importWithDelegate:result] commented out:
2013-12-08 16:17:18.084 staedteApp[30267:70b] Database: Connection was opened successfully
2013-12-08 16:17:18.091 staedteApp[30267:70b] Count of DatabaseResult: 50
EDIT #1 -----
Updated KejithEntryQueryDelegate::importEntry:into
-(void)importEntry:(KejithEntry *)entry into:(sqlite3 *)database
{
sql = "INSERT INTO entry (entry_id, entry_title, entry_description, entry_phone, entry_fax, entry_email, entry_website, enty_latitude, entry_longitude, entry_category_id) \
VALUES \
(0,?,?,?,?,?,?,0,0,0);";
int sqlResult = sqlite3_prepare_v2(database, sql, -1, &statement, NULL);
if(sqlResult != SQLITE_DONE){
sqlite3_bind_text(statement, 1, [[entry title] UTF8String], -1, SQLITE_STATIC);
sqlite3_bind_text(statement, 2, [[entry getDescription] UTF8String], -1, SQLITE_STATIC);
sqlite3_bind_text(statement, 3, [[entry phone] UTF8String], -1, SQLITE_STATIC);
sqlite3_bind_text(statement, 4, [[entry fax] UTF8String], -1, SQLITE_STATIC);
sqlite3_bind_text(statement, 5, [[entry email] UTF8String], -1, SQLITE_STATIC);
sqlite3_bind_text(statement, 6, [[entry website] UTF8String], -1, SQLITE_STATIC);
int sqlStepResult;
if((sqlStepResult = sqlite3_step(statement)) != SQLITE_DONE){
NSLog(#">> Database: Failed to insert into Database");
NSLog(#"SQL Error Message: %s", sqlite3_errmsg(database));
NSLog(#"SQL Step Result: %d", sqlStepResult);
}
} else {
NSLog(#"Database: Problem Occured in KejithEntryQueryDelegate.m step");
NSLog(#"Database: Result Code: %d", sqlResult);
NSLog(#"Database: SQL-Error: %s", sqlite3_errmsg(database));
}
sqlite3_finalize(statement);
}
The issue is that you're using an instance variable for sql, setting it to the SELECT statement when you create KejithEntryQueryDelegate, changing it to an INSERT statement in the importEntry:into: method, but when you call query:, even though the code clearly assumes it should be SELECT statement, the sql is still the INSERT statement.
By looking at the result code of sqlite3_step (point 3, below) one can quickly identify the issue. Since sqlResult != DONE, you want to log the issue and it reports "entry.entry_title may not be NULL" (which doesn't make sense in a SELECT statement, which made me realize that the old INSERT statement was still in the sql variable).
My original answer, based upon a glance at the code is below. Point #3 is the critical observation.
Just looking at the code, I don't see anything that would obviously cause the behavior you describe. If I follow you correctly, you're saying that if you do not import data, 50 records are found, but if you do attempt to import the data, not only do you not see new data, but suddenly nothing is found (including the records that were already there). Is that really what you're saying? That's curious behavior. If this is, in fact, the issue, that would lead me to suspect that the attempt to import is causing the subsequent attempt to read to fail.
The only obvious SQLite issue here is that importWithDelegate should not be calling sqlite3_finalize. I don't even see why KejithDatabaseAccess has a sqlite3_stmt, as you don't prepare any statements in that class. Perhaps calling sqlite3_finalize with some invalid sqlite3_stmt causes problems?
There are a few minor things here:
The importEntry:into: should presumably check the result of sqlite3_prepare_v2 statement. Elsewhere, you confirm that the prepare succeeded before proceeding, but not here.
The query method is storing the email address into the web site property.
I'd also save the result of sqlite3_step in the query method so that you could check for errors, e.g.:
while((sqlResult = sqlite3_step(statement)) == SQLITE_ROW) {
// do all of your updating of entries here
}
if (sqlResult != SQLITE_DONE) {
NSLog(#"Database: Problem Occured in KejithEntryQueryDelegate.m step");
NSLog(#"Database: Result Code: %d", sqlResult);
NSLog(#"Database: SQL-Error: %s", sqlite3_errmsg(database));
}
Right now, if your sqlite3_step method failed, you'd never know.

Program received signal "EXC_Bad_Access" NSMutableArray

if I try and reun the code below I get an EXE_bad_access message on [categoryList count]
NSMutableArray *categoryList = [[CategoryItem alloc] getAll];
NSLog(#"number of items is %#", [categoryList count]);
The class is below
#import "CategoryItem.h"
#import "SQLite.h"
#interface CategoryItem : NSObject {
NSInteger ID;
NSInteger SortOrder;
NSString *Name;
NSString *ShoppingImage;
}
#property (nonatomic, nonatomic) NSInteger SortOrder;
#property (nonatomic, retain) NSString * Name;
#property (nonatomic, retain) NSString * ShoppingImage;
#property (nonatomic, nonatomic) NSInteger ID;
- (id)initWithObject:(NSInteger)itemID;
-(NSMutableArray *)getAll;
#end
#implementation CategoryItem
#synthesize ShoppingImage;
#synthesize Name;
#synthesize ID;
#synthesize SortOrder;
- (id)initWithObject:(NSInteger)itemID {
if ((self = [super init])) {
sqlite3 *database;
// Open the database. The database was prepared outside the application.
if (sqlite3_open([[SQLite fullFilePath] UTF8String], &database) == SQLITE_OK) {
// Get the primary key for all books.
const char *sql = "SELECT ID, Name, ShoppingImage, SortOrder FROM CategoryItem WHERE ID =?";
sqlite3_stmt *statement;
// Preparing a statement compiles the SQL query into a byte-code program in the SQLite library.
// The third parameter is either the length of the SQL string or -1 to read up to the first null terminator.
if (sqlite3_prepare_v2(database, sql, -1, &statement, NULL) == SQLITE_OK) {
// We "step" through the results - once for each row.
sqlite3_bind_int(statement, 1, itemID);
while (sqlite3_step(statement) == SQLITE_ROW) {
// The second parameter indicates the column index into the result set.
self.ID = itemID;
self.Name = [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 1)];
self.ShoppingImage = [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 2)];
self.SortOrder = sqlite3_column_int(statement, 3);
}
}
// "Finalize" the statement - releases the resources associated with the statement.
sqlite3_finalize(statement);
} else {
// Even though the open failed, call close to properly clean up resources.
sqlite3_close(database);
NSLog(#"Failed to open database with message '%s'.", sqlite3_errmsg(database));
// Additional error handling, as appropriate...
}
}
return self;
}
-(NSMutableArray*)getAll{
NSMutableArray *listArray = [[[NSMutableArray alloc] init] autorelease];
sqlite3 *database;
// Open the database. The database was prepared outside the application.
if (sqlite3_open([[SQLite fullFilePath] UTF8String], &database) == SQLITE_OK) {
// Get the primary key for all books.
const char *sql = "SELECT ID, Name, ShoppingImage, SortOrder FROM CategoryItem ORDER BY SortOrder";
sqlite3_stmt *statement;
// Preparing a statement compiles the SQL query into a byte-code program in the SQLite library.
// The third parameter is either the length of the SQL string or -1 to read up to the first null terminator.
if (sqlite3_prepare_v2(database, sql, -1, &statement, NULL) == SQLITE_OK)
{
// We "step" through the results - once for each row.
while (sqlite3_step(statement) == SQLITE_ROW)
{
// The second parameter indicates the column index into the result set.
CategoryItem *categoryItem = [[CategoryItem alloc] init];
categoryItem.ID = sqlite3_column_int(statement, 0);
categoryItem.Name = [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 1)];
categoryItem.ShoppingImage = [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 2)];
categoryItem.SortOrder = sqlite3_column_int(statement, 3);
[listArray addObject:categoryItem];
[categoryItem release];
categoryItem = nil;
}
}else{
printf( "could not prepare statemnt: %s\n", sqlite3_errmsg(database) );
}
// "Finalize" the statement - releases the resources associated with the statement.
sqlite3_finalize(statement);
} else {
// Even though the open failed, call close to properly clean up resources.
sqlite3_close(database);
NSLog(#"Failed to open database with message '%s'.", sqlite3_errmsg(database));
// Additional error handling, as appropriate...
}
//NSLog(#"this is the list array count %#", [listArray count]);
return listArray;
}
- (void)dealloc {
[super dealloc];
[Name release];
[ShoppingImage release];
}
#end
It doesn't seem right the way you create your CategoryItem. You are calling allocbut not any init... method. You may want to use the initWithObject method that you have provided in your implementation.
From Apple docs:
It takes two steps to create an object
using Objective-C. You must:
Dynamically allocate memory for the
new object
Initialize the newly
allocated memory to appropriate values
An object isn’t fully functional until
both steps have been completed. Each
step is accomplished by a separate
method but typically in a single line
of code:
id anObject = [[Rectangle alloc]
init];
EDIT:
Beyond the initialization problem, there seems to be a conceptual problem (pointed out by #Terry Wilcox):
Calling the method getAllon an instance does not seem to make sense and therefore should be defined as a class method instead:
+ (NSMutableArray*)getAll;
and should be called like this:
NSMutableArray *categoryList = [CategoryItem getAll];
EDIT 2:
Your log statement does not seem right either. [categoryList count]returns a NSUIntegerand you are trying to print an object with %#. Use %iinstead:
NSLog(#"number of items is %i", [categoryList count]);
This code:
NSMutableArray *categoryList = [[CategoryItem alloc] getAll];
doesn't make sense. If getAll is a class method on CategoryItem, then it should be defined as
+ (NSMutableArray*)getAll;
and you should call it as
NSMutableArray *categoryList = [CategoryItem getAll];
Then categoryList will be an array that you don't own, so you may want to retain it when you get it.

how to retrieve data from SQLite using iphone sdk?

i have a simple sqllite database with 2 columns and multiple rows. e.g.
Code1 1000
Code2 2000
Code3 3000
Code4 4000
Code5 5000
I want to add all the fields together e.g. code1,code2,code3,code4,code5 and return the total between them to a label in my interface builder. How could i do this using the iphone sdk?are there any tutorials out there? thanks for any help on this.
You'll find a great tutorial here which will cover both the UI and the database part: http://www.techotopia.com/index.php/An_Example_SQLite_based_iOS_4_iPhone_Application
In summary, it would be something like this:
In databaseViewController.h,
#import <UIKit/UIKit.h>
#import "/usr/include/sqlite3.h"
#interface databaseViewController : UIViewController {
UILabel *total;
NSString *databasePath;
sqlite3 *db;
}
#property (retain, nonatomic) IBOutlet UILabel *total;
- (IBAction) getTotal;
#end
In databaseViewController.m,
#import "databaseViewController.h"
#implementation databaseViewController
#synthesize total;
-(void) getTotal
{
sqlite3_stmt *statement;
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &db) == SQLITE_OK)
{
NSString *totalSQL = [NSString initWithUTF8String: #"SELECT SUM(field2) FROM MyTable"];
const char *total_stmt = [totalSQL UTF8String];
sqlite3_prepare_v2(db, total_stmt, -1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_ROW)
{
NSString *totalField = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 0)];
total.text = totalField;
}
sqlite3_finalize(statement);
sqlite3_close(contactDB);
}
}
.
.
.
- (void)viewDidUnload {
self.total = nil;
}
- (void)dealloc {
[total release];
[super dealloc];
}
#end
Something like that... then you just call getTotal in viewDidLoad (or whenever you press a button).

Loading data from database into detailed view

I'm reading data from a sqlite database however in my detailed view one of the data items is not showing correctly. It show what looks like random memory i.e. UIDeviceRGB...(I have two strings, one that works one that doesn't). I can't work out why but when I run the debug it returns null.
Here is my code in HydratedDetailData:
if (SQLITE_DONE != sqlite3_step(detailStmt)) {
double add = sqlite3_column_double(detailStmt, 2);
NSString *address = [NSString stringWithFormat:#"%#", add];
self.ClubAddress = address;
[address release];
}
Any help work be greatly appreciated!
code from Clubs.m
#import "Clubs.h"
static sqlite3 *database = nil;
static sqlite3_stmt *detailStmt = nil;
#implementation Clubs
#synthesize clubID, clubName, ClubAddress, isDirty, isDetailViewHydrated;
+(void) getInitialDataToDisplay:(NSString *)dbPath {
SQLAppDelegate *appDelegate = (SQLAppDelegate *) [[UIApplication sharedApplication] delegate];
if (sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK) {
const char *sql = "select clubID, clubName from clubNames";
sqlite3_stmt *selectstmt;
if (sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL) == SQLITE_OK) {
while (sqlite3_step(selectstmt)== SQLITE_ROW) {
NSInteger primaryKey = sqlite3_column_int(selectstmt, 0);
Clubs *clubObj = [[Clubs alloc] initWithPrimaryKey:primaryKey];
clubObj.clubName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 1)];
clubObj.isDirty = NO;
[appDelegate.clubArray addObject:clubObj];
[clubObj release];
}
}
}
else
sqlite3_close(database);
}
+(void) finalizeStatements {
if (database) sqlite3_close(database);
}
-(id) initWithPrimaryKey:(NSInteger) pk {
[super init];
clubID = pk;
isDetailViewHydrated = NO;
return self;
}
-(void) hydrateDetailViewData {
if (isDetailViewHydrated) return;
if (detailStmt == nil) {
const char *sql = "Select ClubAddress from clubNames Where clubID = ?";
if (sqlite3_prepare_v2(database, sql, -1, &detailStmt, NULL) !=SQLITE_OK)
NSAssert1(0, #"Error while creating detail view statment. '%s'", sqlite3_errmsg(database));
}
sqlite3_bind_int(detailStmt, 1, clubID);
if (SQLITE_DONE != sqlite3_step(detailStmt)) {
double add = sqlite3_column_double(detailStmt, 0);
NSString *address = [NSString stringWithFormat:#"%d", add];
self.ClubAddress = address;
}
else
NSAssert1(0, #"Error while getting the address of club. '%s'", sqlite3_errmsg(database));
sqlite3_reset(detailStmt);
isDetailViewHydrated = YES;
}
-(void) dealloc {
[ClubAddress release];
[clubName release];
[super dealloc];
}
#end
i had such a problem for reading double values, some of values read right but some read as 0 ! i have tried many things but at last my problem was solved by defining variables globally. i have defined the locally in .m file but the solution was to define them in .h file.i hope it can solve yours too.
good luck
Perhaps if you used the %d formatter in your [NSString stringWithFormat:#"%#", add]; call.
(%# is generally for strings, %d is for doubles)
After our little discussion-athon, this should fix what ails you.
if (SQLITE_DONE != sqlite3_step(detailStmt)) {
char *db_text = sqlite3_column_text(detailStmt, 2);
NSString *address = [NSString stringWithUTF8String: db_text];
self.ClubAddress = address;
}
This will pull the text value from the database and convert it into an NSString*. (hopefully)....

iphone memory leak with uitableview and sqlite

I am having a problem with what I believe is a memory leak which after some time is causing my app to slow down. I have a sectioned uitableview that has sections of 'movie directors' with rows of thier movies in their particular section. To do this I am calling a data object (and passing it the section header) to return that section's data and populate the section rows. So I am calling that object a few times on the same view(numberOfRowsInSection, cellForRowAtIndexPath, and didSelectRowAtIndexPath) this happens for each section. Looking at Instruments, I believe the leak is coming from getDirectorsMovies:theDirector from Movies.m. Can anyone tell me what I am doing that is causing this leak. Any help would be greatly appreciated, I've been working on this for a few weeks. Below is some code to show what I am doing.
Thanks in advance!!!
//Movies.h
#import <Foundation/Foundation.h>
#import <sqlite3.h>
#import "Movie.h"
#interface Movies : NSObject {
}
- (NSMutableArray *) getDirectorsMovies:(NSString *)theDirector;
#end
//Movies.m //getDirectorsMovies:(NSString *)theDirector goes to the database, gets the directors movies, and returns them in an array
#import "Movies.h"
#implementation Movies
- (NSMutableArray *) getDirectorsMovies:(NSString *)theDirector
{
sqlite3 *database;
NSString *databaseName = #"Movies.sql";
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
NSString *databasePath = [documentsDir stringByAppendingPathComponent:databaseName];
NSMutableArray *theDirectorsMovies = [[NSMutableArray alloc] init];
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
const char *sqlStatement = "select * from movies where lastname = ? order by lastname, movie";
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
sqlite3_bind_text(compiledStatement, 1, [theDirector UTF8String], -1, SQLITE_TRANSIENT);
while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
NSString *aLastName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 1)];
NSString *aDirector = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 2)];
NSString *aMovie = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 3)];
Movie *movie = [[Movie alloc] initWithName:aMovie lastname:aLastName director:aDirector];
[theDirectorsMovies addObject:movie];
[movie release];
}
}
sqlite3_finalize(compiledStatement);
}
sqlite3_close(database);
return theDirectorsMovies;
[theDirectorsMovies release];
}
#end
//Calling getDirectorsMovies:(NSString *)theDirector
MoviesAppDelegate *appDelegate = (MoviesAppDelegate *)[[UIApplication sharedApplication] delegate];
Director *director = (Director *)[appDelegate.director objectAtIndex:indexPath.section];//appDelegate.director IS A MSMutableArray defined in the AppDelegate
self.theMovies = nil;//THIS IS A MSMutableArray defined in the AppDelegate
Movies *directorMovies = [[Movies alloc] init];
self.theMovies = [directorMovies getDirectorMovies:director.lastname];
[directorMovies release];
Movie *movie = (Movie *)[theMovies objectAtIndex:indexPath.row];
//do whatever with the data
[movie release];
You have this:
return theDirectorsMovies;
[theDirectorsMovies release];
Nothing happens after the return statement, so your call to release will never happen. It was for this very reason that AutoreleasePools were invented (and patented). Simply do:
return [theDirectorsMovies autorelease];
And your memory leak will go away.
There are a number of potential issues here it would be useful to see the init method for Movie as that may be where the issue is. Also you should have an autorelease on the NSMutableArray.
In my sqlite code I have the following statement normally before the sqlite3_finalize call
sqlite3_clear_bindings(compiledStatement);
That call cleared up a lot of issues for my code.