Using SQLite with iOS... very beginner program - ios

I am attempting to write an application in which I have two text fields that I will be using for input. The input taken from the text fields are being initialized as a string. So what I want to accomplish is:
Create an SQLite database (file) that will be saved within the Xcode project (I'm not sure where it can be saved to, but I would need to be able to read it and write to it).
I then want to place the strings (from the text field inputs) into the SQLite table, which will only have two fields (for simplicity). I'm using a button to accept the input from the text fields, place the input into strings, and then put the value of the strings into a label(s).
I ultimately will want to place the strings from the text fields into the table, and then read the table to "grab" the strings and display them into the labels. All of this would be done by the click of a button.
I realize this is very specific, but I have been having a difficult time finding anything simple to accomplish this. I am very new to iOS development and I appreciate if anyone could be as specific and detailed as possible, or at least point me to some resources that would teach me how to accomplish this.
I am using Xcode v4.3.2 and I do not use Storyboard or ARC. I tried to be as detailed as possible, but as you can, my goal is really simple.
I'm tapped out and I appreciate all the help I can get.
Thanks!
-Matt

creating a database file: simply drop your data.sqlite file in your xcode project, as you drop any other class or image resource. Please note, that you will have to copy the file to writeable directory after app installation. take a look at createeditablecopyofdatabaseifneeded.
open your database with sqlite3_open with respect to your new database location.
query the database as you like with sqlite3_prepare_v2
a simple query snippet looks like:
NSString *querystring;
// create your statement
querystring= [NSString stringWithFormat:#"SELECT text1, text2 FROM datatable;"];
const char *sql = [querystring UTF8String];
NSString *text1 = nil;
NSString *text2 = nil;
if (sqlite3_prepare_v2(db, sql, -1, &statement, NULL)!=SQLITE_OK){
NSLog(#"sql problem occured with: %s", sql);
NSLog(#"%s", sqlite3_errmsg(db));
}
else
{
// you could handle multiple rows here
while (sqlite3_step(statement) == SQLITE_ROW) {
text1 = [NSString stringWithUTF8String:(char*)sqlite3_column_text(statement, 0)];
text2 = [NSString stringWithUTF8String:(char*)sqlite3_column_text(statement, 1)];
} // while
}
sqlite3_finalize(statement);
// go on with putting data where you want

There is an example project for using SQLite here you can refer to: https://github.com/AaronBratcher/ABSQLite
It has classes for accessing SQLite in a more traditional database way. The sample project uses SQL to create the tables and shows how you can change the schema over different versions of your app.

Related

How to use two sqlite database files in single iOS project with simultaneously fetch data from both Database

My requirement is to add two SQLite database files in my project. I know that is possible. But how can I access two database files simultaneously?
One more thing currently I am using FMDB to manipulate database operation.
Note : Both of my DB file sizes are near about 1GB each. so also want to know that if I use 2 DB file so is there any memory issue will occur in my application ?
Thanks.
Generally, there is rare requirement of 2 Database files in a single project specially in iOS where we have used only one DB.
But as per your requirement, we can use multiple Database files in a single project with multiple Database instances.
To Create 2 instance use below code for SQLite Native:
//Create Object of DataBase
static sqlite3 *databaseOne = nil;
static sqlite3 *databaseTwo = nil;
//Open Both Databases while we needed in our project
//Open First Database
sqlite3_open([path UTF8String], &databaseOne);
//Opne Second Database
sqlite3_open([path UTF8String], &databaseTwo);
//prepare for statement execution
sqlite3_prepare_v2(databaseOne, [sql UTF8String], -1, &stmt, NULL)
sqlite3_prepare_v2(databaseTwo, [sql UTF8String], -1, &stmt, NULL)
But make sure you will not mix these 2 objects while executing.
Note: Close both connections while your DB task is done.
To Create 2 instance with FMDB use below code:
//First DB
FMDatabase *dbOne = [FMDatabase databaseWithPath:<your first DB file Path>];
[dbOne open];
//Do Your DB task
[dbOne close];
//Second DB
FMDatabase *dbTwo = [FMDatabase databaseWithPath:<your second DB file Path>];
[dbTwo open];
//Do Your Second DB task
[dbTwo close];
Hope this will help you.

Delete row of mySQL table from iOS app [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I'm currently working on an iOS app that takes information from a mySQL database and outputs it to JSON which in turn is displayed in a UITableView. I would like to be able to delete a row of the UITableView, which would also delete the corresponding row in the database. I know I need to use this function:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
[_wordsArray removeObjectAtIndex:indexPath.row];
[self.editTableView reloadData];
}
I'm not sure how it works, I know I'll have to use a PHP script in order for the row to be deleted from the database. What needs to be done on the iOS side? Can anyone point me in the right direction?
Thanks in advance.
What needs to be done on the iOS side?
This is a pretty broad question. You have to be more specific what you need help with.
Generally speaking this is what needs to be done which I am sure you already knew.
Delete the record from your array and reload the table. I see you have already done that.
I am assuming you are storing that array locally somewhere (NSUserDefaults, plist etc), otherwise the user will need to get latest data from your server on every app launch and make sure the delete row doesn't reappear
You need to make a Async call to your php on your server
You would need to pass in values like what info has the user decided to delete and then execute that delete in the database
If you need code samples then google it my man.
Doing the same, kinda, using a mySQL database to save my data and using arrays to access the tables on the iOS level. What I do for inserting, updating and deleting records from the database is something like this:
Using mySQL on a iOS Level ##
mySQL to iOS level: first is to create a method, or inline function, somewhere that is accessible anywhere in the app; inside a singleton for an example. This method will return an array that contains one record by passing a sqlite3_statement in the parameter list. This method looks something like:
example
/**
* From the parameter list, an array is produced in Entry format
* #param [in] statement incoming value from previous call sqlite3_step(..) == SQLITE_ROW
* #return NSArray: Entry format
*/
static inline NSMutableArray * SQLStatementRowIntoEntryEntry( sqlite3_stmt *statement) {
...
return [NSMutableArray arrayWithObjects: stringSubject, date dateCreated, stringBody, emotion, weatherCondition, temperature isBookmarked, [NSMutableDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt: sqlite3_column_int( statement, SQL_ENTRIES_id)], #"id", nil], nil];
};
How I save id keys from the mySQL record is put it in a dictionary as the last object, so it kinda stays out of the way while I'm using the array on the iOS level. But then is there ready whenever I want to update or delete this record from the database.
Updating and Deleting Records from iOS level: so because the id was saved in the array for each record this makes it remarkably easy to update or delete records in the database. In your query you'd have something like:
NSString *sqlStatement = [NSString stringWithFormat: #"UPDATE Entries SET subject = \"%#\", date = \"%#\", dateCreated = \"%#\", body = \"%#\", emotion = %d, weatherCondition = %d, temperature = %d, isBookmarked = %d, diaryID = %d where id = %d;", [[arrayEntry objectEntry_subject] stringByReformatingForSQLQuries], [dateFormatter stringFromDate: [arrayEntry objectEntry_date]], [dateFormatter stringFromDate: [arrayEntry objectEntry_dateCreated]], [[arrayEntry objectEntry_body] stringByReformatingForSQLQuries], [arrayEntry objectEntry_emotion], [arrayEntry objectEntry_weatherCondition], [arrayEntry objectEntry_temperature], [arrayEntry objectEntry_isBookmarked], [[[[[arrayEntry optionsDictionary] objectForKey: #"diary"] optionsDictionary] objectForKey: #"id"] intValue], [[[arrayEntry lastObject] objectForKey: #"id"] intValue]];
What you want is the [[[arrayEntry lastObject] objectForKey: #"id"] intValue] to take place of .. where id = %d; to either update or delete a record.
I hope this helps and do ask for any questions, I copied and pasted code from my project m
You can pass the Database query string to your php Script.
NSString *sqlquery = [NSSring sringwithFormate : #"DELETE FROM tabel_name WHERE tabel_id='your_tabel_row_id'"];
In this tabel_id is the your database row id which is you want to delete and your_tabel_row_id is the identifier which help to you to delete the record from the database.

Using Sqlite3 VACUUM command on Core Data SQLite Persistent store

In our app, we are implementing sharing of partial Core Data SQLite database through network/email. In order to keep the file size small, I have implemented the below method to shrink the Core Data database.
- (void) shrinkDB
{
sqlite3 * database;
NSString * string = [shareStoreURL path];
const char * filename = [string cStringUsingEncoding:[NSString defaultCStringEncoding]];
char *errMsg;
if (sqlite3_open(filename, &database) == SQLITE_OK)
{
NSLog(#"Shrinking...");
if (sqlite3_exec(database, "VACUUM;", NULL, NULL, &errMsg) != SQLITE_OK)
{
NSLog(#"Failed execute VACUUM");
}
sqlite3_close(database);
}
}
QUESTION: The above code does shrink the database. But Apple says the implementation details of Core Data are subject to change any time. Do you think I would be safe using this method for foreseeable future? Or is there any other better solution?
The proper way to do this is by giving the NSSQLiteManualVacuumOption to the persistent store coordinator.
Snippet from documentation:
NSSQLiteManualVacuumOption
Option key to rebuild the store file,
forcing a database wide defragmentation when the store is added to the
coordinator. This invokes SQLite's VACUUM command. It is ignored by
stores other than the SQLite store. Available in OS X v10.6 and later.
Declared in NSPersistentStoreCoordinator.h.
See this: https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/CoreDataFramework/Classes/NSPersistentStoreCoordinator_Class/NSPersistentStoreCoordinator.html
How Apple structures persistent data in an SQLite database is an implementation detail which is subject to change. However, the method by which SQLite manages deleted records is independent of Apple's implementation.
That being said, the process of vacuuming a SQLite database results in rebuilding the entire database, which may have negative effects if the sqlite file is in use by a CoreData NSPersistentStoreCoordinator.
In your case, it sounds like you want to vacuum after saving changes but before sending it via email. Using the NSSQLiteManualVacuumOption option appears to only vacuum the DB when the SQLite file is initially opened.
I'd either run the above code after the file is no longer associated with a NSPersistentStoreCoordinator or use the NSSQLiteManualVacuumOption then re-open and close the file before sending it via email.
Another option is to use an external SQLite tool, such as Base on OS X, to manually vacuum files. I've also used the Firefox SQLite manager extension in the past.

iOS SQLite: Insert statement fails, can't see why

So I can create the database with no issue using the following statement for the first table:
const char *sqlStatement = "CREATE TABLE IF NOT EXISTS LIBRARY_SEARCH (SEARCH_ID INTEGER PRIMARY KEY AUTOINCREMENT, SEARCH_TERM TEXT)";
But when I go to insert a row it fails. This is how I insert the row.
NSString *insertStatement = [NSString stringWithFormat:#"INSERT INTO LIBRARY_SEARCH(SEARCH_TERM) VALUES (\"%#\")", myQuery] ;
Where myQuery is an NSString that holds the value of the searchBar.text in the app. It's a property and is of course synthesized.
So I then call this:
if ( sqlite3_exec(searchSessionDB, [insertStatement UTF8String], NULL, NULL, &insert_error) == SQLITE_OK)
Which fails. Can anyone see why?
Got it. Made a small typo in my open database statement.
For anyone who looks at this in the future, this is how the opening statement now looks (and it works fine!):
if(sqlite3_open(dbpath, &searchSessionDB) = SQLITE_OK){
Thanks to Robert Ryan for suggesting this NSLog:
NSLog(#"%s", sqlite3_errmsg(searchSessionDB));
And thanks Elpsk and H2CO3 for the wrapper/app bundle information.
I suggest you to use FMDB for query your database.
It's a wrapper to sqlite, easy to use and easy and all errors are explained better.
I'm sure you're trying to update an SQLite database located in your app bundle. You can't: you can't write to your app's own bundle. Copy the database file into the Documents or Library directory off of your app sandbox.
Other: if you're looking for an OO SQLite-wrapper, check out mine.

stringWithContentsOfFile and initWithContentsOfFile return null after several runs

I am creating an iOS app which reads in a text file and displays the contents in a UIText field.
For the 1st three consecutive runs of thee app (Restarting a new session without exiting),
the data is read in fine. However on the fourth attempt, the data returned from the file is all nulls.
I've verified the file integrity. The issue exists when using stringWithContentsOfFile or initWithContentsOfFile.
After many hours of troubleshooting, I believe the issue is somehow related to a buffer being cleared within the above mentioned methods.
Any insight regarding this issue is greatly appreciated. I've tried many things with no luck.
Here's the code I use to read in the file:
TheString = [NSString stringWithContentsOfFile:[[NSBundle mainBundle]
pathForResource:#"My_TextFile" ofType:#"txt"] encoding:NSUTF8StringEncoding error:NULL];
Here's the code I use to display certain contents of the file (The contents are placed in an array of type NSArray):
NSArray *My_Array;
My_Array= [TheString componentsSeparatedByString:#"\n"];
/* Obtain specific data to display */
DisplayedData = [My_Array objectAtIndex:M[l]-1];
:
:
/* Display the data in the view */
MyUITextView.text = DisplayedData;
/* Log the data */
NSLog(#"%#", MyUITextView.text);
On the 4th invocation of the code above, the data returned is blank and NSLOG is returning nulls
Thanks so much for any help!
Maybe I'm a little bit late with answer, but, anyway, maybe somebody will find it useful.
OK, I have also spent a day trying to figure out why my custom class for scrollable view is working 3 times and refuse at the 4-th time... I found that the problem has quite the same attributes as yours: nested NSString objects unexpectedly disappear. Though pointers point to the same address in memory, memory is already filled with quite arbitrary objects instead my NSStrings.
And I paid attention that I created these NSStrings using the following class method:
+ (id)stringWithContentsOfFile:(NSString *)path encoding:(NSStringEncoding)enc error:(NSError **)error
So, I'm not the owner of these NSStrings.
And I assumed that to be the owner can be a solution, so I created my NSStrings through alloc and
- (id)initWithContentsOfFile:(NSString *)path encoding:(NSStringEncoding)enc error:(NSError **)error
instance method.
App was repaired!

Resources