Hello I am new in sqlite database, I want to show data which I have stored in database, in second view controller by clicking (show data button) in tableview.
Below is my code for database
file DBManager.h
#interface DBManager : NSObject
{
NSString *databasePath;
}
+(DBManager*)getSharedInstance;
-(BOOL)createDB;
-(BOOL) saveData:(NSString*)registerNumber name:(NSString*)name
department:(NSString*)department year:(NSString*)year;
-(NSArray*) findByRegisterNumber:(NSString*)registerNumber;
#end
file DBManager.m
static DBManager *sharedInstance = nil;
static sqlite3 *database = nil;
static sqlite3_stmt *statement = nil;
#implementation DBManager
+(DBManager *)getSharedInstance
{
if (!sharedInstance) {
sharedInstance = [[super allocWithZone:NULL]init];
[sharedInstance createDB];
}
return sharedInstance;
}
-(BOOL)createDB
{
NSString *docsDir;
NSArray *dirPaths;
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = dirPaths[0];
NSLog(#"%#", docsDir);
databasePath = [[NSString alloc]initWithString:[docsDir stringByAppendingPathComponent:#"student.db"]];
BOOL isSuccess = YES;
NSFileManager *filemngr = [NSFileManager defaultManager];
if ([filemngr fileExistsAtPath:databasePath] == NO)
{
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
char *errMsg;
const char * sql_stmt = "create table if not exists studentsDetail (regno integer primary key, name text, department text, year text)";
if (sqlite3_exec(database, sql_stmt, NULL, NULL, &errMsg)!= SQLITE_OK)
{
isSuccess = NO;
NSLog(#"Failed to create table");
}
sqlite3_close(database);
return isSuccess;
}
else
{
isSuccess = NO;
NSLog(#"Failed to open/create database");
}
}
return isSuccess;
}
-(BOOL)saveData:(NSString *)registerNumber name:(NSString *)name department:(NSString *)department year:(NSString *)year;
{
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
NSString *insertSQL = [NSString stringWithFormat:#"insert into studentsDetail (regno,name,department,year) values (\"%ld\",\"%#\",\"%#\",\"%#\")",(long)[registerNumber integerValue],name,department,year];
const char *insert_stmt = [insertSQL UTF8String];
sqlite3_prepare_v2(database, insert_stmt,-1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_DONE)
{
return YES;
}
else
{
return NO;
}
//sqlite3_reset(statement);
}
return NO;
}
- (NSArray*) findByRegisterNumber:(NSString*)registerNumber
{
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
NSString *querySQL = [NSString stringWithFormat:#"select name,department,year from studentsDetail where regno=\"%#\"",registerNumber];
const char *query_stmt = [querySQL UTF8String];
NSMutableArray *resultArray = [[NSMutableArray alloc]init];
if (sqlite3_prepare_v2(database,
query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_step(statement) == SQLITE_ROW)
{
NSString *name = [[NSString alloc] initWithUTF8String:
(const char *) sqlite3_column_text(statement, 0)];
[resultArray addObject:name];
NSString *department = [[NSString alloc] initWithUTF8String:
(const char *) sqlite3_column_text(statement, 1)];
[resultArray addObject:department];
NSString *year = [[NSString alloc]initWithUTF8String:
(const char *) sqlite3_column_text(statement, 2)];
[resultArray addObject:year];
NSLog(#"%#", resultArray);
return resultArray;
}
else{
NSLog(#"Not found");
return nil;
}
//sqlite3_reset(statement);
}
}
return nil;
}
#end
Please help me..
Updated Code:
DBManager.m
-(NSArray *) showdata{
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
NSString *querySQL = [NSString stringWithFormat: #"SELECT * FROM studentsDetail"];
const char *query_stmt = [querySQL UTF8String];
NSMutableArray *resultentArray=[[NSMutableArray alloc]init];
if (sqlite3_prepare_v2(database,
query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
while(sqlite3_step(statement) == SQLITE_ROW)
{
NSMutableDictionary *resultentDict = [[NSMutableDictionary alloc] init];
NSString *name = [[NSString alloc] initWithUTF8String:
(const char *) sqlite3_column_text(statement, 0)];
NSString * department = [[NSString alloc] initWithUTF8String:
(const char *) sqlite3_column_text(statement, 1)];
NSString *year = [[NSString alloc] initWithUTF8String:
(const char *) sqlite3_column_text(statement, 2)];
NSLog(#"%#",resultentDict);
[resultentDict setValue:name forKey:#"name"];
[resultentDict setValue:department forKey:#"department"];
[resultentDict setValue:year forKey:#"year"];
NSLog(#"%#",resultentDict);
NSLog(#"%#",resultentArray);
[resultentArray addObject:resultentDict];
NSLog(#"%#",resultentArray);
}
return resultentArray;
}
sqlite3_close(database);
}
return nil;
}
after that I created one button called show data ... if I click that it will navigate to another TableViewController:
I implemented like this :
in TableViewController:
- (void)viewDidLoad {
[self showData];
}
-(void)showData{
data = [[DBManager getSharedInstance]showdata];
NSLog(#"DATA %#",data);
NSLog(#"%lu",(unsigned long)[[data valueForKey:#"price"] count]);
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [[data valueForKey:#"price"] count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *simpleTableIdentifier = #"SimpleTableItem";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
NSLog(#"%#",data);
// cell.textLabel.text = [[data valueForKey:#"year"]objectForKey:indexPath.row];
cell.textLabel.text=[[data valueForKey:#"price"]objectAtIndex:indexPath.row];
return cell;
}
Related
I must be doing something wrong here. My SQLite database is working. However, I cannot seem to populate the tname into a picker view while the picked populates three text fields tname, latitude, and longitude.
Info: Two picker views that are independent from each other, they both read the same sqlite db.
#import "ViewController.h"
#interface ViewController ()
{
NSMutableArray *array1;
sqlite3 *towerDB;
NSString *dbPathString;
}
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//UIPickerView *pickerview1;
//array1 = [[NSMutableArray alloc]init];
[[self pickerview1]setDelegate:self];
[[self pickerview1]setDataSource:self];
[self displayTower];
}
- (void)displayTower
{
array1 = [[NSMutableArray alloc] init];
sqlite3_stmt *statement;
if (sqlite3_open([dbPathString UTF8String], &towerDB)==SQLITE_OK) {
[array1 removeAllObjects];
NSString *querySql = [NSString stringWithFormat:#"SELECT * FROM TOWERS"];
const char* query_sql = [querySql UTF8String];
// sqlite3_clear_bindings(statement);
// sqlite3_reset(statement);
if (sqlite3_prepare(towerDB, query_sql, -1, &statement, NULL)==SQLITE_OK) // NOT OK
//This Code works in a TableView!!
//Will NOT work in a PickerView
{
while (sqlite3_step(statement)==SQLITE_ROW)
{
NSString *tname = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(statement, 1)];
NSString *latitude = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(statement, 2)];
NSString *longitude = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(statement, 3)];
// NSString *ds2 = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(statement, 4)];
NSString *PickerTower = [[NSString alloc] initWithFormat:#"%#", tname];
NSString *lat1 = [[NSString alloc] initWithFormat:#"%#", latitude];
NSString *long1 = [[NSString alloc] initWithFormat:#"%#", longitude];
NSArray *array = [[NSArray alloc] initWithObjects:PickerTower, nil];
[array1 addObject:array];
NSLog(#"Lat/Long %# / %#", lat1, long1);
}
}
}
}
#pragma mark Picker Data Source Methods
-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
//ONE Colume
return 1;
}
-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
//data view how many items?
return [array1 count];
// return [_array2 count];
}
#pragma mark Picker Delegate Methods
-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
return [array1 objectAtIndex:row];
//return [self->array1 objectAtIndex:row];
// array1 = [[NSMutableArray alloc] init];
}
-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
long select = row;
NSLog(#"PickerView %ld", select);
}
#end
You have to changed this code in the method name displayTower and code lines -
[array1 addObject:array];
NSLog(#"Lat/Long %# / %#", lat1, long1);
with -
[array1 addObject:array];
NSLog(#"Lat/Long %# / %#", lat1, long1);
[[self pickerview1] reloadAllComponents];
may be it will help you, or feel free.
This is my code for my test app where I want to show users on the next view controller but when I run and try to retrieve the values it is giving me repeated values. I have used NSMutableDictionary and NSMutableArray.
#import "DBManager.h"
static DBManager *sharedInstance = nil;
static sqlite3 *database = nil;
static sqlite3_stmt *statement = nil;
#implementation DBManager
-(void) getsaveData:(NSString *)Username
{
const char *dbpath = [newFileAtPath UTF8String];
NSMutableArray *userArray = [[NSMutableArray alloc]init];
if (sqlite3_open(dbpath, &database)==SQLITE_OK) {
NSMutableDictionary *userInfo = [[NSMutableDictionary alloc] init];
NSString *getSQL = [NSString stringWithFormat:#"SELECT * FROM USERS WHERE USERNAME != \"%#\"",Username];
const char *retrievestmt = [getSQL UTF8String];
if(sqlite3_prepare_v2(database, retrievestmt, -1, &statement, NULL)==SQLITE_OK)
{
while(sqlite3_step(statement)==SQLITE_ROW)//in this while loop i am getting repeated values
{
NSString *User_ID = [[NSString alloc] initWithUTF8String: (const char *) sqlite3_column_text(statement, 0)];
[userInfo setObject:User_ID forKey:#"ID"];
//[userArray addObject:User_ID];
NSString *User_Email = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 1)];
[userInfo setObject:User_Email forKey:#"Email"];
//[userArray addObject:User_Email];
NSString *Password = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 2)];
[userInfo setObject:Password forKey:#"Email"];
//[userArray addObject:Password];
NSString *User_name = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 3)];
[userInfo setObject:User_name forKey:#"Username"];
//[userArray addObject:User_name];
NSString *User_Avatar = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 4)];
[userInfo setObject:User_Avatar forKey:#"Avatar"];
//[userArray addObject:User_Avatar];
[userArray addObject:userInfo];
NSLog(#"userArray %#",userArray);
}
sqlite3_reset(statement);
}
}
}
#end
In the while loop I am geeting the error.
I tried multiple times with multiple solutions please help me fix this.
The problem is simple - you are incorrectly reusing the userInfo dictionary. You need to create a new instance in each loop iteration.
Move the line:
NSMutableDictionary *userInfo = [[NSMutableDictionary alloc] init];
to just after the while loop line.
You also have many other issues with your code:
You never close the database.
You never finalize the prepared statement.
You needlessly reset the prepared statement.
You have insufficient error checking/logging.
You are not using standard naming conventions.
You are not using standard whitespacing which makes your code harder to read.
You don't use consistent curly brace placement. Pick a style and use it everywhere.
You are using static variables when you should not be.
Never build SQL statements using stringWithFormat:. Properly bind values to the query.
Never use SELECT * in a query. Explicitly list out the columns to ensure you get consistent and expected column values.
Here's is your code updated for these issues:
#import "DBManager.h"
static DBManager *sharedInstance = nil;
#implementation DBManager
- (void)getsaveData:(NSString *)username {
const char *dbpath = [newFileAtPath UTF8String];
NSMutableArray *userArray = [[NSMutableArray alloc] init];
sqlite3 *database;
if (sqlite3_open(dbpath, &database) == SQLITE_OK) {
const char *retrievestmt = "SELECT USER_ID, USER_EMAIL, PASSWORD, USER_NAME, USER_AVATAR FROM USERS WHERE USERNAME != ?"; // replace * with actual column names
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(database, retrievestmt, -1, &statement, NULL) == SQLITE_OK) {
sqlite3_bind_text(statement, 1, [username UTF8String], -1, SQLITE_TRANSIENT);
while (sqlite3_step(statement) == SQLITE_ROW) {
NSMutableDictionary *userInfo = [[NSMutableDictionary alloc] init];
NSString *userID = [[NSString alloc] initWithUTF8String:(const char *)sqlite3_column_text(statement, 0)];
userInfo[#"ID"] = userID;
NSString *userEmail = [[NSString alloc] initWithUTF8String:(const char *)sqlite3_column_text(statement, 1)];
userInfo[#"Email"] = userEmail;
NSString *password = [[NSString alloc] initWithUTF8String:(const char *)sqlite3_column_text(statement, 2)];
userInfo[#"Password"] = password;
NSString *username = [[NSString alloc] initWithUTF8String:(const char *)sqlite3_column_text(statement, 3)];
userInfo[#"Username"] = username;
NSString *userAvatar = [[NSString alloc] initWithUTF8String:(const char *)sqlite3_column_text(statement, 4)];
userInfo[#"Avatar"] = userAvatar;
[userArray addObject:userInfo];
}
sqlite3_finalize(statement);
NSLog(#"userArray %#",userArray);
} else {
NSLog(#"Unable to prepare the statement at %s: %s", retrievestmt, sqlite3_errmsg(database));
}
sqlite3_close(database);
} else {
NSLog(#"Unable to open the database at %#: %s", dbpath, sqlite3_errmsg(database));
}
}
#end
I'm saving an image in the document directory and then I save its path inside a SQLite DB. After the process finishes I try to retrieve the image path from the db but I can't get it working and I really have no Idea why. On the simulator the code works but on a real device it doesn't.
This is the code I've used to save the img path and to retrieve the img path and display the image inside an UIImageView
This is the code to save the image:
NSString *stringURL = #"http://addons.cdn.mozilla.net/user-media/addon_icons/80/80205-64.png?modified=1317416463";
NSURL *url = [NSURL URLWithString:stringURL];
NSData *urlData = [NSData dataWithContentsOfURL:url];
NSString *filePath;
if ( urlData )
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
filePath = [NSString stringWithFormat:#"%#/%#", documentsDirectory,#"test.png"];
[urlData writeToFile:filePath atomically:YES];
}
NSLog(#"path:%#",filePath);
[self saveImgPath:filePath];
This is the saveImgPath method:
-(void) saveImgPath:(NSString*)path{
sqlite3_stmt *statement;
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &ImgDB) == SQLITE_OK)
{
NSString *insertSQL = [NSString stringWithFormat: #"INSERT INTO ImgPath (path) VALUES (\"%#\")",path];
const char *insert_stmt = [insertSQL UTF8String];
if(sqlite3_prepare_v2(ImgDB, insert_stmt, -1, &statement, NULL) == SQLITE_OK)
{
sqlite3_step(statement);
}
sqlite3_finalize(statement);
sqlite3_close(ImgDB);
}
[self performSegueWithIdentifier:#"sfondo" sender:self];
}
And this is how I retrieve it:
-(NSString*)getImgPath{
NSString* imgPath;
const char *dbpath = [[self GetDatabasePath] UTF8String];
sqlite3_stmt *statement;
if (sqlite3_open(dbpath, &ImgDB) == SQLITE_OK)
{
NSString *checkSQL = [NSString stringWithFormat: #"SELECT * FROM ImgPath"];
const char *insert_stmt = [checkSQL UTF8String];
sqlite3_prepare_v2(ImgDB, insert_stmt, -1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_ERROR)
NSAssert1(0,#"Errore %s",sqlite3_errmsg(ImgDB));
else
sqlite3_step(statement);
sqlite3_finalize(statement);
sqlite3_close(ImgDB);
}
return imgPath;
}
The DB is initialized correctly and the NSLog of the paths are correct but I get 0 results when I try to retrieve the image path
the first view is word list view controller and it has a word table containing word_id,word meaning and sentence and this data i need to pass on the other view having 1 text field which i add to display the word and two text views to display meaning and sentence.
Here is the code-
- (void)getListData
{
//tableData = [[NSMutableArray alloc]init];
sqlite3_stmt *statement;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"dexternotedb.sqlite"];
if (sqlite3_open([path UTF8String], &database) == SQLITE_OK) {
WordListViewController *temp = APP_DELEGATE.wordListViewController;
NSLog(#"word id %ld",(long)[temp.wordId integerValue]);
NSString *sql=[NSString stringWithFormat:#"SELECT word_id, word ,meaning,sentence FROM words WHERE word_id=\"%#\"",APP_DELEGATE.wordListViewController.wordId];
const char *read_stmt = [sql UTF8String];
NSLog(#"select query%#",sql);
if(sqlite3_prepare_v2(database, read_stmt, -1, &statement, NULL) == SQLITE_OK){
//sqlite3_bind_int(statement, 1, [temp.wordId integerValue]);
while(sqlite3_step(statement) == SQLITE_ROW) {
NSString *word1 = [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 1)];
word.text = word1;
NSString *meaning1 = [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 2)];
meaning.text = meaning1;
NSString *sentence1 = [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 3)];
Sentence.text = sentence1;
}
sqlite3_finalize(statement);
} else
{
sqlite3_close(database);
NSAssert1(0, #"Failed to open database with message '%s'.", sqlite3_errmsg(database));
}
}
Simply Store Value in NSUserDefaults
[[NSUserDefaults standardUserDefaults] setObject:#"String" forKey:#"KeyName"];
[[NSUserDefaults standardUserDefaults] synchronize];
and whenever data is required fetch data from NSUserDefaults in entire app
NSString *str= [[NSUserDefaults standardUserDefaults] valueForKey:#"KeyName"];
I'm trying to add new row to TableView with edit mode. Used this tutorial. But after dismissing my edit mode view my table view is not reloaded. My addItem: method
- (IBAction)addItem:(id)sender {
BIDAppDelegate *appDelegate = (BIDAppDelegate *)[[UIApplication sharedApplication] delegate];
sqlite3 *database;
NSString *databaseName;
NSString *databasePath;
databaseName = #"TestProjectDatabase.sqlite";
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
databasePath = [documentsDir stringByAppendingPathComponent:databaseName];
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL success = [fileManager fileExistsAtPath:databasePath];
if(!success) {
databasePath = [[NSBundle mainBundle] pathForResource:databaseName ofType:nil];
}
if (sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK)
{
NSString *insertSQL = [NSString stringWithFormat:#"insert into \"MyItems\" ( \"MyItemName\", \"MyItemDescription\") values ( '%#', '%#');", _nameTextField.text, _descriptionTextField.text];
const char *insert_stmt = [insertSQL UTF8String];
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(database, insert_stmt, -1, &compiledStatement, NULL) != SQLITE_OK)
{
NSAssert1(0, #"Error while creating add statement. '%s'", sqlite3_errmsg(database));
}else{
if (sqlite3_step(compiledStatement) == SQLITE_DONE)
{
// NSLog(#"All ok");
} else {
// NSLog(#"FAIL");
}
}
sqlite3_finalize(compiledStatement);
}
sqlite3_close(database);
MyItems *itemsToDatabase = [[MyItems alloc] initWithItemName:_nameTextField.text andItemDescription:_descriptionTextField.text];
[appDelegate.myItems addObject:itemsToDatabase];
[self dismissModalViewControllerAnimated:YES];
}
SQL insertion is OK because where is new row after restarting my project. Any suggestions how to fix it?
Assuming the table data source reads from appDelegate.myItems, you just need to reload the table itself [tableView reloadData];.