Tableview app delete from sqlite database - ios

I have a tableview app where I am trying to delete data stored in a sqilte browser. When I delete the data in the simulator, the data does not reappear after closing and re-running the simulator. However, when I open the database where the original data was kept using sqlite browser, the deleted data still appears in the sqlite browser. Can someone advise on what I'm missing?
#import "DataAccess.h"
#import "sqlite3.h"
#import "Product.h"
#import "Company.h"
#implementation DataAccess
NSString *dbPathString;
sqlite3 *companyDB;
sqlite3 *productDB;
-(void) setCompanyListFromDB
{
NSLog(#"setCompanyListFromDB");
dbPathString = #"/Users/user/Desktop/telecom.db";
self.companyList = [self readCompanyDataFromDB];
NSLog(#"read all company data");
}
-(void) deleteCompany:(Company *)company andDeleteProduct:(NSIndexPath*)indexPath{
//pass the company from the tableview, then pass the row from the tablewview
Product *product = [company.products objectAtIndex:indexPath.row];
[self deleteProductFromDB:product.name];
[company.products removeObjectAtIndex:indexPath.row];
}
-(NSMutableArray*)readCompanyDataFromDB //returning companyList bc we want to use this for displaying in tableview
{
NSLog(#"readDataFromDB");
NSMutableArray *companyList = [[NSMutableArray alloc]init];
sqlite3_stmt *statement ;
if (sqlite3_open([dbPathString UTF8String], &companyDB)==SQLITE_OK) { //when we do this process for products, we can skip opening companyDB bc it is already open - just do it once
NSLog(#"sqlite3_open");
// Reading Companies ....................................Start
NSLog(#"Reading Companies");
NSString *querySQL = [NSString stringWithFormat:#"SELECT * FROM company"];
NSLog(#"Company SQL: %#", querySQL);
const char *query_sql = [querySQL UTF8String]; //converting to type of string C understands
if (sqlite3_prepare(companyDB, query_sql, -1, &statement, NULL) == SQLITE_OK)
{
NSLog(#"sqlite3_prepare");
while (sqlite3_step(statement)== SQLITE_ROW) //while stepping through database, if it returns a row it should keep going, cuts out if it returns something other than SQLITE_ROW
{
// 1|Apple|AAPL|593.1|apple.jpeg
NSString *companyID = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(statement, 0)];
NSString *name = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(statement, 1)];
NSString *stockSymbol = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(statement, 2)];
NSString *stockPrice = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(statement, 3)];
NSString *logo = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(statement, 4)];
//Company *company = [Company initWithName:name logo:logo symbol:stockSymbol price:stockPrice];
Company *company = [[Company alloc]init];
company.companyID = companyID;
company.name = name;
company.logo = logo;
company.stockSymbol = stockSymbol;
company.stockPrice = stockPrice;
[company print];
[companyList addObject:company];
}
}
// Reading Companies ....................................Done
// Reading Products for each Company ....................................Start
sqlite3_close(companyDB);
}
for(Company *company in companyList){
NSMutableArray *productList = [self readProductDataFromDBForCompanyID:company.companyID ];
company.products = productList;
}
return companyList;
}
-(NSMutableArray*) readProductDataFromDBForCompanyID:(NSString*)companyId {
NSLog(#"readProductDataFromDB");
NSMutableArray *productList = [[NSMutableArray alloc]init];
sqlite3_stmt *statement ;
if (sqlite3_open([dbPathString UTF8String], &companyDB)==SQLITE_OK) { //when we do this process for products, we can skip opening companyDB bc it is already open - just do it once
NSLog(#"sqlite3_open");
// Reading Products ....................................Start
NSLog(#"Reading Products");
NSString *querySQL = [NSString stringWithFormat:#"select * from product where productid = %#", companyId];
NSLog(#"Product SQL: %#", querySQL);
const char *query_sql = [querySQL UTF8String]; //converting to type of string C understands
if (sqlite3_prepare(companyDB, query_sql, -1, &statement, NULL) == SQLITE_OK)
{
NSLog(#"sqlite3_prepare");
while (sqlite3_step(statement)== SQLITE_ROW) //while stepping through database, if it returns a row it should keep going, cuts out if it returns something other than SQLITE_ROW
{
NSString *name = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(statement, 0)];
NSString *website = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(statement, 2)];
NSString *productID = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(statement, 3)];
Product *product = [[Product alloc]init];
product.productID = productID;
product.name = name;
product.website = website;
[product print];
[productList addObject:product];
}
}
// Reading Products ....................................Done
sqlite3_close(companyDB);
}
// insert into product values('iPad','0','http://www.apple.com/ipad/',1);
return productList;
}
-(void) deleteProductFromDB:(NSString*)productname{
if (sqlite3_open([dbPathString UTF8String], &companyDB)==SQLITE_OK) { //when we do this process for products, we can skip opening companyDB bc it is already open - just do it once
NSLog(#"sqlite3_open");
NSString *querySQL = [NSString stringWithFormat:#"delete from product where productname = '%#'", productname];
NSLog(#"Product Delete SQL: %#", querySQL);
const char *deleteQuery = [querySQL UTF8String]; //converting to type of string C understands
if (sqlite3_exec(companyDB, deleteQuery, NULL, NULL, nil)==SQLITE_OK)
{
NSLog(#"Product Deleted");
}
sqlite3_close(companyDB);
}
}
#end

As it was mentioned in the comments - when your app will run in iOS it will be sandboxed. Moreover, if you will include sqlite database as a resource file with your application - it will get into /Resources folder inside your application folder. And everything in that folder is not writable.
So if you need a database that you want to read/write you need to put it under /Documents folder inside your application folder.

Related

inserting multiple tables data in sqlite database

I have created multiple tables in my database. And now I want insert data into those tables. How to insert multiple tables data can anyone help regarding this.
I have written this code for creating 1 table:
NSString *insertSQL = [NSString stringWithFormat: #"INSERT INTO ATRG (id, name, language,imgurl) VALUES ( \"%#\",\"%#\",\"%#\",\"%#\")", ID, name, lang,imgUrl];
const char *insert_stmt = [insertSQL UTF8String]; sqlite3_prepare_v2(_globalDataBase, insert_stmt, -1, &statement, NULL); if (sqlite3_step(statement) == SQLITE_DONE)
{
NSLog(#"Record Inserted");
} else { NSLog(#"Failed to Insert Record");
}
Try this I hope it would be helpful!! This is mine code for insert data
#import "Sqlitedatabase.h"
#implementation Sqlitedatabase
+(NSString* )getDatabasePath
{
NSString *docsDir;
NSArray *dirPaths;
sqlite3 *DB;
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = dirPaths[0];
NSString *databasePath = [docsDir stringByAppendingPathComponent:#"myUser.db"];
NSFileManager *filemgr = [[NSFileManager alloc]init];
if ([filemgr fileExistsAtPath:databasePath]==NO) {
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath,&DB)==SQLITE_OK) {
char *errorMessage;
const char *sql_statement = "CREATE TABLE IF NOT EXISTS users(ID INTEGER PRIMARY KEY AUTOINCREMENT,FIRSTNAME TEXT,LASTNAME TEXT,EMAILID TEXT,PASSWORD TEXT,BIRTHDATE DATE)";
if (sqlite3_exec(DB,sql_statement,NULL,NULL,&errorMessage)!=SQLITE_OK) {
NSLog(#"Failed to create the table");
}
sqlite3_close(DB);
}
else{
NSLog(#"Failded to open/create the table");
}
}
NSLog(#"database path=%#",databasePath);
return databasePath;
}
+(NSString*)encodedString:(const unsigned char *)ch
{
NSString *retStr;
if(ch == nil)
retStr = #"";
else
retStr = [NSString stringWithCString:(char*)ch encoding:NSUTF8StringEncoding];
return retStr;
}
+(BOOL)executeScalarQuery:(NSString*)str{
NSLog(#"executeScalarQuery is called =%#",str);
sqlite3_stmt *statement= nil;
sqlite3 *database;
BOOL fRet = NO;
NSString *strPath = [self getDatabasePath];
if (sqlite3_open([strPath UTF8String],&database) == SQLITE_OK) {
if (sqlite3_prepare_v2(database, [str UTF8String], -1, &statement, NULL) == SQLITE_OK) {
if (sqlite3_step(statement) == SQLITE_DONE)
fRet =YES;
}
sqlite3_finalize(statement);
}
sqlite3_close(database);
return fRet;
}
+(NSMutableArray *)executeQuery:(NSString*)str{
sqlite3_stmt *statement= nil; // fetch data from table
sqlite3 *database;
NSString *strPath = [self getDatabasePath];
NSMutableArray *allDataArray = [[NSMutableArray alloc] init];
if (sqlite3_open([strPath UTF8String],&database) == SQLITE_OK) {
if (sqlite3_prepare_v2(database, [str UTF8String], -1, &statement, NULL) == SQLITE_OK) {
while (sqlite3_step(statement) == SQLITE_ROW) {
NSInteger i = 0;
NSInteger iColumnCount = sqlite3_column_count(statement);
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
while (i< iColumnCount) {
NSString *str = [self encodedString:(const unsigned char*)sqlite3_column_text(statement, (int)i)];
NSString *strFieldName = [self encodedString:(const unsigned char*)sqlite3_column_name(statement, (int)i)];
[dict setObject:str forKey:strFieldName];
i++;
}
[allDataArray addObject:dict];
}
}
sqlite3_finalize(statement);
}
sqlite3_close(database);
return allDataArray;
}
#end
And called that method where you want to use!!
NSString *insertSql = [NSString stringWithFormat:#"INSERT INTO users(firstname,lastname,emailid,password,birthdate) VALUES ('%#','%#','%#','%#','%#')",_firstNameTextField.text,_lastNameTextField.text,_emailTextField.text,_passwordTextField.text,_BirthdayTextField.text];
if ([Sqlitedatabase executeScalarQuery:insertSql]==YES)
{
[self showUIalertWithMessage:#"Registration succesfully created"];
}else{
NSLog(#"Data not inserted successfully");
}
And If you want to fetch data from table then you can do this!!
NSString *insertSql = [NSString stringWithFormat:#"select emailid,password from users where emailid ='%#' and password = '%#'",[_usernameTextField.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]],[_passwordTextField.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]];
NSMutableArray *data =[Sqlitedatabase executeQuery:insertSql];
NSLog(#"Fetch data from database is=%#",data);
Multiple Execute Query!!
NSString *insertSql = [NSString stringWithFormat:#"INSERT INTO users (firstname,lastname,emailid,password,birthdate) VALUES ('%#','%#','%#','%#','%#')",_firstNameTextField.text,_lastNameTextField.text,_emailTextField.text,_passwordTextField.text,_BirthdayTextField.text];
NSString *insertSql1 = [NSString stringWithFormat:#"INSERT INTO contact (firstname,lastname,emailid,password,birthdate) VALUES ('%#','%#','%#','%#','%#')",_firstNameTextField.text,_lastNameTextField.text,_emailTextField.text,_passwordTextField.text,_BirthdayTextField.text];
NSMutableArray * array = [[NSMutableArray alloc]initWithObjects:insertSql,insertSql1,nil];
for (int i=0; i<array.count; i++)
{
[Sqlitedatabase executeScalarQuery:[array objectAtIndex:i]];
}
See this for your issue:
Insert multiple tables in same database in sqlite
or if you want
Multi-table INSERT using one SQL statement in AIR SQLite
then use this:
http://probertson.com/articles/2009/11/30/multi-table-insert-one-statement-air-sqlite/

How to fetch data from table in Sqlite in ios?

I am working with the SQLite i am able to create the table and alter table but after adding columns to the table, data is not fetching.
Up to now my implementation inserting table values like below
NSString *sqlString=[NSString stringWithFormat:#"insert into %#(toid,fromid,msg,timedate,left,messageID,chatStatus) values('%#','%#','%#','%#',%d,'%#','%#')",tableName,userid,friendid,message,timedate,(int)leftright,messageID,chatStatus];
below i am fetching data from table
-(NSMutableArray *)AllRowFromTableName:(NSString *)tableName withUserID:(NSString *)userid withFriendID:(NSString *)friendid
{
NSMutableArray *array=[[NSMutableArray alloc] init];
NSString *sqlString=[NSString stringWithFormat:#"select *from chatTable where toid='%#' and fromid='%#'",userid,friendid];
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(db, [sqlString UTF8String], -1, &statement, nil)==SQLITE_OK) {
while (sqlite3_step(statement)==SQLITE_ROW) {
ChatHistorySkeleton *tempSkeleton=[[ChatHistorySkeleton alloc] init];
tempSkeleton.u_id =[[NSString alloc] initWithUTF8String:(char *)sqlite3_column_text(statement, 1)];//f_id
// NSString *strn = [NSString stringWithFormat:#"%#",tempSkeleton.mToID];
tempSkeleton.f_id=[[NSString alloc] initWithUTF8String:(char *)sqlite3_column_text(statement, 2)];
tempSkeleton.msg=[[NSString alloc] initWithUTF8String:(char *)sqlite3_column_text(statement, 3)];
//tempSkeleton.fromMe=[[NSString alloc] initWithUTF8String:(char *)sqlite3_column_text(statement, 3)];
// tempSkeleton.fromMe=((int)sqlite3_column_int(statement, 4)) ? YES : NO;
tempSkeleton.lft_rght=(int)sqlite3_column_int(statement, 4);
tempSkeleton.tim_dte=[[NSString alloc] initWithUTF8String:(char *)sqlite3_column_text(statement, 5)];
//if messageID Null
char *messageIDForEmptyCheck = (char *)sqlite3_column_text(statement, 6);
NSString *messageID1 = messageIDForEmptyCheck?[[NSString alloc]initWithUTF8String:messageIDForEmptyCheck]:#"";
tempSkeleton.messageID=messageID1;
//if chat status Null
char *chatStatus = (char *) sqlite3_column_text(statement,7);
NSString *chatStatus1 = chatStatus?[[NSString alloc]initWithUTF8String:chatStatus]:#"";
tempSkeleton.chatStatus=chatStatus1;
[array addObject:tempSkeleton];
// NSLog(#"IN LOOP=>%#",array);
}
}
return array;
}
I just alter table and added two columns messageID,chatstatus but these two values showing empty. What I am missing?

Loop through while(sqlite3_step(statement) until all the rows

I am storing multiple values in Sqlite database in my iOS app.
I need to retrieve the values under "cellForRowAtIndexPath"
- (NSString *) retrieveDetailText :(NSString *) emailAddress :(NSString *) uidText :(NSString *) folderName {
NSString *detailText = nil;
const char *dbpath = [databasePath UTF8String];
//SQLIte Statement
NSString *selettablequery = [NSString stringWithFormat:#"select * from MailFolderDBTable"];
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
if (sqlite3_prepare(database, [selettablequery UTF8String], -1, &statement, NULL) ==SQLITE_OK)
{
while(sqlite3_step(statement) == SQLITE_ROW)
{
char *uidfield = (char *) sqlite3_column_text(statement, 5);
NSString *uidStr = [[NSString alloc] initWithUTF8String: uidfield];
NSLog(#"retrieveDetailText: uidStr: %#", uidStr);
if([uidStr isEqualToString:uidText]) {
char *emailstring = (char *) sqlite3_column_text(statement, 6);
NSString *detailTextData = [[NSString alloc] initWithUTF8String: emailstring];
NSData *data = [[NSData alloc] initWithBase64EncodedString:detailTextData options:NSDataBase64DecodingIgnoreUnknownCharacters];
detailText = [NSKeyedUnarchiver unarchiveObjectWithData:data];
}
From this code, I need to loop through at while(sqlite3_step(statement) == SQLITE_ROW)
As I am calling retrieveDetailText under cellForRowAtIndexPath, and it is not looping through here while(sqlite3_step(statement) == SQLITE_ROW), It checks if([uidStr isEqualToString:uidText]) only one time.
How can i loop through while(sqlite3_step(statement) until all the rows checked and get the value.
If you only need one row which satisfies uidText, then you can change your query no?
//SQLIte Statement
NSString *selettablequery = [NSString stringWithFormat:#"select * from MailFolderDBTable where uid = %#", uidText];
Otherwise, you can fetch all the data before loading your tableView, in an array and then use it as your tableView data source.

How to Show Distinct Value From Sqllite Table in iOS?

i am Newbie in iOS Development, and First time Use Sqllite database so Sorry For this Question but i am So Confusing Please Give me Solution for this.
I added Data in to My Sqllite Table Like as
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
sqlite3_stmt *statement;
const char *dbpath = [_databasePath UTF8String];
if (sqlite3_open(dbpath, &_myDatabase) == SQLITE_OK) {
NSString *insertSQL = [NSString stringWithFormat:
#"INSERT INTO ALLREADTABLE (PostId, PostTitle, ImageLink, ShortDescription,Category,PostDate) VALUES (\"%#\", \"%#\", \"%#\", \"%#\",\"%#\",\"%#\")",
post_id, cell.headLabel.text, image,self.shortDiscription,cell.categoryLabel.text,cell.timeLabel.text];
const char *insert_stmt = [insertSQL UTF8String];
sqlite3_prepare_v2(_myDatabase, insert_stmt,
-1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_DONE)
{
NSString *string=[NSString stringWithFormat:#"Value Added %# %# %# %# %# %#",post_id, cell.headLabel.text, image,self.shortDiscription,cell.categoryLabel.text,cell.timeLabel.text];
NSLog(#"String %#",string);
} else
{
NSLog(#"Failed to add contact");
}
sqlite3_finalize(statement);
sqlite3_close(_myDatabase);
}
Then it is added data in to Data Base as I want and it also added Duplicate Value in to table , so For Distinct Value i Write a Code to Fetch data like as
- (void)getTextFomDB
{
NSString *docsDir;
NSArray *dirPaths;
// Get the documents directory
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = dirPaths[0];
// Build the path to the database file
_databasePath = [[NSString alloc]
initWithString: [docsDir stringByAppendingPathComponent:
#"sampleDatabase.db"]];
const char *dbpath = [_databasePath UTF8String];
sqlite3_stmt *statement;
if (sqlite3_open(dbpath, &_myDatabase) == SQLITE_OK)
{
NSString *querySQL = #"SELECT DISTINCT PostId, PostTitle, ImageLink, ShortDescription,Category,PostDate FROM ALLREADTABLE";
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(_myDatabase, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
[self.postId removeAllObjects];
[self.postTitle removeAllObjects];
[self.imageLink removeAllObjects];
[self.shortDecsription removeAllObjects];
[self.category removeAllObjects];
[self.postDate removeAllObjects];
while (sqlite3_step(statement) == SQLITE_ROW) {
//NSString *personID = [[NSString alloc] initWithUTF8String: (const char *) sqlite3_column_text(statement, 0)];
NSString *postId = [[NSString alloc] initWithUTF8String: (const char *) sqlite3_column_text(statement, 1)];
NSString *postTitle = [[NSString alloc] initWithUTF8String: (const char *) sqlite3_column_text(statement, 2)];
NSString *ImageLink = [[NSString alloc] initWithUTF8String: (const char *) sqlite3_column_text(statement, 3)];
NSString *shortDescrip = [[NSString alloc] initWithUTF8String: (const char *) sqlite3_column_text(statement, 4)];
NSString *Category = [[NSString alloc] initWithUTF8String: (const char *) sqlite3_column_text(statement, 5)];
NSString *postDate = [[NSString alloc] initWithUTF8String: (const char *) sqlite3_column_text(statement, 6)];
[self.postId addObject:[NSString stringWithFormat:#"%# ", postId]];
[self.postTitle addObject:[NSString stringWithFormat:#"%# ",postTitle]];
[self.imageLink addObject:[NSString stringWithFormat:#"%#",ImageLink]];
[self.shortDecsription addObject:[NSString stringWithFormat:#" %#",shortDescrip]];
[self.category addObject:[NSString stringWithFormat:#" %#",Category]];
[self.postDate addObject:[NSString stringWithFormat:#" %#",postDate]];
}
sqlite3_finalize(statement);
}
sqlite3_close(_myDatabase);
}
}
Then it Give me Error like as
[NSPlaceholderString initWithUTF8String:]: NULL cString
Here I want Distinct Value From My SqlliteTable. please Give me Solution For that. I know It is easy But i am Newbie in Database so please Sorry
and Thanks in advance.
You are using initWithUTF8String to get values from database, So if there is a field in database which accept null data than it will gives you an error when you are trying to fetch null data from database.
I suggest you replace all data retrieving code like
NSString *postId = [[NSString alloc] initWithUTF8String: (const char *) sqlite3_column_text(statement, 1)];
with below code:
NSString *postId = [NSString stringWithUTF8String:(const char *) sqlite3_column_text(statement, 1)];
This will replace not null data to an empty string.
This is being caused by trying to create a NSString object with a NULL string. It is on one of these lines:
[[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, ...)];
So, before you create a NSString with the results of the sql statement you need to check for NULL like this:
char *tmp = sqlite3_column_text(statement, 1);
if (tmp == NULL)
postId = nil;
else
postId = [[NSString alloc] initWithUTF8String:tmp];
Reference: lnafziger

Store String from SQLite to NSMutableArray

I'm working on an app that displays various feeds using ASIHTTPRequest. The user can add new sources to the app that are stored in an SQLite database. Currently I give the feeds to the app in the viewDidLoad method of my FeedsViewController but i want to be able to retrieve the data that contains the link for the source and store it in an array to use it.
Currently the app looks like and below the current code:
- (void)viewDidLoad
{
[super viewDidLoad];
self.title =#"Lajmet";
self.navigationController.navigationBar.tintColor = [UIColor blackColor];
//self.tabBarController.tabBar.tintColor = [UIColor blackColor];
self.allEntries = [NSMutableArray array];
self.queue = [[NSOperationQueue alloc] init];
self.feeds = [NSMutableArray arrayWithObjects:#"http://pcworld.al/feed",#"http://geek.com/feed", #"http://feeds.feedburner.com/Mobilecrunch",#"http://zeri.info/rss/rss-5.xml",
nil];
[self.tableView reloadData];
[self refresh];
}
My view that contains the function (AddSourcesViewController) to add and delete new sources looks like this and here the code:
- (void)viewDidLoad
{
[super viewDidLoad];
arrayOfSource = [[NSMutableArray alloc]init];
[[self myTableView]setDelegate:self];
[[self myTableView]setDataSource:self];
[self createOrOpenDB];
// Display sources in table view
sqlite3_stmt *statement;
if (sqlite3_open([dbPathString UTF8String], &sourceDB)==SQLITE_OK) {
[arrayOfSource removeAllObjects];
NSString *querySql = [NSString stringWithFormat:#"SELECT * FROM SOURCES"];
const char* query_sql = [querySql UTF8String];
if (sqlite3_prepare(sourceDB, query_sql, -1, &statement, NULL)==SQLITE_OK) {
while (sqlite3_step(statement)==SQLITE_ROW) {
NSString *name = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(statement, 1)];
NSString *link = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(statement, 2)];
NSString *category = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(statement, 3)];
SourceDB *source = [[SourceDB alloc]init];
[source setName:name];
[source setLink:link];
[source setCategory:category];
[arrayOfSource addObject:source];
}
}
}
[[self myTableView]reloadData];
}
- (void)createOrOpenDB
{
NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docPath = [path objectAtIndex:0];
dbPathString = [docPath stringByAppendingPathComponent:#"sources.db"];
char *error;
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:dbPathString]) {
const char *dbPath = [dbPathString UTF8String];
//creat db here
if (sqlite3_open(dbPath, &sourceDB)==SQLITE_OK) {
const char *sql_stmt = "CREATE TABLE IF NOT EXISTS SOURCES (ID INTEGER PRIMARY KEY AUTOINCREMENT, NAME TEXT, LINK TEXT, CATEGORY TEXT)";
sqlite3_exec(sourceDB, sql_stmt, NULL, NULL, &error);
sqlite3_close(sourceDB);
}
}
}
- (IBAction)addSourceButton:(id)sender
{
char *error;
if (sqlite3_open([dbPathString UTF8String], &sourceDB)==SQLITE_OK) {
NSString *inserStmt = [NSString stringWithFormat:#"INSERT INTO SOURCES(NAME,LINK,CATEGORY) values ('%s', '%s','%s')",[self.nameField.text UTF8String], [self.linkField.text UTF8String],[self.categoryField.text UTF8String]];
const char *insert_stmt = [inserStmt UTF8String];
if (sqlite3_exec(sourceDB, insert_stmt, NULL, NULL, &error)==SQLITE_OK) {
NSLog(#"Source added");
SourceDB *source = [[SourceDB alloc]init];
[source setName:self.nameField.text];
[source setLink:self.linkField.text];
[source setCategory:self.categoryField.text];
[arrayOfSource addObject:source];
}
sqlite3_close(sourceDB);
}
}
- (IBAction)deleteSourceButton:(id)sender
{
[[self myTableView]setEditing:!self.myTableView.editing animated:YES];
}
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
SourceDB *s = [arrayOfSource objectAtIndex:indexPath.row];
[self deleteData:[NSString stringWithFormat:#"Delete from sources where name is '%s'", [s.name UTF8String]]];
[arrayOfSource removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
-(void)deleteData:(NSString *)deleteQuery
{
char *error;
if (sqlite3_exec(sourceDB, [deleteQuery UTF8String], NULL, NULL, &error)==SQLITE_OK) {
NSLog(#"Source deleted");
}
}
- (IBAction)showSourceButton:(id)sender
{
sqlite3_stmt *statement;
if (sqlite3_open([dbPathString UTF8String], &sourceDB)==SQLITE_OK) {
[arrayOfSource removeAllObjects];
NSString *querySql = [NSString stringWithFormat:#"SELECT * FROM SOURCES"];
const char* query_sql = [querySql UTF8String];
if (sqlite3_prepare(sourceDB, query_sql, -1, &statement, NULL)==SQLITE_OK) {
while (sqlite3_step(statement)==SQLITE_ROW) {
NSString *name = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(statement, 1)];
NSString *link = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(statement, 2)];
NSString *category = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(statement, 3)];
SourceDB *source = [[SourceDB alloc]init];
[source setName:name];
[source setLink:link];
[source setCategory:category];
[arrayOfSource addObject:source];
}
}
}
[[self myTableView]reloadData];
}
Now i created a method in my FeedsViewConrtoller:
-(void)ReadData
{
[self createOrOpenDB];
feedsArray = [[NSMutableArray alloc] init];
const char *dbPath = [dbPathString UTF8String];
if (sqlite3_open(dbPath, &sourceDB)==SQLITE_OK)
{
const char *sqlstmt = "SELECT LINK FROM SOURCES";
sqlite3_stmt *completedstmt;
if (sqlite3_prepare_v2(sourceDB, sqlstmt, -1, &completedstmt, NULL)==SQLITE_OK)
{
while(sqlite3_step(completedstmt)==SQLITE_ROW)
{
NSString *link = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(completedstmt, 2)];
SourceDB *source = [[SourceDB alloc]init];
[source setLink:link];
[feedsArray addObject:link];
}
}
}
}
And when i change
self.feeds = [NSMutableArray arrayWithObjects:#"http://pcworld.al/feed",#"http://geek.com/feed", #"http://feeds.feedburner.com/Mobilecrunch",#"http://zeri.info/rss/rss-5.xml",
nil];
to:
self.feeds = [NSMutableArray arrayWithArray:feedsArray];
i get the following error:
2013-08-14 15:03:55.328 ShqipCom[3128:c07] (null)
What am i doing wrong here?
Thanks a lot!
Granit
In ReadData, you're returning one column, but then retrieving the third column with:
NSString *link = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(completedstmt, 2)];
That should be:
NSString *link = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(completedstmt, 0)];
A couple of other thoughts:
Part of the reason it's hard for us to answer this is that you aren't reporting SQLite errors. I'd suggest logging when a SQLite test failed, e.g.:
if (sqlite3_prepare_v2(sourceDB, sqlstmt, -1, &completedstmt, NULL)==SQLITE_OK
{
while(sqlite3_step(completedstmt)==SQLITE_ROW)
{
NSString *link = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(completedstmt, 2)];
SourceDB *source = [[SourceDB alloc]init];
[source setLink:link];
[feedsArray addObject:link];
}
}
whereas you might want something like:
if (sqlite3_prepare_v2(sourceDB, sqlstmt, -1, &completedstmt, NULL)!=SQLITE_OK
{
NSLog(#"%s: prepare error: %s", __FUNCTION__, sqlite3_errmsg(sourceDB));
return;
}
int rc;
while ((rc = sqlite3_step(completedstmt)) == SQLITE_ROW)
{
NSString *link = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(completedstmt, 2)];
SourceDB *source = [[SourceDB alloc]init];
[source setLink:link];
[feedsArray addObject:link];
}
if (rc != SQLITE_DONE)
{
NSLog(#"%s: step error: %s", __FUNCTION__, sqlite3_errmsg(sourceDB));
return;
}
You really should be checking the result of every SQLite call, and reporting an error message if not successful. Otherwise you're flying blind.
On your INSERT statement, are you 100% sure that those three fields will never have an apostrophe in them? (Also, if the user is entering any of this data, you have to be concerned about SQL injection attacks.) Generally you'd use ? placeholders in your SQL, you'd prepare the SQL with sqlite3_prepare_v2, and then use sqlite3_bind_text to bind text values to those placeholders, and then you'd sqlite3_step and confirm a return value of SQLITE_DONE.
Note, checking each and every sqlite3_xxx function call return result and doing all of the necessary sqlite3_bind_xxx calls is a little cumbersome. In your next project, if you want to streamline your SQLite code, you might want to consider using FMDB.
Your can add any object in NSMutableArray by
[myArray name addObject:mYString]; // add whatever object here;
if you want to add Array to you NSMutableArray
[myArray addObjectsFromArray:anOtherArray];

Resources