I'm trying to copy an item from orginal path for destination path, but it throw exception while copying file. Any body can examine why? Thank in advance.
- (void) copyFile:(NSString*) fromPath toPath:(NSString*) toPath
{
NSError *error = nil;
NSFileManager* fileManager = [NSFileManager defaultManager];
BOOL success = [fileManager fileExistsAtPath:toPath];
if (success)
[fileManager removeItemAtPath:toPath error:&error];
success = [fileManager copyItemAtPath:fromPath toPath:toPath error:&error];
if (!success) {
NSLog(#"fail to copy signature temp file!");
}
}
I receive no error logs!
I have seen this error several times in relation to delegates.
Have you set the file manager's delegate? If you have be sure that the delegate is still valid when that method is executed. Add a log statement to be sure.
If you haven't set one it might be worth setting one just to see if that has an effect.
Related
So, I searched the net and stackoverflow, checked the threads mentioned above this text box as possible already asked questions but the answers or tips couldn't help me because the code at first was OK and there was nothing wrong with it, it shouldn't be, because it is just not that hard. But for some reason I can not delete a earlier created file. The code:
NSArray *dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, true);
NSString *dbFile = [[NSString alloc] initWithString:[dirPaths[0] stringByAppendingPathComponent:#"database.db"]];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
BOOL fileExists = [fileManager fileExistsAtPath:dbFile];
NSLog(#"Path to file: %#", dbFile);
NSLog(#"File exists: %d", fileExists);
NSLog(#"Is deletable file at path: %d", [fileManager isDeletableFileAtPath:dbFile]);
if (fileExists) {
BOOL success = [fileManager removeItemAtPath:dbFile error:&error];
if (!success) { NSLog(#"Error: %#", [error localizedDescription]); }
else { NSLog(#"probably deleted the file!"); }
}
The output:
2014-09-15 17:29:25.058 test[13862:60b] Path to file: /var/mobile/Applications/BB708129-C504-4E84-9C08-DF4ACE1369DC/Documents/database.db
2014-09-15 17:29:25.060 test[13862:60b] File exists: 1
2014-09-15 17:29:25.061 test[13862:60b] Is deletable file at path: 1
2014-09-15 17:29:25.063 test[13862:60b] probably deleted the file!
But every time I run the code It says the file exists and does not get deleted. Am I missing something?
I have a newsstand app which has magazines and uses the newsstand framework. I realized there was something wrong when deleting the magazines and/or when downloading them because when I accessed settings/usage my app keeps growing in memory usage when downloading and deleting the same magazine.
Found the issue... when downloading the issue in the delegate method:
-(void)connectionDidFinishDownloading:(NSURLConnection *)connection destinationURL:(NSURL *)destinationURL
I just needed to add something like this at the end:
NSError *error;
[[NSFileManager defaultManager] removeItemAtPath:[destinationURL path] error:&error];
if (error){
NSLog(#"ERROR:%#", error);
}
Even the directory is called "caches" you need to manually delete. Ok problem solved but what about the customers who already download my app and have tons of MBs dead in the cache directory.
I wanted to know how to get this directory and delete everything on it at launch and only once...
I can do it only once using a NSUserdefault but how do I get this directory and delete any zip files in it... an example of this directory and a file within is:
/private/var/mobile/Applications/1291CC20-C55F-48F6-86B6-B0909F887C58/Library/Caches/bgdl-280-6e4e063c922d1f58.zip
but this path varies with the device. I want to do this at launch so I'm sure there are no downloads in progress but any other solutions are welcome, thanks in advance.
Everything that you need is enumerate all files from Caches directory and remove ones that have zip extension:
- (void)removeZipFilesFromCachesDirectory {
static NSString *const kZIPExtension = #"zip";
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *cachesDirectoryPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSError *error = nil;
NSArray *fileNames = [fileManager contentsOfDirectoryAtPath:cachesDirectoryPath error:&error];
if (error == nil) {
for (NSString *fileName in fileNames) {
NSString *filePath = [cachesDirectoryPath stringByAppendingPathComponent:fileName];
if ([filePath.pathExtension.lowercaseString isEqualToString:kZIPExtension]) {
NSError *anError = nil;
[fileManager removeItemAtPath:filePath error:&anError];
if (anError != nil) {
NSLog(#"%#", anError);
}
}
}
} else {
NSLog(#"%#", error);
}
}
Using the line below,
[fileManager copyItemAtPath:sourcePath toPath:targetPath error:&error];
We can copy a folder but if the folder already exists it throws an exception "File Exists".
In order to overwrite a single file, we can achieve it through the following lines:
NSData *myData = [NSData dataWithContentsOfURL:FileURL]; /fetch single file
[myData writeToFile:targetPath atomically:YES];
But I want to copy an already existing folder i.e, overwrite.
Edit :
Simple Possibility , I can remove the items before copying them.
Please suggest any more possibilities.
The default behavior of NSFileManager method is to throw an exception/error "File Exists." when the file exists. But still if you want to overwrite using NSFileManager then it provides one api for that which is mentioned below replaceItemAtURL as well in first solution:-
Also there are three solutions to achieve that
First Solution
[filemanger replaceItemAtURL:url1
withItemAtURL:url2
backupItemName:#"/Users/XYZ/Desktop/test.xml"
options:NSFileManagerItemReplacementUsingNewMetadataOnly
resultingItemURL:nil error:nil];
Using the above API you can overwrite the file contents. But before that you have to take the backup of your source path in your temporary directory.
Second Solution
Already you have mentioned in your question using NSData writeToUrl.
Third Solution
trojanfoe has mentioned in their answer. i.e. remove the item being overwritten beforehand.
I would like to add one more using delegate, in order to override files with copyItemAtPath (NSFileManager) function use:
[[NSFileManager defaultManager] setDelegate:self];
[[NSFileManager defaultManager] copyItemAtPath:fileOrigin toPath:fileDestin error:&error];
and implement the delegates optional function:
- (BOOL)fileManager:(NSFileManager *)fileManager shouldProceedAfterError:(NSError *)error copyingItemAtPath:(NSString *)srcPath toPath:(NSString *)dstPath{
if ([error code] == NSFileWriteFileExistsError) //error code for: The operation couldn’t be completed. File exists
return YES;
else
return NO;
}
Remove the item first, with:
[fileManager removeItemAtPath:targetPath error:NULL];
(i.e. ignoring any error)
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath])
[[NSFileManager defaultManager] removeItemAtPath:filePath error:nil];
I am trying to write some image data to disk on iOS, but while it's working perfectly in the Simulator, when I try it on a real iPad it fails (returns 0).
BOOL success = [[NSFileManager defaultManager] createFileAtPath:filePath contents:imageData attributes:nil];
The path in question looks something like this: /Library/Caches/_0_0_0_0_1100_1149.jpg and I've also tried /Documents/....
Is there any way to actually get an error code or something beyond just success/fail?
The simulator does not simulate the sandboxing of the file system that is enforced on a device. You can write anywhere on the sim, but on a device writing anywhere but one of your designated directories will fail.
I'm guessing that your path is badly formed somehow. Try logging your path and the path you get from NSCachesDirectory (as shown in your second post.) They are almost certainly different.
Turns out you have to programmatically obtain the directory. The iOS file system is not sandboxed like I expected.
NSString* pathRoot = NSSearchPathForDirectoriesInDomains( NSCachesDirectory, NSUserDomainMask, YES )[0];
If you're writing image data, why not try writing via NSData's [writeToFile: options: error:] method, the "error" parameter for which can give you some really useful hints as to why your file isn't writing.
This is illogical:
if ( !( [ fileManager copyItemAtPath:resourceDBFolderPath toPath:documentDBFolderPath error:&error ]))
You are checking if the method exists, not if it succeeded!!
I have some relevant code I've used in my project, I hope it may be help you some way or another:
-(void)testMethod {
NSString *resourceDBFolderPath;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *documentDBFolderPath = [documentsDirectory stringByAppendingPathComponent:#"plans.gallery"];
BOOL success = [fileManager fileExistsAtPath:documentDBFolderPath];
if (success){
NSLog(#"Success!");
return;
}
else {
//simplified method with more common and helpful method
resourceDBFolderPath = [[NSBundle mainBundle] pathForResource:#"plans" ofType:#"gallery"];
//fixed a deprecated method
[fileManager createDirectoryAtPath:documentDBFolderPath withIntermediateDirectories:NO attributes:nil error:nil];
[fileManager copyItemAtPath:resourceDBFolderPath toPath:documentDBFolderPath
error:&error];
//check if destinationFolder exists
if ([ fileManager fileExistsAtPath:documentDBFolderPath])
{
//FIXED, another method that doesn't return a boolean. check for error instead
if (error)
{
//NSLog first error from copyitemAtPath
NSLog(#"Could not remove old files. Error:%#", [error localizedDescription]);
//remove file path and NSLog error if it exists.
[fileManager removeItemAtPath:documentDBFolderPath error:&error];
NSLog(#"Could not remove old files. Error:%#", [error localizedDescription]);
return;
}
}
}
}
I'm trying to copy a folder and it's contents to a sub-directory in the documentation directory and it's failing with the error:
"The operation couldn’t be completed. No such file or directory"
First I try to create a folder in the documentation directory like this:
NSString *diagramsDirectory = [docDirectory stringByAppendingPathComponent:#"Diagrams"];
if (![fileManager fileExistsAtPath:docDirectory isDirectory:&isDirectory] || !isDirectory)
{
NSError *error = nil;
NSDictionary *attr = [NSDictionary dictionaryWithObject:NSFileProtectionComplete
forKey:NSFileProtectionKey];
[fileManager createDirectoryAtPath:diagramsDirectory
withIntermediateDirectories:NO
attributes:attr
error:&error];
if (error) {
NSLog(#"error creating dir. path: %#", [error localizedDescription]);
}
}
NSLog(#"diagrams directory = %#", diagramsDirectory);
The console log seems to indicate this works:
diagrams directory = /Users/../iPhone Simulator/../Library/Documentation/Diagrams
However, when I then try to copy a folder called "Diagrams" from a directory on the Mac:
NSString *pathToDirectories = #"/User/Desktop/Project Resource Files/Files/";
NSError *error = nil;
NSArray *folders = [fileManager contentsOfDirectoryAtPath:pathToDirectories error:&error];
for (NSString *folder in folders) {
if ([folder isEqualToString:#"Diagrams"]) {
[self copyFolderAtPath:folder toDestinationFolderAtPath:docDirectory];
}
which calls the "copyFolderAtPath" method:
- (BOOL)copyFolderAtPath:(NSString *)sourceFolder toDestinationFolderAtPath:(NSString *)destinationFolder
{
destinationFolder = [destinationFolder stringByAppendingPathComponent:[sourceFolder lastPathComponent]];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error = nil;
// check for destination folder
if ([fileManager fileExistsAtPath:destinationFolder])
{
if (![fileManager removeItemAtPath:destinationFolder error:&error])
{
NSLog(#"Could not remove old files. Error: %#", error);
return NO;
}
}
error = nil;
// copy destination
if (!([fileManager copyItemAtPath:sourceFolder toPath:destinationFolder error:&error])) {
NSLog(#"failed copying file at path %# to path %#. Error %#", sourceFolder, destinationFolder, error);
return NO;
}
return YES;
}
it returns "no" and I get the error.
Anyone got an idea what I'm doing wrong?
The device (and therefore the simulator) is isolated from the operating system so you cannot directly do file system copies. Imagine even if it let you do it from the simulator, how would a disconnected device running your app access the OS filesystem?
You will have to look into other options like having an application on the mac that opens sockets or having an http end point on the mac that the device copies from. Other options include syncing documents via iCloud or another cloud service. You can also transfer files via iTunes. I'm sure there's many other options ... Also checkout this