I have an iOS app which locates its database in what I believe is a fairly standard manner, viz:
+ (NSString *)dbPath
{
NSArray *a =
NSSearchPathForDirectoriesInDomains(NSCachesDirectory,
NSUserDomainMask, YES);
NSString *dir = [a objectAtIndex:0];
return [dir stringByAppendingPathComponent:[self dbFile]];
}
Here dbFile is a function that just returns the name of the database file.
Recently users have complained that the app sometimes fails to find its database. Is there anything I am doing wrong? I have not been keeping abreast of the latest changes in iOS.
I also save db in caches in current project.Whenever user run the app,it finds db correctly.Mainly I use with FMDB.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory , NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
NSString *documentsDirectory = [documentsDir stringByAppendingPathComponent:strFileName];
if (![[NSFileManager defaultManager] fileExistsAtPath:documentsDirectory])
{
NSString *backupDbPath = [[NSBundle mainBundle] pathForResource:#"DBName" ofType:#"sqlite"];
NSLog(#"Test backuppath %#",backupDbPath);
if (backupDbPath == nil)
{
NSLog(#"Database path is nil");
}
else
{
BOOL copiedBackupDb = [[NSFileManager defaultManager] copyItemAtPath:backupDbPath toPath:documentsDirectory error:nil];
if (!copiedBackupDb) NSLog(#"Copying database failed");
}
}
Now I remember.
An app store reviewer told me that I could not store the database in the directory that I originally intended to use, because its contents were downloaded from the internet. He was wrong of course, but I was having a lot of trouble with them at the time, so I just moved the database to the cache area as requested.
That is why is sometimes gets deleted.
Related
I am creating an application. I am storing the files in Document directory. And after my work completed, delete the files from document directory as like below:
NSMutableDictionary * Dictionary = [NSMutableDictionary alloc]init];
// Next every file storing into this dictionary like below
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *baseDir = [paths objectAtIndex:0];
NSString *pathComp = [baseDir stringByAppendingPathComponent:[NSString stringWithFormat:#"IMG%d.PNG",presentCount];
fileURL = [NSURL fileURLWithPath:pathComp];
[Dictionary setObject:fileURL forKey:fileURL];
while ([[Dictionary allKeys]count]!=0) {
NSURL *deleteFileURL = [[Dictionary allKeys] lastObject];
NSLog(#"Path %#",deleteFileURL.path);
[[NSFileManager defaultManager] removeItemAtPath:deleteFileURL.path error:nil];
[Dictionary removeObjectForKey:deleteFileURL];
}
Here my problem is, after delete the files from document directory, memory is not reduced, still it's occupying as like files exist. Due to this issue, my is crashing. So please help me how to clear the memory.
Actually i am getting the files(Photos ) from the server and first placing in documents directory,and trying to save using photo library.Once i give input from dictionary to photo library, after completion handler, i am trying to delete the file.Its removed and photo saved, but memory is not reduced.
1、Remove the file after checking for the existence of a file on the path, and check the return value of removeItemAtPath: to determine if the deletion succeeded.
NSString *path = #"a/b";
if ([[NSFileManager defaultManager] fileExistsAtPath:path]) {
BOOL success = [[NSFileManager defaultManager] removeItemAtPath:path error:nil];
// Check the success's value
}
I am developing one iOS app in that I am using sqlite database.I have inserted records in database now I want to see that records.I searched in Library->Application Support->iPhone simulator, But in iPhone simulator folder nothing is present.So is there any another way to view sqlite database records.
Please help me,
Thank you.
This is my code for file path
-(NSString *)filePath
{
NSString *documentDir=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)objectAtIndex:0];
return [documentDir stringByAppendingPathComponent:#"Test.sqlite"];
}
Now you can have your Simulator folder as "Core Simulator" not as "iPhone simulator"
Use the following Code.
// Get the Sqlite Data from the url in a NSData Object
NSData *sqlData = [[NSData alloc] initWithContentsOfURL:[
NSURL URLWithString:[sqlUrlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]];
// Store the Data locally as Sqlite File
NSString *resourceDocPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *filePath = [resourceDocPath
stringByAppendingPathComponent:#"Test.sqlite"];
[sqlData writeToFile:filePath atomically:YES];
NSLog(#"File Path: %#", filePath);
In Console as:
File Path:
/Users/Library/Developer/CoreSimulator/Devices/3C0492CE-2C27-48D8-AB04-7B7EFDB77228/data/Containers/Data/Application/91AF3E65-D0C2-4CC9-A7F6-35DD32AB1FD0/Documents/Test.sqlite
Now You can easily go to your database file path and open it where ever you want.
You can achieve this by using a simple code and opening the Sqlite file in to a simple Sqlite Client like chrome extension(SqliteManager), Firefox Extension and Navicat Premium.
Code:
-(NSString *)GetDocumentDirectory
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
NSString *documentsDir = [paths objectAtIndex:0];
return documentsDir;
}
-(NSString *)getDBPath
{
NSString *documentsDir = [self GetDocumentDirectory];
return [documentsDir stringByAppendingPathComponent:#"YourSqliteFileName.sqlite"];
}
Call it like this
NSString *dbPath = [self getDBPath];
NSLog(#"Database Path = %#",dbPath);
Note: Every time you will run your application on simulator, Every time a new path is created which will be different from your previous path so you have to just copy paste this path and open it in any Sqlite Client.
I have this database that i created, i want to load it using FMDB, but on the simulator i can query select the data, but not on the ipad.
i use this code to check it.
- (void)createDatabase{
//set reference to database here
BOOL success;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
// Database filename can have extension db/sqlite.
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *appDBPath = [documentsDirectory stringByAppendingPathComponent:#"product.db"];
success = [fileManager fileExistsAtPath:appDBPath];
if (success) {
[self getAllData];
return;
}
// The writable database does not exist, so copy the default to the appropriate location.
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"product.db"];
success = [fileManager copyItemAtPath:defaultDBPath toPath:appDBPath error:&error];
NSAssert(success, #"Failed to create writable database file with message '%#'.", [error localizedDescription]);
[self getAllData];
}
//method used to create database and check if it exists
- (void)getAllData {
// Getting the database path.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsPath = [paths objectAtIndex:0];
NSString *dbPath = [docsPath stringByAppendingPathComponent:#"product.db"];
database = [FMDatabase databaseWithPath:dbPath];
[database open];
NSString *sqlSelectQuery = #"SELECT * FROM Categories";
// Query result
FMResultSet *resultsWithNameLocation = [database executeQuery:sqlSelectQuery];
while([resultsWithNameLocation next]) {
NSString *strID = [NSString stringWithFormat:#"%d",[resultsWithNameLocation intForColumn:#"id"]];
NSString *strName = [NSString stringWithFormat:#"%#",[resultsWithNameLocation stringForColumn:#"cat"]];
NSString *strLoc = [NSString stringWithFormat:#"%#",[resultsWithNameLocation stringForColumn:#"Location"]];
// loading your data into the array, dictionaries.
NSLog(#"ID = %#, Name = %#, Location = %#",strID, strName, strLoc);
}
[database close];
}
i put the product.db in the supporting files, and i copied it in the Copy Bundle Resources for the targets. Does anyone what i am doing wrong? i am kind of at a dead end here.
Thanks in advance
The problem occurs at the selecting stage, when i select it it returns:
"DB Error: 1 "no such table"
If you ever ran the app on the device before you refined the file open/copy logic, you may have accidentally created a blank database in the documents folder (because if you open a database and it's not found, it creates a blank database). Try deleting the app (which will remove any blank database that might be lingering about) and reinstalling the app and see if that fixes it.
By the way, in the future, you can avoid this problem by using openWithFlags (rather than open) with SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE), and that will ensure that the app never creates a blank database if it doesn't find one.
You can see the SQLite documentation on sqlite3_open (which FMDB open uses) and sqlite_open_v2 (which FMDB openWithFlags uses) for a discussion of these flags.
I want to replace core data and want to delete old core data. Does Apple allows it to delete old core data. Is there any chance to reject app.
Apple won't care, but your users might. If there is data that your users might be sorry to lose, you should make every effort to migrate it or give an option to export it when they upgrade.
If you're only using core data to cache downloaded values, then there's no problem with this at all. In fact, deleting the old store would be necessary to prevent the app crashing on upgrade, since it wouldn't be able to migrate from the existing store. The best place to do this is in the core data setup code when you receive an error - the boilerplate comments guide you toward this.
There are no problems doing that.
For example, you can check app's version in the AppDelegate:
- (void)clearCacheIfNeeded;
{
NSString *savedVersion = [[NSUserDefaults standardUserDefaults] objectForKey:#"currentVersion"];
NSString *currentVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey:#"CFBundleVersion"];
if (![savedVersion isEqualToString:currentVersion]) {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *cachesDirectory = [paths objectAtIndex:0];
NSArray *contents = [fileManager contentsOfDirectoryAtPath:cachesDirectory error:NULL];
NSEnumerator *e = [contents objectEnumerator];
NSString *filename;
while ((filename = [e nextObject])) {
NSLog(#"file name: %#", filename);
[fileManager removeItemAtPath:[cachesDirectory stringByAppendingPathComponent:filename] error:NULL];
}
[[NSUserDefaults standardUserDefaults] setObject:currentVersion forKey:#"currentVersion"];
}
}
I am quite new to iOS app development.
I am trying to build a sample DB app which saves records to DB and fetches from it.
The App works well when I test with simulators. I have created a local database and also I am programatically making a copy of it when required. Also I have checked that local DB is referenced in the 'Copy Bundle Resources'.
But the error I am getting is, " * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '* -[NSFileManager copyItemAtPath:toPath:error:]: source path is nil' ".
I think the piece of code which causes this problem is
" [FileManager copyItemAtPath:databasePathFromApp toPath:DBPath error:nil]; "
It work perfectly good for simulators but not when I test with my device.
Expecting help.
My code is,
- (id)init {
self = [super init];
//Datbase Name
DBName=#"Person.sqlite3";
//Getting DB Path
NSArray *documentsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentsPath objectAtIndex:0];
DBPath=[documentsDir stringByAppendingPathComponent:DBName ];
//DBPath = [[NSString alloc] initWithString: [documentsDir stringByAppendingPathComponent:DBName]];
NSLog(#"DBPath is %#",DBPath);
return self;
}
-(void)checkAndCreateDB{
BOOL Success;
//NSFileManager maintains File
NSFileManager *FileManager = [NSFileManager defaultManager];
NSLog(#"line 1");
//Checks Database Path
Success = [FileManager fileExistsAtPath:DBPath];
NSLog(#"line 2");
//If file exists, it returns true
if(Success)return;
NSLog(#"line 3");
//NSString *databasePathFromApp = [[[NSBundle mainBundle]resourcePath]stringByAppendingPathComponent:DBName];
// Get the path to the database in the application package
NSString *databasePathFromApp=[[NSBundle mainBundle] pathForResource:#"Person.sqlite3" ofType:#"sqlite3"];
NSLog(#"line 4");
[FileManager copyItemAtPath:databasePathFromApp toPath:DBPath error:nil];
//[FileManager release];
NSLog(#"line 5");
}
My Application crashes while testing in device after the line NSLOG(line 4); But works good in simulator.
Many Thanks
Prakash
The device can not write to the app bundle, you need to use the Documents directory.
Here is how to get the Documents directory path:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:fileName];
If you have an initial db in the app bundle copy it to the Documents on initial startup.
change this line
NSString *databasePathFromApp=[[NSBundle mainBundle] pathForResource:#"Person.sqlite3" ofType:#"sqlite3"];
to
NSString *databasePathFromApp=[[NSBundle mainBundle] pathForResource:#"Person" ofType:#"sqlite3"];
also, pay attention to capitalisation, iOS devices are case sensitive, while on simulator, you'll get away with wrong capitalisation