how to created an application that records a series of longitude and latitude values in a SQLite database and display them as a coloured track on a MapActivity.
I need help. How can store the map coordinates in sqlite database and display like journey details in table .For example I have done one journey from mumbai to Pune .Then how can store the data into database that can available for future reference .when user click on journey name it should give all details
If you are new to Sqlite Then look into this class for data base
Create two database file as the following
---->>>>
Database.h
Write the following code in this file
#import <Foundation/Foundation.h>
#import <sqlite3.h>
#interface DataBase : NSObject {
sqlite3 *database;
}
+(DataBase *) shareDataBase;
-(BOOL) createDataBase:(NSString *)DataBaseName;
-(NSString*) GetDatabasePath:(NSString *)database;
-(NSMutableArray *) getAllDataForQuery:(NSString *)sql forDatabase:(NSString *)database;
-(void) inseryQuery:(NSString *) insertSql forDatabase:(NSString *)database1;
-(void) deleteQuery:(NSString *) deleteSql forDatabase:(NSString *)database1;
-(void) updateQuery:(NSString *) updateSql forDatabase:(NSString *)database1;
#end
---->>>>
Database.m
Write the following code in this file
#import "DataBase.h"
#implementation DataBase
static DataBase *SampleDataBase =nil;
+(DataBase*) shareDataBase{
if(!SampleDataBase){
SampleDataBase = [[DataBase alloc] init];
}
return SampleDataBase;
}
-(NSString *) GetDatabasePath:(NSString *)database1{
[self createDataBase:database1];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
return [documentsDirectory stringByAppendingPathComponent:database1];
}
-(BOOL) createDataBase:(NSString *)DataBaseName{
BOOL success;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:DataBaseName];
success = [fileManager fileExistsAtPath:writableDBPath];
if (success) return success;
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:DataBaseName];
success = [fileManager copyItemAtPath:defaultDBPath toPath:writableDBPath error:&error];
if (!success) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error!!!" message:#"Failed to create writable database" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:nil];
[alert show];
[alert release];
}
return success;
}
-(NSMutableArray *) getAllDataForQuery:(NSString *)sql forDatabase:(NSString *)database1{
sqlite3_stmt *statement = nil ;
NSString *path = [self GetDatabasePath:database1];
NSMutableArray *alldata;
alldata = [[NSMutableArray alloc] init];
if(sqlite3_open([path UTF8String],&database) == SQLITE_OK )
{
NSString *query = sql;
if((sqlite3_prepare_v2(database,[query UTF8String],-1, &statement, NULL)) == SQLITE_OK)
{
while(sqlite3_step(statement) == SQLITE_ROW)
{
NSMutableDictionary *currentRow = [[NSMutableDictionary alloc] init];
int count = sqlite3_column_count(statement);
for (int i=0; i < count; i++) {
char *name = (char*) sqlite3_column_name(statement, i);
char *data = (char*) sqlite3_column_text(statement, i);
NSString *columnData;
NSString *columnName = [NSString stringWithCString:name encoding:NSUTF8StringEncoding];
if(data != nil)
columnData = [NSString stringWithCString:data encoding:NSUTF8StringEncoding];
else {
columnData = #"";
}
[currentRow setObject:columnData forKey:columnName];
}
[alldata addObject:currentRow];
}
}
sqlite3_finalize(statement);
}
sqlite3_close(database);
return alldata;
}
-(void) inseryQuery:(NSString *) insertSql forDatabase:(NSString *)database1{
sqlite3_stmt *statement = nil ;
NSString *path = [self GetDatabasePath:database1];
if(sqlite3_open([path UTF8String],&database) == SQLITE_OK )
{
if((sqlite3_prepare_v2(database,[insertSql UTF8String],-1, &statement, NULL)) == SQLITE_OK)
{
if(sqlite3_step(statement) == SQLITE_OK){
}
}
sqlite3_finalize(statement);
}
sqlite3_close(database);
}
-(void) updateQuery:(NSString *) updateSql forDatabase:(NSString *)database1{
sqlite3_stmt *statement = nil ;
NSString *path = [self GetDatabasePath:database1];
if(sqlite3_open([path UTF8String],&database) == SQLITE_OK )
{
if((sqlite3_prepare_v2(database,[updateSql UTF8String],-1, &statement, NULL)) == SQLITE_OK)
{
if(sqlite3_step(statement) == SQLITE_OK){
}
}
sqlite3_finalize(statement);
}
sqlite3_close(database);
}
-(void) deleteQuery:(NSString *) deleteSql forDatabase:(NSString *)database1{
sqlite3_stmt *statement = nil ;
NSString *path = [self GetDatabasePath:database1];
if(sqlite3_open([path UTF8String],&database) == SQLITE_OK )
{
if((sqlite3_prepare_v2(database,[deleteSql UTF8String],-1, &statement, NULL)) == SQLITE_OK)
{
if(sqlite3_step(statement) == SQLITE_OK){
}
}
sqlite3_finalize(statement);
}
sqlite3_close(database);
}
#end
Now to get data use the following code
NSString *sql = #"select * from UserInfo"; <br>
userInfo = [[DataBase shareDataBase] getAllDataForQuery:sql forDatabase:#"Sample.db"];
It will return array of all the row in form of NSDictionary.
To add new record use the following code
NSString *sql = [NSString stringWithFormat:#"insert into userInfo values ('city','name','phone')"];
[[DataBase shareDataBase] inseryQuery:sql forDatabase:#"Sample.db"];
In the same way there is also method to update and delete record.
so This is the best example I have seen we just need to call one method to for fetch, insert , update or delete.
Thanks for seeing the question,
To get location import corelocation framework in your project.
follow this link
http://developer.apple.com/library/ios/#samplecode/LocateMe/Introduction/Intro.html#//apple_ref/doc/uid/DTS40007801 to get sample for getting location.
This is the format to set location in json
[{"Longitude":"45.2655","Latitude":"23.2655"},{"Longitude":"45.2655","Latitude":"23.2655"},{"Longitude":"45.2655","Latitude":"23.2655"}]
Thanks.
You need to create a table with fields ...... Source,Destination,SourceLat,SourceLong,DestinationLat,DestinationLong....... and in this you will pass
Source - Mumbai,(or other) - text - varchar type
Destinatino - Pune, (or other) -text - varchar type
SourceLat - coordinate.latitude; - number with decimal precison upto 10 points.
SourceLong - coordinate.longitude - number with decimal precison upto 10 points.
DestinationLat - coordinate.latitude; - number with decimal precison upto 10 points.
DestinationLong - coordinate.longitude - number with decimal precison upto 10 points.
Thanks,
First you need to create object of NSMutableArray *arrayOflocation; in .h file,
Then in you locationUpdate method write the following code
NSMutableDictionary *LocationDic = [[NSMutableDictionary alloc] init];
[LocationDic setObject:[NSString stringWithFormat:#"%f",c.latitude] forKey:#"Latitude"];
[LocationDic setObject:[NSString stringWithFormat:#"%f",c.longitude] forKey:#"Longitude"];
[arrayOflocation addObject:LocationDic];
now when you save the trip you need to create the string for the json format for that you need to use json API you can get it using google easily . write the following code when you want to save the string in file.
NSString *dataString = [arrayOflocation JSONRepresentation];
//// code to write dataString in txt file.
and at finally need to store the file name in sqlite along with other detail for the trip.
Related
Im storing some values in my server. Then i fetched that values using JSON and added to local database table. Then i need to display that values to view. But array values displaying in NSLog. It won't displaying in view. I don't need to display in TableView.
code:
-(void) addDataToArray{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
//NSLog(#"docs dir is %#", documentsDirectory);
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"db1.sqlite"];
//NSLog(#"filepath %#",path);
mArray = [[NSMutableArray alloc]init];
if (sqlite3_open([path UTF8String], &database) == SQLITE_OK) {
// const char *sql = "SELECT id,cat_name FROM categories order by order_by";
const char *sql = "SELECT * FROM categories";
NSLog(#"Sql is %s",sql);
sqlite3_stmt *statement;
int catID = 0;
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) {
NSString *catName = [[NSString alloc] initWithUTF8String:
(const char *) sqlite3_column_text(statement, 1)];
NSLog(#"catName is %#",catName);
[mArray addObject:catName];
// [self.view addConstraints:mArray];
NSLog(#"mArray is %#", mArray);
[catName release];
catID = sqlite3_column_int(statement, 0);
}
}
sqlite3_finalize(statement);
} else {
sqlite3_close(database);
NSAssert1(0, #"Failed to open database with message '%s'.", sqlite3_errmsg(database));
// Additional error handling, as appropriate...
}
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(#"connectionDidFinishLoading");
[self addDataToArray];
}
NSLog:
catName is person1
mArray is (
person1
)
catName is person2
mArray is (
person1
person2
)
TextView:
UITextView *txt=[[UITextView alloc]initWithFrame:CGRectMake(50, 50, 200, 200)];
// txt.text=[mArray objectAtIndex:0];
[self.view addSubview:txt];
for (int i = 0; i<[mArray count]; i++ ) { NSLog(#"index %d",i); }
You need to merge array's objects to convert them in string, because you can't show an array in textView directly. If mArray contains NSString type object then you can do like this:
NSMutableString *string = [[NSMutableString alloc] init];
for (id obj in mArray){
[string appendString:obj];
}
textView.text = string;
If you want to show each person in next line you can add \n after each name.
I have created a dictionary application with several data bases , everything works fine except saving columns in bookmark ! , I know , it's not possible change files in NSBundle but I don't know how can I fix it . I would be grateful if you help me out here is the code :
- (NSString *) getDBPath {
NSString *path;
if ( [[[NSUserDefaults standardUserDefaults] stringForKey:#"Bv"] intValue] == 2)
{
path = [[NSBundle mainBundle]pathForResource:#"pr-eng" ofType:#"sqlite"];
} else {
path = [[NSBundle mainBundle]pathForResource:#"eg-pr" ofType:#"sqlite"];
}
if ( [[[NSUserDefaults standardUserDefaults] stringForKey:#"Bv"] intValue] == 3)
{
path = [[NSBundle mainBundle]pathForResource:#"german" ofType:#"sqlite"];
}
return path;
}
Here is bookmarking function :
-(void) setBookMark:(NSInteger)oid {
sqlite3_stmt *statement;
const char *dbpath = [[self getDBPath] UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
NSString *SetFavSQL = [NSString stringWithFormat: #"UPDATE DIC SET bookmark=1 WHERE id=\"%d\"", oid];
// NSLog(#"%#",SetFavSQL);
const char *SetFav_stmt = [SetFavSQL UTF8String];
sqlite3_prepare_v2(database, SetFav_stmt, -1, &statement, NULL);
if (sqlite3_step(statement) != SQLITE_DONE)
{
}
sqlite3_finalize(statement);
sqlite3_close(database);
}
}
Reading database :
-(void) read_Database{
NSMutableArray *DB_Array = [[NSMutableArray alloc] init];
NSMutableArray *word_Array = [[NSMutableArray alloc] init];
if(sqlite3_open([[self getDBPath]UTF8String], &database) == SQLITE_OK) {
NSString *sql =#"SELECT * FROM DIC";
// NSLog(#"%#",sql);
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(database, [sql UTF8String] , -1, &compiledStatement, NULL) == SQLITE_OK) {
while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
NSInteger oid = sqlite3_column_int(compiledStatement, 0);
const char* f1 = (const char*)sqlite3_column_text(compiledStatement, 1);
NSString *oName = f1 == NULL ? nil : [[NSString alloc] initWithUTF8String:f1];
const char* f2 = (const char*)sqlite3_column_text(compiledStatement, 2);
NSString *oMean = f2 == NULL ? nil : [[NSString alloc] initWithUTF8String:f2];
const char* f3 = (const char*)sqlite3_column_text(compiledStatement, 3);
NSString *oPron = f3 == NULL ? nil : [[NSString alloc] initWithUTF8String:f3];
NSInteger bm = sqlite3_column_int(compiledStatement, 5);
readerClass = [[Reader alloc]initWithReadDB:oid Name:oName Mean:oMean Pron:oPron bookMark:bm];
[DB_Array addObject:readerClass];
}
}
sqlite3_finalize(compiledStatement);
}
sqlite3_close(database);
AppDelegate *appDelegateClass = (AppDelegate *)[[UIApplication sharedApplication] delegate];
[appDelegateClass.wordList removeAllObjects];
appDelegateClass.wordList=[word_Array mutableCopy];
[appDelegateClass.dictionaryArray removeAllObjects];
appDelegateClass.dictionaryArray=[DB_Array mutableCopy];
}
I know , it's not possible change files in NSBundle
Great, at least you made the effort to google the issue. Then, why not just copy these files to be updated upon the very first launch of the application to some writable path, like NSDocumentsDirectory?
NSArray *paths = NSSearchPathsForDirectoriesInDomains(NSDocumentsDirectory, NSUserDomainMask, YES);
NSString *docsDir = [paths objectAtIndex:0];
[[NSFileManager defaultManager] copyItemAtPath:path toPath:[docsDir stringByAppendingPathComponent:#"db.sql"] error:NULL];
etc.
For further improvement in #H2CO3's answer and for more clarification I post my answer :)
Here is what I do to save data to database on iPhone or iPad (iOS). All data is been kept in device locally. So if app is uninstalled all data will lost, if user hasn't take backup of the app and restored if from backup.
NSFileManager *fileMgr;
NSString *homeDir;
These are the ivar I use in below functions all functions are in my .m file which is contains all my db related functions like update, insert, select, delete.
-(void)CopyDbToDocumentsFolder
{
NSError *err=nil;
fileMgr = [NSFileManager defaultManager];
NSString *dbpath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"res_in_mil.sqlite"];
NSString *copydbpath = [self.GetDocumentDirectory stringByAppendingPathComponent:#"res_in_mil.sqlite"];
[fileMgr removeItemAtPath:copydbpath error:&err];
if(![fileMgr copyItemAtPath:dbpath toPath:copydbpath error:&err])
{
UIAlertView *tellErr = [[UIAlertView alloc] initWithTitle:title message:#"Unable to copy database." delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[tellErr show];
}
}
-(NSString *) GetDocumentDirectory
{
fileMgr = [NSFileManager defaultManager];
homeDir = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents"];
return homeDir;
}
As the name is self-explains there is no need to explain what these functions are for.
And in appDelegate.m I use the below code to copy my DB to the specified location where I can edit my DB. This code is in - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions method.
NSFileManager *fileMgr;
myDB *dbObj = [[myDB alloc]init];
fileMgr = [NSFileManager defaultManager];
NSString *dbPath = [[dbObj GetDocumentDirectory] stringByAppendingPathComponent:#"res_in_mil.sqlite"];
BOOL success = [fileMgr fileExistsAtPath:dbPath];
if(!success)
[dbObj CopyDbToDocumentsFolder];
I use this for one DB as I have only one DB. But I think you can extend these functions to copy more then one DB.
Even you can make one function to identify that the required DB is in DocumentDirectory or not using the code of - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions method given above.
And for insert, update, delete, select operation I use the below code to open the DB for any access.
fileMgr = [NSFileManager defaultManager];
NSString *dbPath = [[self GetDocumentDirectory] stringByAppendingPathComponent:#"res_in_mil.sqlite"];
BOOL success = [fileMgr fileExistsAtPath:dbPath];
if(!success)
{
NSLog(#"Cannot locate database file '%#'",dbPath);
[self CopyDbToDocumentsFolder];
}
Happy Coding :)
I think you have to make only one master database and can have multiple tables in it. That can resolve your problem.
I am creating an application where I am using SQLite database to save data. But when I run my application I get the following errors:
#interface TDatabase : NSObject {
sqlite3 *database;
}
+(TDatabase *) shareDataBase;
-(BOOL) createDataBase:(NSString *)DataBaseName;
-(NSString*) GetDatabasePath:(NSString *)database;
-(NSMutableArray *) getAllDataForQuery:(NSString *)sql forDatabase:(NSString *)database;
-(void*) inseryQuery:(NSString *) insertSql forDatabase:(NSString *)database1;
#end
#import "TDatabase.h"
#import <sqlite3.h>
#implementation TDatabase
static TDatabase *SampleDataBase =nil;
+(TDatabase*) shareDataBase{
if(!SampleDataBase){
SampleDataBase = [[TDatabase alloc] init];
}
return SampleDataBase;
}
-(NSString *)GetDatabasePath:(NSString *)database1{
[self createDataBase:database1];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
return [documentsDirectory stringByAppendingPathComponent:database1];
}
-(BOOL) createDataBase:(NSString *)DataBaseName{
BOOL success;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:DataBaseName];
success = [fileManager fileExistsAtPath:writableDBPath];
if (success) return success;
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:DataBaseName];
success = [fileManager copyItemAtPath:defaultDBPath toPath:writableDBPath error:&error];
if (!success) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error!!!" message:#"Failed to create writable database" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:nil];
[alert show];
[alert release];
}
return success;
}
-(NSMutableArray *) getAllDataForQuery:(NSString *)sql forDatabase:(NSString *)database1{
sqlite3_stmt *statement = nil ;
NSString *path = [self GetDatabasePath:database1];
NSMutableArray *alldata;
alldata = [[NSMutableArray alloc] init];
if(sqlite3_open([path UTF8String],&database) == SQLITE_OK )
{
NSString *query = sql;
if((sqlite3_prepare_v2(database,[query UTF8String],-1, &statement, NULL)) == SQLITE_OK)
{
while(sqlite3_step(statement) == SQLITE_ROW)
{
NSMutableDictionary *currentRow = [[NSMutableDictionary alloc] init];
int count = sqlite3_column_count(statement);
for (int i=0; i < count; i++) {
char *name = (char*) sqlite3_column_name(statement, i);
char *data = (char*) sqlite3_column_text(statement, i);
NSString *columnData;
NSString *columnName = [NSString stringWithCString:name encoding:NSUTF8StringEncoding];
if(data != nil)
columnData = [NSString stringWithCString:data encoding:NSUTF8StringEncoding];
else {
columnData = #"";
}
[currentRow setObject:columnData forKey:columnName];
}
[alldata addObject:currentRow];
}
}
sqlite3_finalize(statement);
}
sqlite3_close(database);
return alldata;
}
-(void*) inseryQuery:(NSString *) insertSql forDatabase:(NSString *)database1{
sqlite3_stmt *statement = nil ;
NSString *path = [self GetDatabasePath:database1];
if(sqlite3_open([path UTF8String],&database) == SQLITE_OK )
{
if((sqlite3_prepare_v2(database,[insertSql UTF8String],-1, &statement, NULL)) == SQLITE_OK)
{
if(sqlite3_step(statement) == SQLITE_OK){
}
}
sqlite3_finalize(statement);
}
sqlite3_close(database);
return insertSql;
}
NSString *sql = #"select * from Location";
const location = [[TDatabase shareDataBase] getAllDataForQuery:sql forDatabase:#"journeydatabase.sqlite"];//1
NSString* insertSql = [NSString stringWithFormat:#"insert into Location values ('city','name','phone')"];//2
const insert =[[TDatabase shareDataBase] inseryQuery:insertSql forDatabase:#"journeydatabase.sqlite"];//3
in line no 1,2,3 I get the same error:
initializer element is not constant
What might be the problem?
#rani writing your own methods to deal with sqlite database is very painstaking. You should use fmdb wrapper class or use core data. I personally prefer fmdb. Initially I was doing the same way you were. I found about fmdb here. After using it I had to write very little code whenever I have to deal With sqlite db.
I find this link everywhere for SQLite sample code (http://developer.apple.com/library/ios/#samplecode/SQLiteBooks/index.html) but either it has been removed or changed to another location.. I couldn't find it in google searches.. Does anyone know any other link to the code or any other good sample code for SQLite?
May be this is useful to you.
http://www.switchonthecode.com/tutorials/using-sqlite-on-the-iphone
http://dblog.com.au/iphone-development-tutorials/iphone-sdk-tutorial-reading-data-from-a-sqlite-database/
http://www.icodeblog.com/2008/08/19/iphone-programming-tutorial-creating-a-todo-list-using-sqlite-part-1/
You can use this class and send query in this class and get all functionality of sqlite using this class
.h
#import <Foundation/Foundation.h>
#import "sqlite3.h"
#interface DBLib : NSObject {
sqlite3 *database;
NSString *path;
}
- (NSString *)getDatabasePath:(NSString*)DBName;
- (void)createEditableCopyOfDatabaseIfNeeded:(NSString*)DBName;
- (void)initializeDatabase:(NSString*)DBName;
-(NSMutableArray*)GetListBySQL:(NSString*)SQL;
-(BOOL)UpdateData:(NSMutableDictionary*)objDic :(NSString*)PrimaryKey :(NSString*)TABLE_NAME;
-(BOOL)deleteQuery:(NSString *)query;
#end
.m
#import "DBLib.h"
#implementation DBLib
#pragma mark Database methods
- (NSString *)getDatabasePath:(NSString*)DBName
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) ;
NSString *documentsDirectory = [paths objectAtIndex:0] ;
return [documentsDirectory stringByAppendingPathComponent:DBName];
}
// Creates a writable copy of the bundled default database in the application Documents directory.
- (void)createEditableCopyOfDatabaseIfNeeded:(NSString*)DBName {
// First, test for existence.
BOOL success;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:DBName];
success = [fileManager fileExistsAtPath:writableDBPath];
if (success) return;
// The writable database does not exist, so copy the default to the appropriate location.
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:DBName];
success = [fileManager copyItemAtPath:defaultDBPath toPath:writableDBPath error:&error];
if (!success) {
NSString *errString = [NSString stringWithFormat:#"%#", [#"Fail" stringByReplacingOccurrencesOfString:#"#" withString:[error localizedDescription] ]];
NSAssert1(0, #"%#", errString);
}
}
// Open the database connection and retrieve minimal information for all objects.
- (void)initializeDatabase:(NSString*)DBName {
// The database is stored in the application bundle.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
path = [documentsDirectory stringByAppendingPathComponent:DBName];
NSStringEncoding enc = [NSString defaultCStringEncoding];
// Open the database. The database was prepared outside the application.
if (sqlite3_open([path UTF8String], &database) == SQLITE_OK)
{
//TRUE
NSLog(#"Successfully opened-sqlite3");
}
else
{
// Even though the open failed, call close to properly clean up resources.
sqlite3_close(database);
NSLog(#"closed");
NSString *errString = [NSString stringWithFormat:#"%#", [#"Fail" stringByReplacingOccurrencesOfString:#"#" withString:[NSString stringWithCString:sqlite3_errmsg(database) encoding:enc] ]];
NSAssert1(0, #"%#", errString);
// Additional error handling, as appropriate...
}
}
-(NSMutableArray*)GetListBySQL:(NSString*)SQL
{
[self initializeDatabase:#"DBNAME"];
NSMutableArray* Array;
Array=[[NSMutableArray alloc]init];
NSStringEncoding enc = [NSString defaultCStringEncoding];
sqlite3_stmt *select_statement=nil;
if (sqlite3_prepare_v2(database, [SQL UTF8String], -1, &select_statement, NULL) != SQLITE_OK) {
NSString *errString = [NSString stringWithFormat:#"%#", [#"Fail" stringByReplacingOccurrencesOfString:#"#" withString:[NSString stringWithCString:sqlite3_errmsg(database) encoding:enc] ]];
NSAssert1(0, #"%#", errString);
}
int columncount=sqlite3_column_count(select_statement);
NSMutableDictionary* dic;
while (sqlite3_step(select_statement) == SQLITE_ROW)
{
dic=[[NSMutableDictionary alloc]init];
for(int j=0;j<columncount;j++)
{
if(sqlite3_column_text(select_statement, j)!=nil)
[dic setObject:[NSString stringWithUTF8String:(char *)sqlite3_column_text(select_statement, j)] forKey:[NSString stringWithUTF8String:(char *)sqlite3_column_name(select_statement,j)]];
else
[dic setObject:#"" forKey:[NSString stringWithUTF8String:(char *)sqlite3_column_name(select_statement,j)]];
}
[Array addObject:dic];
[dic release];
}
sqlite3_finalize(select_statement);
NSMutableArray *arr = [[NSMutableArray alloc] initWithArray: Array];
[Array release];
return arr;
}
//Method for Datbase
-(BOOL)UpdateData:(NSMutableDictionary*)objDic :(NSString*)PrimaryKey :(NSString*)TABLE_NAME
{
NSAutoreleasePool* pool=[[NSAutoreleasePool alloc]init];
[self initializeDatabase:DBNAME];
NSString* SQLColumns=#"";
NSString* SQLValues=#"";
NSString* SQL=#"";
//Chekc Wheather Insert or update?
BOOL IsNew=NO;;
if([[objDic valueForKey:PrimaryKey] intValue]==0)
{
IsNew=YES;
}
NSArray* Keys=[objDic allKeys];
NSLog(#"%#",Keys);
if(IsNew)
{
for(int i=0;i<Keys.count;i++)
{
if(![[Keys objectAtIndex:i] isEqual:PrimaryKey])
{
SQLColumns=[NSString stringWithFormat:#"%#%#,",SQLColumns,[Keys objectAtIndex:i]];
SQLValues=[NSString stringWithFormat:#"%#?,",SQLValues];
}
}
if([SQLColumns length]>0)
{
SQLColumns=[SQLColumns substringToIndex:[SQLColumns length]-1];
SQLValues=[SQLValues substringToIndex:[SQLValues length]-1];
}
SQL=[NSString stringWithFormat:#"INSERT INTO %# (%#) Values(%#)",TABLE_NAME,SQLColumns,SQLValues];
}
else
{
for(int i=0;i<Keys.count;i++)
{
if(![[Keys objectAtIndex:i] isEqual:PrimaryKey])
{
SQLColumns=[NSString stringWithFormat:#"%#%#=?,",SQLColumns,[Keys objectAtIndex:i]];
}
}
if([SQLColumns length]>0)
{
SQLColumns=[SQLColumns substringToIndex:[SQLColumns length]-1];
}
SQL=[NSString stringWithFormat:#"UPDATE %# SET %# WHERE %#=?",TABLE_NAME,SQLColumns,PrimaryKey];
//NSLog(sql);
}
sqlite3_stmt *insert_statement=nil;
if (sqlite3_prepare_v2(database, [SQL UTF8String], -1, &insert_statement, NULL) != SQLITE_OK) {
//NSAssert1(0, #"Error: failed to prepare statement with message '%s'.", sqlite3_errmsg(database));
NSLog(#"Error: failed to prepare statement with message '%s'.", sqlite3_errmsg(database));
}
int intBindIndex=1;
for(int i=0;i<Keys.count;i++)
{
if(![[Keys objectAtIndex:i] isEqual:PrimaryKey])
{
sqlite3_bind_text(insert_statement,intBindIndex,[[objDic valueForKey:[Keys objectAtIndex:i]] UTF8String],-1, SQLITE_STATIC);
intBindIndex++;
}
}
if(!IsNew)
{
sqlite3_bind_text(insert_statement,Keys.count,[[objDic valueForKey:PrimaryKey] UTF8String],-1, SQLITE_STATIC);
}
int result;
result=sqlite3_step(insert_statement);
if(IsNew)
{
[objDic setObject:[NSString stringWithFormat:#"%d",sqlite3_last_insert_rowid(database)] forKey:PrimaryKey];
}
sqlite3_finalize(insert_statement);
[pool release];
NSLog(#"result:%d",result);
if(result==SQLITE_DONE)
return YES;
else
return NO;
}
-(BOOL)deleteQuery:(NSString *)query
{
NSAutoreleasePool* pool=[[NSAutoreleasePool alloc]init];
[self initializeDatabase:DBNAME];
NSString* SQL=#"";
SQL=[NSString stringWithString:query];
sqlite3_stmt *insert_statement=nil;
if (sqlite3_prepare_v2(database, [SQL UTF8String], -1, &insert_statement, NULL) != SQLITE_OK) {
//NSAssert1(0, #"Error: failed to prepare statement with message '%s'.", sqlite3_errmsg(database));
NSLog(#"Error: failed to prepare statement with message '%s'.", sqlite3_errmsg(database));
}
int result;
result=sqlite3_step(insert_statement);
sqlite3_finalize(insert_statement);
[pool release];
NSLog(#"result:%d",result);
if(result==SQLITE_DONE)
return YES;
else
return NO;
}
#end
I'm using the code below to populate an array from my ManagedObjectContext, but what I would like to do is to fetch only the unique ID numbers of each row matching my query (itemType = 1) and populate the fetchResults array with only these unique ID numbers. Is that possible?
Any help is appreciated.
lq
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:#"MyAppName"
inManagedObjectContext:[self managedObjectContext]]];
NSError *error = nil;
NSPredicate *predicate;
NSArray *fetchResults;
predicate = [NSPredicate predicateWithFormat:#"(itemType = %i)", 1];
[request setPredicate:predicate];
fetchResults = [managedObjectContext executeFetchRequest:request error:&error];
if (!fetchResults) {
// NSLog(#"no fetch results error %#", error);
}
self.mutableArrayName = [NSMutableArray arrayWithArray:fetchResults];
[request release];
To help anyone with similar needs, I'm answering my own question. I figured out a solution that works for pulling specific row and/or column data from my SQLite database in query form, rather than using Fetch with Predicate. (Note: code shows examples for extracting string and integer data types.)
First, add a Framework for libsqlite3.0.dylib
In the header add the following file:
#import <sqlite3.h>
#interface MyViewController : UIViewController {
NSMutableArray *dataArray; // This array will hold data you will extract
NSArray *summaryArray; // This holds an array of PKIDs that will be queried
}
#property (nonatomic, retain) NSMutableArray *dataArray;
#property (nonatomic, assign) NSArray *summaryArray;
- (void)getData:(NSInteger *)intPKID;
- (NSString *) getDBPath;
#end
In the implementation file add the following:
static sqlite3 *database = nil; // add this before the #implementation line
#synthesize dataArray;
#synthesize summaryArray;
- (NSString *) getDBPath {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
return [documentsDir stringByAppendingPathComponent:#"MyDatabaseName.sqlite"];
}
- (void)getData:(NSInteger *)intPKID {
NSString *dbPath = [self getDBPath];
if (sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK) {
NSString *strSQL;
NSString *strExtractedData;
NSUInteger count;
NSInteger intPK;
if (self.dataArray == nil) {
self.dataArray = [[[NSMutableArray alloc] init] autorelease];
} else {
[self.dataArray removeAllObjects];
}
count = [self.summaryArray count];
for (NSUInteger i = 0; i < count; ++i) {
// Extract a specific row matching a PK_ID:
strSQL = [NSString stringWithFormat: #"select intPKID, strColumnName from MyDatabaseName where (PKID = %i)", [[self.summaryArray objectAtIndex:i]intValue]];
// Extract a range of rows matching some search criteria:
// strSQL = [NSString stringWithFormat: #"select intPKID, strColumnName from MyDatabaseName where (ITEMTYPE = '%i')", 1];
const char *sql = (const char *) [strSQL UTF8String];
sqlite3_stmt *selectstmt;
if(sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL) == SQLITE_OK) {
while(sqlite3_step(selectstmt) == SQLITE_ROW) {
[self.dataArray addObject:[NSNumber numberWithInt:qlite3_column_int(selectstmt, 0)]];
[self.dataArray addObject:[NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 1)]];
}
}
}
} else {
sqlite3_close(database); // Database not responding - close the database connection
}
}
predicate = [NSPredicate predicateWithFormat:#"itemType == 1"];
or
predicate = [NSPredicate predicateWithFormat:#"(itemType == %i)", 1];
should both work.