Error while moving file in Cache Directory in Iphone - iphone

I am facing problem to move image file in Cache Directory. My requirement is when I am deleting one file for example image3.png then all other files (suppose there is 9 files like image1.png,image2.png,.....image9.png)after that position (image4.png,....,image9.png) will move to their previous position. I want to rename that files like image4.png to image 3.png.
Below is my code
NSError *error=nil;
NSString *imgName = [NSString stringWithFormat:#"image%d.png",3];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:imgName];
[fileManager removeItemAtPath: fullPath error:NULL];
for (int i=3; i<=9 ; i++) {
NSString *imgName1 = [NSString stringWithFormat:#"image%d.png",i];
NSString *getImagePath1 = [documentsDirectory stringByAppendingPathComponent:imgName1];
NSString *imgName2 = [NSString stringWithFormat:#"image%d.png",i+1];
NSString *getImagePath2 = [documentsDirectory stringByAppendingPathComponent:imgName2];
if ([fileManager moveItemAtPath:getImagePath2 toPath:getImagePath1 error:&error] != YES)
NSLog(#"Unable to move file: %#", [error localizedDescription]);
// Show contents of Documents directory
NSLog(#"Documents directory: %#",
[fileManager contentsOfDirectoryAtPath:documentsDirectory error:&error]);
}
But its showing following error
Unable to move file: The operation couldn’t be completed. (Cocoa error 516.)
Please help me .
Thanks in advance.

From NSFileManager docs on moveItemAtPath:toPath:error::
If an item with the same name already exists at dstPath, this method
aborts the move attempt and returns an appropriate error
Delete the file you want to overwrite first.

Related

how to create a directory in iphone settings in objective c

I am new programmer in objective c. I want to create "Download" directory inside the i phone(path : setting (i phone setting directory))I want to know is it possible?. I am using i phone simulator to test the program.
Another question is, How can I access created directory in i phone simulator. Below contains code I tried to create folder in i phone. But I can not access that directory by using i phone simulator. what the wrong of this code?
NSString *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:#"/Test"];
if (![[NSFileManager defaultManager] fileExistsAtPath:dataPath])
[[NSFileManager defaultManager] createDirectoryAtPath:dataPath withIntermediateDirectories:NO attributes:nil error:&error];
you can create Directory in to Document Directory as sub Folder like this way:-
-(IBAction)CreatDirInDocDir
{
NSFileManager *filemgr = [NSFileManager defaultManager];
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *dir = [NSString stringWithFormat:#"%#",DirName];
NSString *path = [documentsDirectory stringByAppendingPathComponent:dir];
NSError *error;
if ([filemgr fileExistsAtPath:path ] == YES){
}
else
{
NSLog (#"File not found");
[[NSFileManager defaultManager] createDirectoryAtPath:path withIntermediateDirectories:NO attributes:nil error:&error];
}
}
when ever you create directory in to Document directory folder then you can get all list of Created Custom directory like this way:-
//Get all Directory
NSFileManager *fileMan = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSArray *filePathsArray = [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:documentsDirectory error:nil];
NSLog(#"files array %#", filePathsArray);
NSMutableArray *directoryList=[[NSMutableArray alloc]init];
for ( NSString *direPath in filePathsArray )
{
NSString *path = [documentsDirectory stringByAppendingPathComponent:direPath];
BOOL isDir = NO;
[fileMan fileExistsAtPath:path isDirectory:(&isDir)];
if(isDir) {
NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:path];
NSLog(#"log path ==%#",fullPath);
[directoryList addObject:fullPath];
}
}
NSLog(#"list path ==%#",directoryList);
Now you have array of all directory you can get any directory with index :)
Hope its helps you
All The method posted here are correct and there are tons of answers about them, but I'd like to warn you about a concept. Since The introduction of iCloud, Apple started to reject applications that saves a lot of data in document directory, when they are used by means of caches or they could be downloaded again later. The problem here is that you can backup your ios devices on the cloud and document directory is one of the backupped. Can you image yourself backupping one GB on application on the cloud? That's the explanation about apple rejects. To avoid that temp/redownloadable/cached data should be saved in cache directory. This useful dir is freed when the device is running out of space on "disk", like when you try to install a new app and you don't have enough space. So this is ok if your data can be downloaded again and are not indispensable. the other way around is to keep data in the document directory but telling the system to do not backup them, this is possible adding a special flag to the doc subdirectory where you saved the file, here is how link , pay attention that this methods is only available from 5.0.1 so you need to check its existence if you target lower ioses. In this case the system will not free your data and not backup them this is safe for apple guidelines. hope this helps
For creating directory you can use:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:#"Test"];
NSError *error;
if (![[NSFileManager defaultManager] createDirectoryAtPath:dataPath withIntermediateDirectories:NO attributes:nil error:&error])
{
NSLog(#"Couldn't create directory error: %#", error);
}
For getting the files inside that directory you can use:
NSArray *datArray = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:dataPath error:&error];
if(error)
{
NSLog(#"Could not get list from directory, error = %#",error);
}
Here all file names will be in the datArray.
No need append '/' . Just Use
NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:#"Test"];
Try This
NSArray *dirPath;
NSString *docsDir;
NSFileManager *filemgr = [NSFileManager defaultManager];
dirPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = [dirPath objectAtIndex:0];
if ([filemgr changeCurrentDirectoryPath: docsDir] == NO)
{
NSLog(#"Error");
}else {
NSString *currentPath = [filemgr currentDirectoryPath];
NSLog(#"%#",currentPath);
}
NSString *dataDirectory = [docsDir stringByAppendingPathComponent:#"Test"];
if ([filemgr fileExistsAtPath:dataDirectory]){
NSLog(#"dir Exist");
}else{
NSLog(#"Creating Dir");
[filemgr createDirectoryAtPath:dataPath withIntermediateDirectories:NO attributes:nil error:&error];
}
Anyone want to show your created directory in i phone simulator follow bellow steps :
Go to finder
Click Command +Shift + g
Type ~/Library then click Go
Open Application Support --> i phone simulator
Then you can find your created applications and directories..

How to Get file From one Document Folder to Another Document Folder?

In my Application i save Recording file in Document Directory.then later gets all these file from document directory and showing all these files in My mainClass where i have UITableview for it.
When i Click on any row of this mainClass Tableview it goes to next Class where i play this file,delete this file and Send this file to my Favourite Recording Class where i have Tableview for it.Now my play button action method and delete Button action method works fine but i Don't know how to send this file to my Favurite Class Tableview.now i show here my delete button Code through which we can get the basic idea.
-(IBAction)deleteFile
{
NSArray *dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsDir = [dirPaths objectAtIndex:0];
NSString *documentPath = [docsDir stringByAppendingPathComponent:#"MyRecordings"];
NSString *soundFilePath = [documentPath stringByAppendingPathComponent:fileToPlay];
recordedTmpFile = [NSURL fileURLWithPath:soundFilePath];
[[NSFileManager defaultManager] removeItemAtURL:recordedTmpFile error:nil];
}
As my Delete button Code show how we delete the Current Recording file which i selected from MainTableview .Now if the user Want to send the current Recording file to my Favourite Class Tableview instead of Deleting it then Whether i use the another Document folder here if answer is yes? then how we can save the Current file(recordedTmpFile) in this new Document folder.
-(IBAction)AddToFavourite
{
NSArray *dirPaths1 = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsDir1 = [dirPaths1 objectAtIndex:0];
NSString *documentPath1 = [docsDir1 stringByAppendingPathComponent:#"MyFovouriteRecordings"];
// How to pass here the Current Recording File (recordedTmpFile) to this new document Folder.
}
When i NSlog recordedTmpFile it show result :file://localhost/Users/Umar/Library/Application%20Support/iPhone%20Simulator/4.2/Applications/9219677A-B0E3-4B78-B2E5-FEA49D689618/Documents/MyRecordings/06:Dec:12_05:54:07%20PM+Active%20song
Any Help will be appriated.Thanks
-(IBAction)AddToFavourite {
NSArray *dirPaths1 = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsDir1 = [dirPaths1 objectAtIndex:0];
NSString *documentPath1 = [docsDir1 stringByAppendingPathComponent:#"MyFovouriteRecordings"];
NSString *soundFilePath1 = [documentPath1 stringByAppendingPathComponent:fileToPlay];
// How to pass here the Current Recording File (recordedTmpFile) to this new document Folder.
// First check if the directory existst
if([[NSFileManager defaultManager] fileExistsAtPath:documentPath1]==NO) {
NSLog(#"Creating content directory: %#",documentPath1);
NSError *error=nil;
if([[NSFileManager defaultManager] createDirectoryAtPath:documentPath1 withIntermediateDirectories:NO attributes:nil error:&error]==NO) {
NSLog(#"There was an error in creating the directory: %#",error);
}
}
//then get the origin file path
NSArray *dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsDir = [dirPaths objectAtIndex:0];
NSString *documentPath = [docsDir stringByAppendingPathComponent:#"MyRecordings"];
NSString *soundFilePath = [documentPath stringByAppendingPathComponent:fileToPlay];
//Then convert paths to URL
NSURL* originURL = [NSURL fileURLWithPath:soundFilePath];
NSURL* destinationURL = [NSURL fileURLWithPath:soundFilePath1];
//Then, you have to copy the file
[[NSFileManager defaultManager] copyItemAtURL:destinationURL toURL:originURL error:NULL];
}
That should do it, tell me if there is any error.
Just create an instance of NSData with your original file. Than write it to the other location.
//write file to the other location
NSData *myData = [[NSData alloc] initWithContentsOfFile:originalPath];
[myData writeToFile:newDataPath options:NSDataWritingAtomic error:&error];
//delete file from original location
NSFileManager *fileManager = [[NSFileManager alloc] init];
[fileManager removeItemAtPath:originalPath error:&removeError];

copying plist to document directory

How do I copy an existing plist I have in the app build to the Document directory?
My plist is basically an array of dictionary, I have successfully copy the plist to the directory using the following:
BOOL success;
NSError *error;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:#"States.plist"];
success = [fileManager fileExistsAtPath:filePath];
if (success) return;
NSString *path = [[NSBundle mainBundle] pathForResource:#"States" ofType:#"plist"];
success = [fileManager copyItemAtPath:path toPath:filePath error:&error];
if (!success) {
NSAssert1(0, #"Failed to copy Plist. Error %#", [error localizedDescription]);
}
However, when I try to access the NSDictionary it gives me:
CoreAnimation: ignoring exception: -[__NSCFDictionary setObject:forKey:]: mutating method sent to immutable object
Why is this? I have to relaunch the app again and now I can change the dictionary stored in my array
This is the way I copy the *.plist file to documents folder. Hope this helps.
+ (NSString*) getPlistPath:(NSString*) filename{
//Search for standard documents using NSSearchPathForDirectoriesInDomains
//First Param = Searching the documents directory
//Second Param = Searching the Users directory and not the System
//Expand any tildes and identify home directories.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
return [documentsDir stringByAppendingPathComponent:filename];
}
+ (void) copyPlistFileToDocument{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSString *dbPath = [Utilities getPlistPath:#"AppStatus.plist"];
if( ![fileManager fileExistsAtPath:dbPath])
{
NSString *defaultDBPath = [[NSBundle mainBundle] pathForResource:#"AppStatus" ofType:#"plist"];
BOOL copyResult = [fileManager copyItemAtPath:defaultDBPath toPath:dbPath error:&error];
if(!copyResult)
NSAssert1(0, #"Failed to create writable plist file with message '%#'.", [error localizedDescription]);
}
}
Just create a new pList in the documents directory, and set to the contents of the existing plist you have.

Read/write file in Documents directory problem

I am trying to write a very basic text string to my documents directory and work from there to later save other files etc.
I am currently stuck with it not writing anything into my Documents directory
(In my viewDidLoad)
NSArray *pathArray = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)
NSString *documentsDirectory = [pathArray objectAtIndex:0];
NSString *textPath = [documentsDirectory stringByAppendingPathComponent:#"file1.txt"];
NSString *text = #"My cool text message";
[[NSFileManager defaultManager] createFileAtPath:textPath contents:nil attributes:nil];
[text writeToFile:textPath atomically:NO encoding:NSUTF8StringEncoding error:NULL];
NSLog(#"Text file data: %#",[[NSFileManager defaultManager] contentsAtPath:textPath]);
This is what gets printed out:
2011-06-27 19:04:43.485 MyApp[5731:707] Text file data: (null)
If I try this, it also prints out null:
NSLog(#"My Documents: %#", [[NSFileManager defaultManager] contentsOfDirectoryAtPath:documentsDirectory error:NULL]);
What have I missed or am I doing wrong while writing to this file?
Might it be something I need to change in my plist or some frameworks/imports needed?
Thanks
[EDIT]
I passed a NSError object through the writeToFile and got this error:
Error: Error Domain=NSCocoaErrorDomain Code=512 "The operation couldn’t be completed. (Cocoa error 512.)" UserInfo=0x12aa00 {NSFilePath=/var/mobile/Applications/887F4691-3B75-448F-9384-31EBF4E3B63E/Documents/file1.txt, NSUnderlyingError=0x14f6b0 "The operation couldn’t be completed. Not a directory"}
[EDIT 2]
This works fine on the simulator but not on my phone :/
Instead of using NSFileManager to get the contents of that file, try using NSString as such:
NSArray *pathArray = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)
NSString *documentsDirectory = [pathArray objectAtIndex:0];
NSString *textPath = [documentsDirectory stringByAppendingPathComponent:#"file1.txt"];
NSError *error = nil;
NSString *str = [NSString stringWithContentsOfFile:textPath encoding:NSUTF8StringEncoding error:&error];
if (error != nil) {
NSLog(#"There was an error: %#", [error description]);
} else {
NSLog(#"Text file data: %#", str);
}
Edit: Added error checking code.
How are you getting documentsDirectory?
You should be using something like this:
NSArray *pathArray = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)
NSString *documentsDirectory = [pathArray lastObject];
Put an NSLog statement after every line where you are setting a variable's value, so that you can inspect those values. This should help you quickly pinpoint where things start to go wrong.
The problem got solved by setting a non standard Bundle ID in die info.plist
I used the Bundle ID from iTunes Connect for this specific app. Now everything works perfectly.
You can also use NSFileHandle for writing data in file and save to document directory:
Create a variable of NSFileHandle
NSFileHandle *outputFileHandle;
use the prepareDataWrittenHandle function with passing file name in parameter with file extension
-(void)prepareDataWrittenHandle:(NSString *)filename
{
//Create Path of file in document directory.
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *outputFilePath = [documentsDirectory stringByAppendingPathComponent:filename];
//Check file with above name is already exits or not.
if ([[NSFileManager defaultManager] fileExistsAtPath:outputFilePath] == NO) {
NSLog(#"Create the new file at outputFilePath: %#", outputFilePath);
//Create file at path.
BOOL suc = [[NSFileManager defaultManager] createFileAtPath:outputFilePath
contents:nil
attributes:nil];
NSLog(#"Create file successful?: %u", suc);
}
outputFileHandle = [NSFileHandle fileHandleForWritingAtPath:outputFilePath];
}
then write the string value to file as:
//Create a file
[self prepareDataWrittenHandle:#"file1.txt"];
//String to save in file
NSString *text = #"My cool text message";
//Convert NSString to NSData to save data in file.
NSData* data = [text dataUsingEncoding:NSUTF8StringEncoding]
//Write NSData to file
[_outputFileHandle writeData:data];
//close the file if written complete
[_outputFileHandle closeFile];
at the end of file written you should close the file.
You can also check the content written in file as NSString for debug point of view as mention above by #Glenn Smith:
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *outputFilePath = [documentsDirectory stringByAppendingPathComponent:#"file1.txt"];
NSError *error;
NSString *str = [NSString stringWithContentsOfFile:outputFilePath encoding:NSUTF8StringEncoding error:&error];
if (error != nil) {
NSLog(#"There was an error: %#", [error description]);
} else {
NSLog(#"Text file data: %#", str);
}

PList Chicken/Egg Scenario

I want to read/write to cache.plist
If I want to read an existing premade plist file stored in the resources folder I can go:
path = [[NSBundle mainBundle] bundlePath];
NSString *finalPath = [path stringByAppendingPathWithComponent#"cache.plist"];
NSMutableDictionary *root = ...
But then I wish to read it from the iPhone.
Can't, the Resources folder is only readable.
So I need to use:
NSDocumentDirectory, NSUserDomain,YES
So how can I have my plist file preinstalled to the Document Directory location?
Thus meaning I don't have to mess around with untidy code copying the plist file over at startup. (Unless that's the only way).
I know this isn't really what you're after, but as far as I know the only way to get the document into the Documents folder IS to actually copy it there...but only on the first startup. I'm going something similar for a sqlite database. Code is below, it works but please note it could do with a little bit of cleaning up:
// Creates a writable copy of the bundled default database in the application Documents directory.
- (void)createEditableCopyOfDatabaseIfNeeded {
// First, test for existence.
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:#"WordsDatabase.sqlite3"];
createdDatabaseOk = [fileManager fileExistsAtPath:writableDBPath];
if (createdDatabaseOk) return;
// The writable database does not exist, so copy the default to the appropriate location.
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"WordsDatabase.sqlite3"];
createdDatabaseOk = [fileManager copyItemAtPath:defaultDBPath toPath:writableDBPath error:&error];
}
Just call in your AppDelegate - not too messy really?
Easy. Look first to see if it's in the documents directory. If it's not, find it inside your app's Resources folder ([[NSBundle mainBundle] pathForResource...]), then copy it into the documents directory using [[NSFileManager defaultManager] copyItemAtPath:...]. Then use the fresh copy in the documents directory with impunity.
The final product
NSString *path = [[NSBundle mainBundle] bundlePath];
NSString *finalPath = [path stringByAppendingPathComponent:#"Cache.plist"];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *giveCachePath = [documentsDirectory stringByAppendingPathComponent:#"Cache.plist"];
BOOL fileExists = [fileManager fileExistsAtPath:giveCachePath];
if (fileExists) {
NSLog(#"file Exists");
}
else {
NSLog(#"Copying the file over");
fileExists = [fileManager copyItemAtPath:finalPath toPath:giveCachePath error:&error];
}
NSLog(#"Confirming Copy:");
BOOL filecopied = [fileManager fileExistsAtPath:giveCachePath];
if (filecopied) {
NSLog(#"Give Cache Plist File ready.");
}
else {
NSLog(#"Cache plist not working.");
}