Error copying file from app bundle - ios

I used the FireFox add-on SQLite Manager, created a database, which saved to my desktop as "DB.sqlite". I copied the file into my supporting files for the project. But when I run the app, immediately I get the error
"Assertion failure in -[AppDelegate copyDatabaseIfNeeded], /Users/Mac/Desktop/Note/Note/AppDelegate.m:32 2014-08-19 23:38:02.830
Note[28309:60b] Terminating app due to uncaught exception
'NSInternalInconsistencyException', reason: 'Failed to create writable
database file with message 'The operation couldn’t be completed.
(Cocoa error 4.)'.' First throw call stack: "...
Here is the App Delegate Code where the error takes place
-(void) copyDatabaseIfNeeded
{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSString *dbPath = [self getDBPath];
BOOL success = [fileManager fileExistsAtPath:dbPath];
if (!success)
{
NSString *defaultDBPath = [[ [NSBundle mainBundle
] resourcePath] stringByAppendingPathComponent:#"DB.sqlite"];
success = [fileManager copyItemAtPath:defaultDBPath toPath:dbPath error:&error];
if (!success)
NSAssert1(0, #"Failed to create writable database file with message '%#'.", [error localizedDescription]);
}
}
I am very new to Sqlite, so I maybe I didn't create a database correctly in the FireFox Sqlite manager, or maybe I didn't "properly" copy the .sqlite file in? (I did check the target membership in the sqlite and it correctly has my project selected. Also, the .sqlite file names all match up perfectly.)

In iOS, you can't write a file in your app's bundle. The entire bundle is read-only.
You should create the database (sqlite file) inside the NSDocumentDirectory in order to work on it.
Please visit site below for tutorial:
http://objectivecwithsuraj.blogspot.in/2012/10/database-implementation-using-sqlite-in.html
Sample Code:
https://github.com/surajwebo/SQLite-Demonstration-

Related

Issues writing files on iOS

I'm fighting with the following error NSCocoaErrorDomain 513 reported by a very small number of users:
Unable to create directory at path /var/mobile/Containers/Data/Application/EBE2C5D8-5AEC-4D62-9393-B19CAD598FE5/Documents/documents/FF2F88FB-2C07-4FA3-988E-58AD5C21F659/9A02F8A0-74EB-4ED6-81B6-4F40653856D3.
Error: Error Domain=NSCocoaErrorDomain Code=513 "You don’t have permission to save the file “9A02F8A0-74EB-4ED6-81B6-4F40653856D3” in the folder “FF2F88FB-2C07-4FA3-988E-58AD5C21F659”."
UserInfo={
NSFilePath=/var/mobile/Containers/Data/Application/EBE2C5D8-5AEC-4D62-9393-B19CAD598FE5/Documents/documents/FF2F88FB-2C07-4FA3-988E-58AD5C21F659/9A02F8A0-74EB-4ED6-81B6-4F40653856D3,
NSUnderlyingError=0x15e09de00 {
Error Domain=NSPOSIXErrorDomain
Code=13 "Permission denied"
}
}
This error means that the directory cannot be created because of a permission error. That's where I'm lost as the only reason I can see would be if I'm creating a file outside of my app's sandbox.
The code generating this error:
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString* documentsDirectory = [paths objectAtIndex:0];
NSString *directory = [documentsDirectory stringByAppendingPathComponent:documentsPathAndUUIDs];
NSError *error = nil;
if (![[NSFileManager defaultManager] createDirectoryAtPath:directory
withIntermediateDirectories:YES
attributes:nil
error:&error]) {
NSError(#"Unable to create directory at path %#. Error: %#", directory, error);
}
A couple things worth noting:
This path isn't saved, it's regenerated every time, so it's not as if the app container had changed between installs;
The users seem to have available disk space;
This affects at least iOS 9 (I don't have enough reports to know if it also affects iOS 10)
Would anyone have a hint of why this could happen?
Do you have sudo/chown privileges on /var? If not and you're running an OS post Mavericks, you may need to restart in safety mode and disable CSRUtil
Documentation on CSRUtil

Sqlite Copied issue

I have created a SQLite file using FireFox sqliteManager and imported it to my application.
I need to copy this SQLite file from bundle to document directory. By using the below code, I am able to copy the SQLite file to document directory.
fIlMan=[NSFileManager defaultManager];
data=[fIlMan contentsAtPath:[[NSBundle mainBundle]pathForResource:#"mydatabase" ofType:#"sqlite"]];
pAth=[[[NSBundle mainBundle]resourcePath]stringByAppendingPathComponent:#"localDBFile"];
NSLog(#"%.2f",(float)data.length/1024.0f/1024.0f);
if ([fIlMan fileExistsAtPath:pAth]==NO) {
[fIlMan createFileAtPath:pAth contents:data attributes:Nil];
}
if (sqlite3_open([pAth UTF8String], &newDB)==SQLITE_OK) {
NSLog(#"DataBase successfully Created");
}
else{
NSLog(#"DataBase Failed to Create");
}
sqlite3_close(newDB);
Now if I run it in simulator its fine(nicely working). When I run this same on device, the application will terminate and show the warning as
Terminated due to memory pressure
Guidance needed on this. Thanks.
Use the copyItemAtPath:toPath:error: method of the file manager so that the file isn't loaded into memory.
Also, be careful about the destination path as [[[NSBundle mainBundle]resourcePath]stringByAppendingPathComponent:#"localDBFile"] is not a suitable way to get the document directory. Instead you should be using NSSearchPathForDirectoriesInDomains or URLsForDirectory:inDomains:.

App does not store any content in document directory but Appstore reject

I am new to iOS development. My app got rejected from the review, stating the following reason,
2.23 Apps must follow the iOS Data Storage Guidelines or they will be rejected
We found that your app does not follow the iOS Data Storage Guidelines, which is required per the App Store Review Guidelines.
I am not storing my DB file in documents directory. Here's my code,
NSString *libraryPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) lastObject];
NSString *path = [libraryPath stringByAppendingPathComponent:#"DatabaseFolder"];
NSURL *pathURL = [NSURL fileURLWithPath:path];
BOOL isDirectory = NO;
if ([[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&isDirectory]) {
if (isDirectory) {
return pathURL;
} else {
// Handle error. ".data" is a file which should not be there...
[NSException raise:#"'Private Documents' exists, and is a file" format:#"Path: %#", path];
}
}
NSError *error = nil;
if (![[NSFileManager defaultManager] createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:&error]) {
[NSException raise:#"Failed creating directory" format:#"[%#], %#", path, error];
}
return pathURL;
How to reproduce a crash or bug that only App Review or users are seeing?
The iOS Data Storage guideline document (login required to view) says,
Everything in your app’s home directory is backed up, with the exception of the application bundle itself, the caches directory, and temp directory.
This means even your NSLibraryDirectory directory contents gets backed up to iCloud. To resolve this you have following options,
Use the /tmp directory for storage
Use the /Caches directory for storage
Only use the /Documents directory for user-generated content that cannot be re-created.
Set the do not backup attribute on the file using setResourceValue:forKey:error: method of NSURL.
Here is how you can mark a resource for not backing up to iCloud.
- (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL
{
assert([[NSFileManager defaultManager] fileExistsAtPath: [URL path]]);
NSError *error = nil;
BOOL success = [URL setResourceValue: [NSNumber numberWithBool: YES]
forKey: NSURLIsExcludedFromBackupKey error: &error];
if(!success){
NSLog(#"Error excluding %# from backup %#", [URL lastPathComponent], error);
}
return success;
}
Hope that helps!
I assume the reviewer doesn't like that you are storing the database in the library folder and there within one created by you. If you read the mentioned guidelines you'll see that you shouldn't store there.
Data that can be downloaded again or regenerated should be stored in the /Library/Caches directory. Examples of files you should put in the Caches directory include database cache files and downloadable content, such as that used by magazine, newspaper, and map applications
I had this problem for a while also. So I made a class to handle this for me. There are different rules of where you can store stuff in different OS's. So my class checked the OS and returned a proper data director for each one and even handled the migration of data from one location to the other if the OS was updated.
But pretty much today you could just support the 5.1 and up location and be fine.
The key is that you need to set your do not backup attribute also.
I just put in a github here: https://github.com/badweasel/BWFileManager

How to add a .sql file to sqlite db in Xcode [duplicate]

This question already has answers here:
How should I specify the path for an sqlite db in an iPhone project?
(3 answers)
Closed 9 years ago.
I am writing a offline iPhone app in which I need to read and display from a database which consists of a few number of tables. The tables have over 100k entries in it, so it is almost impossible to enter it all individually. I have downloaded the .sql file of the entire db. Now how can I import the db as such into sqlite/Xcode so that I can readily start accessing the data in it??
Edit: I have seen that when using a database, the file extension that is used is a .db file. Is there anyway I can convert the .sql file to a .db file. And if I can do that, can I simply access the .db file by placing it in the project directory?
If you have created the .sqlite file and have the tables in it,Then add the .sqlite file into xcode like just drag from desktop into your bundle(Resources).And then use NSFileManager to access the sqlite file.You need to write methods for createdatabase and initialize database and also you can see the sqlite file in your documents folder/simulator folder.
- (void)createEditableCopyOfDatabaseIfNeeded {
NSLog(#"Checking for database file");
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSString *dbPath = [self getDBPath];
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"ihaikudb.sql"];
BOOL success = [fileManager fileExistsAtPath:dbPath];
NSLog(#"If needed, bundled default DB is at: %#",defaultDBPath);
if(!success) {
NSLog(#"Database didn't exist... Copying default from resource dir");
success = [fileManager copyItemAtPath:defaultDBPath toPath:dbPath error:&error];
if (!success)
NSAssert1(0, #"Failed to create writable database file with message '%#'.", [error localizedDescription]);
} else {
NSLog(#"Database must have existed at the following path: %#", dbPath);
}
NSLog(#"Done checking for db file");
}

is it OK to handle a Core Data database created with from an UIManagedDocument with NSFileManager?

I'm making an app which uses Core Data, and for the purpose of my app I need to bundle a pre-populated database with the app bundle.
I'm using a UIManagedDocument
For this, I created the database with the app and later loaded the data. Then I searched the iOS Simulator folder in my Mac and drag and dropped the persistentStore file into the app bundle.
Later in the code I copied it to the NSDocumentDirectory because the user will be allowed to edit the database at runtime. This was done with the following method:
if(![[NSFileManager defaultManager] fileExistsAtPath:[self.appDatabase.fileURL path]])
{
// COPY FROM BUNDLE
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *DB = [[paths lastObject] stringByAppendingPathComponent:#"Default App Database"];
DB = [DB stringByAppendingPathComponent:#"StoreContent"];
[fileManager createDirectoryAtPath:DB withIntermediateDirectories:YES attributes:nil error:&error];
NSLog(#"create directory error: %#",error);
DB = [DB stringByAppendingPathComponent:#"persistentStore"];
NSString *shippedDB = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"persistentStore"];
NSLog(#"%d",[fileManager fileExistsAtPath:shippedDB]);
[fileManager copyItemAtPath:shippedDB toPath:DB error:&error];
NSLog(#"Copy error %#",error);
}
Everything is working perfectly! But, I'm not sure if this will generate some type of error. So my question, is it OK to handle a Core Data database created with from an UIManagedDocument with NSFileManager?
And, will Apple complain in the review process for bundling the persistentStore file?
Bundling a default persistent store with the app is explicitly mentioned in the "Core Data Programming Guide":
How do I initialize a store with default data?
...
You can create a separate persistent store that contains the default
data and include the store as an application resource. When you want
to use it, you must either copy the whole store to a suitable
location, or copy the objects from the defaults store to an existing
store.

Resources