Creating a custom directory which has all the images. Designing it custom because, it will help me to get the images as an when I need at various places in the configuration.
NSFileManager *filemgr;
filemgr = [NSFileManager defaultManager];
[filemgr createDirectoryAtPath: #"/Users/home/lifemoveson/test" withIntermediateDirectories:YES attributes: nil error:NULL];
I have placed images under test folder and are of .png types.
Is there a way to retrieve the images like below.
/** UPDATED again **/
Currently this folder is under Application_Home/Resources/ImageTiles/ as per Photoscroller example.
How can we change it to /Users/home/lifemoveson/test/ImageTiles/ folder ?
- (UIImage *)tileForScale:(CGFloat)scale row:(int)row col:(int)col
{
// we use "imageWithContentsOfFile:" instead of "imageNamed:" here because we don't want UIImage to cache our tiles
NSString *tileName = [NSString stringWithFormat:#"%#_%d_%d_%d", imageName, (int)(scale * 1000), col, row];
// Currently this folder is under <Application_Home>/Resources/ImageTiles/ as per Photoscroller example.
// How can we change it to /Users/home/lifemoveson/test/ImageTiles/ folder ?
NSString *path = [[NSBundle mainBundle] pathForResource:tileName ofType:#"png"];
UIImage *image = [UIImage imageWithContentsOfFile:path];
return image;
}
Applications running on iOS are sandboxed; you can't simply create directories wherever you please. Your createDirectoryAtPath: call will fail. You should use one of the directories set aside for your application instead.
Once you obtain the path for one of those directories, getting the path for files within them is simply a case of using NSString's stringByAppendingPathComponent: method.
Makin a call to the functions such as
NSString* newDirPath = [self createDirectoryWithName:#"Test"];
if (newDirPath) {
[self saveFile:#"MasterDB.sqlite" atPath:newDirPath];
}
which are implemented as follows
-(NSString*)createDirectoryWithName:(NSString*)dirName{
NSArray* directoryArray = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask , YES);
NSString* directoryPath = [directoryArray objectAtIndex:0];
NSString* newPath = [directoryPath stringByAppendingString:[NSString stringWithFormat:#"/%#",dirName]];
NSFileManager *filemamager = [NSFileManager defaultManager];
BOOL flag = [filemamager createDirectoryAtPath:newPath withIntermediateDirectories:YES attributes: nil error:NULL];
return flag == YES ?newPath: nil;
}
-(BOOL)saveFile:(NSString*)fileName atPath:(NSString*)path{
BOOL success;
// Create a FileManager object, we will use this to check the status
// of the File and to copy it over if required
NSFileManager *fileManager = [NSFileManager defaultManager];
// Check if the File has already been created in the users filesystem
NSString *filePath = [path stringByAppendingPathComponent:fileName];
success = [fileManager fileExistsAtPath:filePath];
// If the File already exists then return without doing anything
if(success) return YES;
// If not then proceed to copy the File from the application to the users filesystem
// Get the path to the database in the application package
NSString *pathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:fileName];
// Copy the database from the package to the users filesystem
NSError *error = nil;
BOOL flag = [fileManager copyItemAtPath:pathFromApp toPath:filePath error:&error];
return flag;
}
might help you solve your problem. Creating a directory is achieved using first function and the second will let you save files from your application bundle to any of the previously created directory. I hope you can modify it save files located at places other than Application bundle to suit to your need.
Related
In my application I want to implement a simple Alarm function. I know how to use UILocalNotifications, but I came across this source code with a like UI of the iPhone's native Clock app alarm area as well as it having a believe a type of data persistence. Two things I am not good at interface design and data persistence this source code has. But I downloaded it and started playing around with it to find the alarms are not persistent.
Download
Does anyone know how the source code can be adjusted so that it is persistent and the plist can be saved and read to and from? I am open to learning too, this area is somewhat unknown to me too. Thanks
I review your code and find issue that you not moved your "Alarms.plist" file form resource to document directory. we are not able to edit file which is in resource folder. so write following code in app delegate file.
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *theFileName = #"Alarms.plist"; //Change this appropriately
NSString *oldPath = [[NSBundle mainBundle] pathForResource:#"Alarms" ofType:#"plist"];//[NSString stringWithFormat:#"%#/Inbox/%#", documentsDirectory, theFileName];
NSString *newPath = [NSString stringWithFormat:#"%#/%#", documentsDirectory, theFileName];
if (![[NSFileManager defaultManager] fileExistsAtPath:newPath])
[[NSFileManager defaultManager] moveItemAtPath:oldPath toPath:newPath error:nil];
Perform save operation on file which is in Document directory folder.
try this code... to save plist from bundle to Document Directory
Notice that you will have "Unable to read... " just at the first app launch
- (NSMutableArray *)displayedObjects
{
if (_displayedObjects == nil)
{
NSString *path = [[self class] pathForDocumentWithName:#"Alarms.plist"];
NSArray *alarmDicts = [NSMutableArray arrayWithContentsOfFile:path];
if (alarmDicts == nil)
{
NSLog(#"Unable to read plist file: %#", path);
NSLog(#"copy Alarms.plist to: %#", path);
NSString *pathToSetingbundle = [[NSBundle mainBundle] pathForResource:#"Alarms" ofType:#"plist"];
[[NSFileManager defaultManager]copyItemAtPath:pathToSetingbundle toPath:path error:nil];
}
_displayedObjects = [[NSMutableArray alloc]
initWithCapacity:[alarmDicts count]];
for (NSDictionary *currDict in alarmDicts)
{
Alarm *alarm = [[Alarm alloc] initWithDictionary:currDict];
[_displayedObjects addObject:alarm];
NSLog(#"#disply obj %#", alarm);
}
}
return _displayedObjects;
}
I want to copy some files as part of a backup routine.
I have the following function which gives the location of my files.
- (NSString *)getLocalDocumentPath:(NSString*)strFile {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *path = [[paths objectAtIndex:0]
stringByAppendingPathComponent:strFile];
return path;
}
Heres my database
NSString *filePath = [self getLocalDocumentPath:#"mydatabase.db"];
I want to copy this to a new file called upload.txt
NSString *filePath = [self getLocalDocumentPath:#"upload.txt"];
Then later on I download a file.
NSString *filePath = [self getLocalDocumentPath:#"download.txt"];
Which I want to copy on top of my original database file.
NSString *filePath = [self getLocalDocumentPath:#"mydatabase.db"];
NSFileManager *fileManager = [NSFilemanager defaultManager];
[fileManager copyItemAtPath:databasePath toPath:uploadFilePath error:nil];
and if you want to overwrite the database using the download.txt, make an instance of NSData and use - (BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile
Sounds like you want to get to know NSFileManager very well (documentation is linked for you).
The method you'd most likely be most interested in is:
moveItemAtPath:toPath:error:
one method could be:
you can read the file contents you want to save in NSData then can use:
- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile
in which you can replace the path with one your relative file paths you have mentioned for various files.
As part of my app start-up i copy bundle files to my documents directory.
This works fine for three out of four of my files but the fourth one create a Zero KB file.
running on iOS 5.0 sim. I have cleaned the build several times and checked the file name capitalization vis correct.
the file appears in the directory but is zero kb and should be 24K
any help appreciated.
-(BOOL) CheckDBs: (NSString *)dbname
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
NSString *dbPath = [documentsDir stringByAppendingPathComponent:dbname];
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL success = [fileManager fileExistsAtPath: dbPath];
NSLog(#"AppDelegate CheckDatabase: %# = %i", dbPath, success);
if (success) {
//NSLog(#"return YES");
return YES;
}
else {
return NO;
}
} // Complete - checks if files exist in the User Documents directory
-(void) copyDBs: (NSString *) dbname
{
//Using NSFileManager we can perform many file system operations.
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
NSString *dbPath = [documentsDir stringByAppendingPathComponent:dbname];
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:dbname];
BOOL success = [fileManager copyItemAtPath:defaultDBPath toPath:dbPath error:&error];
if (success) {
// Version 4.0 code
//NSDictionary *attribs = [NSDictionary dictionaryWithObject:NSFileProtectionComplete forKey:NSFileProtectionKey];
//success = [fileManager setAttributes:attribs ofItemAtPath:dbPath error:&error];
NSLog(#"AppDelegate copyDatase: %# = %d", dbPath, success);
}
//NSLog(#"AppDelegate copyDatase: %# = %d", dbPath, success);
if (!success) {
NSLog(#"Failed to copy database: '%#'", [error localizedDescription]);
// NSAssert1(0, #"Failed to create writable database file with message '%#'.", [error localizedDescription]);
}
}
Have you also checked the original file size?
Try resetting your simulator. From the NSFileManager documentation:
If a file with the same name already exists at dstPath, this method
aborts the copy attempt and returns an appropriate error.
Make sure the destination is empty and try again. Also, check the error object.
If all that checks out there has got to be an error in spelling the file name. Check if the exact file exists in bundle, NSLog wherever you use a file name or path, etc. You should find the error. Also check the appropriate folder in the Finder.
Instead of using
[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:dbname]
try
[[NSBundle mainBundle] pathForResource:shortName ofType:#"db"]
Ok I figured out what is causing the problem.
as i run the app the appdidfinishlaunching method is not complete before one of the view controllers is loading. That view controller attempts to access one of the files being copied over from the bundle.
I'm guessing that sqlite creates the file when you attempt to access the database, it creates it with with a zero bytes length.
So when my appdidfinish launching method checks for the existance of the file it exists due to the sql call.
This is usually only going to be a problem prior to the first run of the app as after that the database will exist.
problem now is how do i get the appdidfinish launching to complete prior to the rest being allow to start as the view controller in question is part of the mainwindow.xib
I have a zip file that I unzip it in a directory 'extract' under the Documents directory (the dir and its content is properly created). Then I would to do some stuff on each item in the new dir, dipendently if it's a file or a dir. I use the contentsOfDirectoryAtPath method of the NSFileManager.
The problem is that the array extractedItems returns always null and I don't know what I'm wronging.
NSString *dirnameForUnzippedData = [[NSString alloc] initWithString:#"extract"];
NSString *dirpath = [documentsDirectory stringByAppendingPathComponent:dirnameForUnzippedData];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *extractedItems = [fileManager contentsOfDirectoryAtPath:dirnameForUnzippedData error:NULL];
for (NSString *item in extractedItems) { ... }
It seems you are looking at the wrong path. Your code doesn't use dirpath (or your documentsDirectory).
As a side note, don't forget to release dirnameForUnzippedData after you're done with it - or just do dirnameForUnzippedData = #"extract"; instead of the alloc/init.
I'm working on a new iPhone project and I'm running into problems with sqlite. I've done this before on a different project and it worked just fine so I'm not sure exactly what is going on with this one. I'm using the same code from before, but the situation is a little different.
First of all, I'm trying this time to use Unit Testing so I've created a Cocoa Unit Test Bundle, and I got that working correctly, then I wanted to make a Unit Test for my sqlite database.
The first thing run with this test is [self checkAndCreateDatabase] which is as follows:
-(void) checkAndCreateDatabase{
BOOL success;
// Create a FileManager object, we will use this to check the status
// of the database and to copy it over if required
NSFileManager *fileManager = [NSFileManager defaultManager];
// Check if the database has already been created in the users filesystem
success = [fileManager fileExistsAtPath:databasePath];
// If the database already exists then return without doing anything
if(success) return;
// If not then proceed to copy the database from the application to the users filesystem
// Get the path to the database in the application package
NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:databaseName];
// Copy the database from the package to the users filesystem
[fileManager copyItemAtPath:databasePathFromApp toPath:databasePath error:nil];
[fileManager release];
}
Then I attempt to open the database with the following line:
int result = sqlite3_open([databasePath UTF8String], &database);
This fails everytime with error code 14 SQLITE_CANTOPEN, and databasePath is "/Users/labuser/Library/Application Support/iPhone Simulator/Documents/projectfusion.db3".
What is odd is that when I go to that directory, Documents/ isn't there, so if I create that, then it doesn't fail, BUT projectfusion.db3 then has a size of 0kb; the tables aren't there. That makes any sqlite3_prepare_v2() fail, because the tables aren't there. If I manually copy the projectfusion.db3 file to that directory before running, then it works just fine.
Is it because I'm doing this inside the unit tests and the scripts don't have permission or something? Or is it possibly because I'm working on a school computer at my university and can't write to that directory? (I tried logging in as admin and it didn't work either).
Try the code given below,
I've set a macro called TEST so I don't have to keep commenting code out.
- (NSString *)createEditableCopyOfDatabaseIfNeeded {
// First, test for existence.
BOOL success;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
#ifdef TEST
documentsDirectory = [[NSFileManager defaultManager] currentDirectoryPath];
#endif
NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:DBNAME];
success = [fileManager fileExistsAtPath:writableDBPath];
if (success) { return writableDBPath;} ;
// The writable database does not exist, so copy the default to the appropriate location.
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:DBNAME];
#ifdef TEST
defaultDBPath = [[NSBundle bundleForClass:[self class]] pathForResource:#"YOURDB" ofType:#"sqlite"];
#endif
success = [fileManager copyItemAtPath:defaultDBPath toPath:writableDBPath error:&error];
if (!success) {
NSAssert1(0, #"Failed to create writable database file with message '%#'.", [error localizedDescription]);
}
return (defaultDBPath);
}
Try adding the database to your application bundle in xcode and then copy it to the applications Documents directory. You can get that path using
- (NSString *)applicationDocumentsDirectory {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
return basePath;
}