Is there a way to detect if a file located on iCloudDrive has been moved to the iCloudDrive trash?
I could check the URL to contain ".Trash" but I am looking for an official way to retrieve this.
To detect if a file/folder is in Trash use following code:
NSURLRelationship relationship;
NSError *error;
[[NSFileManager defaultManager] getRelationship:&relationship ofDirectory:NSTrashDirectory inDomain:0 toItemAtURL:URL error:&error];
if (relationship == NSURLRelationshipContains) {
//file is in trash
}
Found a decent way to detect this. Starting with iOS11 the following approach is possible:
NSURL* fileURL; // any file URL pointing to a file resource
NSURL* trashURL = [NSFileManager.defaultManager URLForDirectory:NSTrashDirectory inDomain:NSUserDomainMask appropriateForURL: fileURL create:NO error:NULL];
if (trashURL && [fileURL.path hasPrefix:trashURL.path])
{
// fileURL is located in the iCloudDrive trash
}
Related
I want to start off by saying that this block of code worked before the implementation and roll out of iOS 7.
Basically I have a file name that I'm looking for in the NSCachesDirectory, so I create a URL object as my search item. Then I enumerate the directories (using the same NSFileManager object) and look for file names that equal each other, and that's how I know the file exists.
+ (BOOL)itemExistsInMemory:(NSString *)itemName
{
BOOL itemExists = NO;
NSFileManager *fileManager = [[NSFileManager alloc] init];
NSArray *mySandboxDirs = [fileManager URLsForDirectory:NSCachesDirectory inDomains:NSUserDomainMask];//get the directories for the application
NSURL *searchForURL = [[mySandboxDirs lastObject] URLByAppendingPathComponent:[NSString stringWithFormat:#"%#%#", itemName, FileNameAppendix]];//look for the specific file
NSArray *enumerator = [fileManager contentsOfDirectoryAtURL:[mySandboxDirs lastObject] includingPropertiesForKeys:[NSArray arrayWithObjects:NSURLNameKey, NSURLIsRegularFileKey, NSURLCreationDateKey, nil] options:NSDirectoryEnumerationSkipsHiddenFiles error:nil];
for(NSURL *url in enumerator)
{//find out if any of the URLs within the NSCachesDirectory match what we're looking for
NSNumber *isRegularFile = nil;
[url getResourceValue:&isRegularFile forKey:NSURLIsRegularFileKey error:NULL];
if([isRegularFile boolValue])
{
if([url relativeString] isEqualToString:[searchForURL relativeString]])
{
itemExists = YES;
break;
}
}
}
return itemExists;
}
The file DOES INDEED EXIST in the NSCachesDirectory, however, the code doesn't find it because the searchForURL object was created without a path component (the path component is private/...). Why? Even stranger is that I save the data to a URL that's created with the
[[mySandboxDirs lastObject] URLByAppendingPathComponent:[NSString stringWithFormat:#"%#%#", itemName, FileNameAppendix]];
instruction! So it doesn't include the private/ path component in the URL, but when I write the data with [NSData writeToURL:] it "redirects" it to the private/ directory.
So why can't [NSFileManager URLsForDirectory: inDomains:] get me the correct directories for NSCachesDirectory?
More info moved from the comment for better formatting:
By the way, here's an example of what's contained in the URLs I'm creating and looking for ->
When I create a URL for saving:
file:///var/mobile/Applications/C63B378E-5EBE-417C-A465-8C3A3DCE013A/Library/Caches/Experimental%20Post.cnt
When I create a URL for searching:
file:///var/mobile/Applications/C63B378E-5EBE-417C-A465-8C3A3DCE013A/Library/Caches/Experimental%20Post.cnt
What the enumerator sees:
file:///private/var/mobile/Applications/C63B378E-5EBE-417C-A465-8C3A3DCE013A/Library/Caches/Experimental%20Post.cnt
I could simply take the URLs that the enumerator comes up with and remove the "private" part of the URL so that the strings match and I can proceed, but I'd like to understand why this is happening. Please also note that this only happens when you put the app on an iDevice since the directories are different than when you simulate it with the iOS Simulator.
Thanks to anyone that can be of assistance.
/var is a symlink to /var/private, use [NSURL URLByResolvingSymlinksInPath] to resolve the symlink.
In your example:
for(NSURL *url in enumerator) {
NSURL *resolvedSymlinksURL = [url URLByResolvingSymlinksInPath];
...
}
More detailled discussion: What does the /private prefix on an iOS file path indicate?
in the for loop, see if the url object have some return characters (like \r or \n) and remove it before proceeding.
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 Making an Audio recorder(m4a extension files). I am Giving a particular URL for the output of the recorded File(in directory).
I am able to play it, save the path of the file in database and can retrieve it later. EVery thing is going Fine. BUT I am not able to delete the saved/unsaved files. Every time I record an audio , the file is taking a permanent space. Am not able to delete them.
I tried it over internet(stackoverflow ofcourse). I got Links like this: I have video URL and want to delete it from the iPhone using this URl
But they are showing COCOA ERROR 4 when ever i try to delete them using codes like this: [[NSFileManager defaultManager] removeItemAtPath:strPath error:&error];
Please suggest, and reply
You typically accomplish this for resources you've saved in your Apps documents directory like this:
unlink([pathForURL UTF8String]);
where pathForURL is an NSString that describes the path to the resource you're deleting.
This is the path earlier i was getting , at which i was unable to write file
/var/mobile/Applications/8584F54E-75D2-4833-8826-29C125E53DBC/Library/Documentation/291013193758w.png
This morning, I just run my code once again ,. now its showing path
/var/mobile/Applications/DDA14123-6A88-4756-B2E4-C4A3AA39AA5B/Documents/291013081335test.png
on this path am able to write my file
the Difference between two paths is that, first one is of Library/Documentation , where as second one is of Documents
dont know the difference, but it is working now
There may be case that file path which you provide is not correct. If its correct then try following with URL, it might solve your issue
NSString *str= [outputFieldURL absoluteString];
NSError *error;
NSURL *url = [NSURL URLWithString:str];
BOOL success = [[NSFileManager defaultManager] removeItemAtURL:url error:&error];
if (!success) {
NSLog(#"Error removing file at path: %#", error.localizedDescription);
}
else
{
NSLog(#"File removed at path: %#", error.localizedDescription);
}
}
Before deleting the file you have to check file there or not :
NSFileManager* manager = [[NSFileManager alloc] init];
if ([manager fileExistsAtPath:path]) {
[manager removeItemAtPath:path error:&error];
}
A little embarrassing question, but I can find an answer which works in my case... I need to put some xml file (settings.xml) in order to read some data from it during application runtime.
According to some answers here and not only here, I have putted it here:
~/Library/Application Support/iPhone Simulator/5.0/[AppUUID]/Documents
and I'm trying to use it as follows:
// Loading data from external XML File
NSURL *url = [[NSBundle mainBundle]
URLForResource: #"settings" withExtension:#"xml"];
NSError *err;
if ([url checkResourceIsReachableAndReturnError:&err] == NO){
NSLog(#"FILE NOT FOUND");
}
Result: "FILE NOT FOUND".
I've tried to do put the file under any possible directory in
~/Library/Application Support/iPhone Simulator/5.0/[AppUUID]/ and efect is still the same.
I'm using XCode 4.2
If you are putting the file into the .../Documents folder then you need to use the following code to access it (you are looking for it in the App Bundle, which is a different location altogether):
NSString *docFolder = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *filename = [docFolder stringByAppendingPathComponent:#"settings.xml"];
if ([[NSFileManager defaultManager] fileExistsAtPath:filename])
{
// Read file
}
else
{
NSLog(#"settings.xml file not found!");
}
I'm trying to copy a downloaded file to a specific folder in the app's documents directory but can't seem to get it working. The code I'm using is:
NSString *itemPathString = #"http://pathToFolder/folder/myFile.doc";
NSURL *myUrl = [NSURL URLWithString:itemPathString];
NSArray *paths = [fm URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask];
NSURL *folderPath = [[paths objectAtIndex:0] URLByAppendingPathComponent:#"folder"];
NSURL *itemURL = [documentsPath URLByAppendingPathComponent:#"myFile.doc"];
// copy to documents directory asynchronously
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSFileManager *theFM = [[NSFileManager alloc] init];
NSError *error;
[theFM copyItemAtURL:myUrl toURL:itemURL error:&error];
}
});
I can retrieve the file OK but can't copy it. Can anyone tell me if there's anything wrong with the above code?
If downloading a file from a server, if it's a reasonably small file (e.g. measured in kb, not mb), you can use dataWithContentsOfURL. You can use that method to load the file into memory, and then use the NSData instance method writeToFile to save the file.
But, if it's a larger file, you will want to use NSURLConnection, which doesn't try to hold the whole file in memory, but rather writes it to the file system when appropriate. The trick here, though, is if you want to download multiple files, you either have to download them sequentially, or encapsulate the NSURLConnection and the NSOutputStream such that you can have separate copies of those for each simultaneous download.
I have uploaded a project, Download Manager that demonstrates what a NSURLConnection implementation might look like, but it's non-trivial. You might rather want to contemplate using an established, third-party library, such as ASIHTTPRequest or RestKit.
If you want to access a folder with a given name you should check if it exists and if not create it. That could quite easy be done like this:
NSString *folder = [documentsPath stringByAppendingPathComponent:folderName];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error = nil;
if (![fileManager fileExistsAtPath:folder]) {
[fileManager createDirectoryAtPath:folder withIntermediateDirectories:YES attributes:nil error:&error];
}
if (error != nil) {
NSLog(#"Some error: %#", error);
return;
}
EDIT
If you want to check if the folder was created properly on your device got to Organizer -> Devices -> [YourDevelopingDeviceWhereTheAppWasInstalled] -> Applications -> [YourApplication]
In the lower section you should at least see some folders like Documents. And if successful your created folders as well.
You need to create any intermediate directories prior to copying files. Check in the Simulator folder to see wether the "folder" directory is created in the applications Documents-folder.
Path to simulator is /Users/$username/Library/Application Support/iPhone Simulator/