Sqlite Prepare Failed: No such table <table_name> - iphone

I am using Sqlite database in my iphone app.
Here in my app i initially used a absolute path like #"/Users/macos/Documents/appdatabase.sql
Now here I want to run the app on the device. It requires the relative path.
What needs to be done to get that path for the database ?
Here I am getting this error when i try to run with the absolute path on the device.
Sqlite Prepare Failed: No such table
I have checked that table already exist in my database.
What should I do to get the relative path for the database?
Please Help and Suggest.
Thanks

You can get the database path using this -
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
NSString *databasePath = [documentsDir stringByAppendingPathComponent:#"mydb.sqlite"];
also delete your app from simulator or device and run/install it again.

Related

Remove file - Read only file from device

I create a file with attribute NSFileappendonly, i am thinking this is enough to create readonly file in ios.My problem is try to remove the file from device it returns error.Please anyone help me..
A 513 states you do not have permission to write to that folder NSFileWriteNoPermissionError. You need to make sure you are only trying to write to one of the 3 folders in your app's dir (Documents, Temp, or Cache). Generally you use the Documents folder. (Trying to write directly to the main bundle can cause the error you are having)
iOS Environment
You can remove a file with NSFileManager but only if your app is signed and you are attempting to remove from one of the 3 allowed folders. Those 3 folders are only accessible by your app.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectoryPath = [paths objectAtIndex:0];
NSString *yourFile = [documentsDirectoryPath stringByAppendingPathComponent:#"yourFile.txt"];
NSFileManager *fileManager = [NSFileManager defaultManager];
[fileManager removeItemAtPath:yourFile error:NULL];

default document directory changes after deleting, re running the application in xcode.

I am not sure if it is the expected behavior.
I have xcode 4.3.2, and running an application, where in i get the default Document directory by the following code.
NSArray *dirPaths;
NSString *docsDirectory;
NSString *databasePath;
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDirectory = [dirPaths objectAtIndex:0];
databasePath = [[NSString alloc] initWithString: [docsDirectory stringByAppendingPathComponent: DBNAME]];
const char *dbpath = [databasePath UTF8String];
NSFileManager *filemgr = [NSFileManager defaultManager];
if ([filemgr fileExistsAtPath:databasePath] == NO) {
NSLog (#" GETDBPATHNAME: database file does not exist");
}
else {
NSLog (#" GETDBPATHNAME: Database File EXISTS");
}
Use Cases:
1) I run the application each time in xcode the path is same.
2) Reboot the device, and re run the application in xcode, also the path is same.
3) BUT WHEN I DELETE THE APPLICATION, AND RE-RUN IN THE PATH DIFFERS. How it is possible?
What get the path something like:
/var/mobile/Applications/xxxxxxx-xxx-xxxx-xxx-xxxxxxxxxxx/Documents/
The value xxxxxxx-xxx-xxxx-xxx-xxxxxxxxxxx claimed to be a Phone UUID. How it is different each time?
Your help is much appreciated.
Each application has a UNIQUE document directory.
When you delete an APP the document directory is also get deleted. Then when you install the same application. The iOS generates another directory for the APP. It never use the previous directory name for this purpose.
Whenever you delete and reinstall the application this path changes.
xxxxxxx-xxx-xxxx-xxx-xxxxxxxxxxx is not the phone UUID otherwise this path would have been the same for every application. Further More this path is also changed when you update your application on the app store.
So the solution to avoid this problem is to save the path after /Documents Directory and use
stringByAppendingPathComponent:
after the path to the Documents Directory to get the full path. In this way you would not have any problem regarding the path of the resource.

About NSSearchPathForDirectoriesInDomains

I hv spent quite a while but no luck on following question:
I tried to access Document directory.
Both following codes work perfectly. Could someone tell me whats the difference between
last object and objectAtIndex:0
NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentPath = [searchPaths lastObject];
or
NSString *documentPath = [searchPaths objectAtIndex:0];
The most close question was How to get URL for application's document directory iPhone, but it didn't explain the difference between lastObject and objectAtIndex:0.
I have read thru Apple Developer Library. It only says 'The directory returned by this method may not exist. This method simply gives you the appropriate location for the requested directory. Depending on the application’s needs, it may be up to the developer to create the appropriate directory and any in between.' Someone please help, thx.
In this case, there is no difference between [searchPaths lastObject] and [searchPaths objectAtIndex:0], because searchPaths contains only one entry. The user domain only contains one document directory.
If you try this you'll get different results:
NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(
NSApplicationDirectory, NSAllDomainsMask, YES);
searchPaths may contain more than one directory if you look with NSAllDomainsMask.
Since Xcode 5, best practice is:
NSString *documentPath = [searchPaths firstObject];

How to add existent database into my app in iphone sdk

I have to add an existent DB into my iphone app
I' ve tried to put it into the project's folder and used this init function
-(id) initDatabase{
databaseName = #"mydatabase.sqlite";
// Get the path to the documents directory and append the databaseName
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
databasePath = [documentsDir stringByAppendingPathComponent:databaseName];
[databasePath retain];
return self;
}
and then i used this function
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK){ //inserting methods
but I have an error: the table 'nametable' does not exists, I am sure that this table exists and I think that these methods create a new db file into the device path.
You can't have any files in the documents folder to start. Everything that comes with the app has to be included in the app bundle. The first time the app runs, the documents folder is always empty.
You need to locate the file inside the app bundle using NSBundle's pathForResource:ofType:.
If the DB is readonly, you can just leave it there. If it is readwrite, you need to copy the file into the documents or library folder the first time the app launches.
Update:
could you make an example about using
'NSBundle's pathForResource:ofType:'
please?I'm sorry but I'm new to iphone
sdk
It's just:
NSString *path=[[NSBundle mainBundle] pathForResource:#"myDatabase" ofType:#"sqlite"];
In the sidebar, check "Targets" => (Your Target) => "Copy Bundle Resources". I think your database file might not have been copied because Xcode has no idea what file type that is.

How can i change sqlite ReadOnly to ReadWrite on the iPhone?

i deployed my App to my iPhone and get
Unknown error calling sqlite3_step (8: attempt to write a readonly database) eu
on Insert / Update Statements.
On the Simulator it all works like it should.
My sqlite Database is placed in the Resource Folder (Xcode).
Thanks for help!
Your application bundle is not writable on the iPhone. You MUST copy the file somewhere else, like your documents folder. It works in the simulator because the Mac does not enforce all the sandboxing restrictions the iPhone does.
You can copy your database from the application bundle directory to the Documents directory in viewDidLoad. You can read/write from/to your database in the Documents directory after this. Of course, you need to check if the database in the Documents directory exist before you do the copy in order not to overwrite it the next time you bring up the app.
Assuming you have defined your database name '#define kFilename #"yourdatabase.db"' in the .m file.
In viewDidLoad add:
// Get the path to the main bundle resource directory.
NSString *pathsToReources = [[NSBundle mainBundle] resourcePath];
NSString *yourOriginalDatabasePath = [pathsToResources stringByAppendingPathComponent:kFilename];
// Create the path to the database in the Documents directory.
NSArray *pathsToDocuments = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [pathsToDocuments objectAtIndex:0];
NSString *yourNewDatabasePath = [documentsDirectory stringByAppendingPathComponent:kFilename];
if (![[NSFileManager defaultManager] isReadableFileAtPath:yourNewDatabasePath]) {
if ([[NSFileManager defaultManager] copyItemAtPath:yourOriginalDatabasePath toPath:yourNewDatabasePath error:NULL] != YES)
NSAssert2(0, #"Fail to copy database from %# to %#", yourOriginalDatabasePath, yourNewDatabasePath);
}
Good luck!
aobs