Check if file exists at URL instead of path
Asked Answered
P

4

72

How can I check if a file exists at a URL (instead of a path), in order to set a pre-populated default store into the iPhone Simulator:

NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Food.sqlite"];
/*
 Set up the store.
 For the sake of illustration, provide a pre-populated default store.
 */
NSFileManager *fileManager = [NSFileManager defaultManager];
// If the expected store doesn't exist, copy the default store.
if (![fileManager fileExistsAtPath:storePath]) {
    NSString *defaultStorePath = [[NSBundle mainBundle] pathForResource:@"Food" ofType:@"sqlite"];
    if (defaultStorePath) {
        [fileManager copyItemAtPath:defaultStorePath toPath:storePath error:NULL];
    }
}

I've read that in recent versions of the templates, the applicationDocumentsDirectory method returns an URL, so I've changed the code to use NSURL objects to represent the file path. But at [fileManager fileExistsAtPath:storePath], I need to change fileExistsAtPath to something like fileExistsAtURL (obviously it doesn't exist).

I've checked the NSFileManager Class Reference and I didn't find any suitable task suited for my purpose.

Any hints please?

Preciado answered 24/10, 2011 at 16:33 Comment(0)
L
135
if (![fileManager fileExistsAtPath:[storeURL path]]) 
...

From the documentation:

If this URL object contains a file URL (as determined with isFileURL), the return value of this method is suitable for input into methods of NSFileManager or NSPathUtilities. If the path has a trailing slash it is stripped.

Loreleilorelie answered 24/10, 2011 at 18:38 Comment(3)
was having an error using [url absoluteString]. DO NOT USE absoluteString. Cheers.Henriques
Thank you codrut!!!!! absoluteString was messing with my file. Now using .path instead of .absoluteString everything is fine!Diluent
It should. The store URL is just different because it is not in the app sandbox but in a shared container folder. This implementation detail is abstracted away, so it should work.Loreleilorelie
C
19

For a file system URL NSURL itself has a method to check the reachability of an URL

NSError *error;
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Food.sqlite"];
if ([storeURL checkResourceIsReachableAndReturnError:&error]) {
  // do something
} else {
  NSLog(@"%@", error);
}
Charmian answered 31/12, 2015 at 9:3 Comment(5)
Most direct solution. There is no need to rely on fileManager.Drugstore
This has a problem in Swift land, in that checkResourceIsReachable() throws an exception (!) if the item is not reachable. So you have to go to all the trouble of catching an exception rather than checking a return result...Rosemarierosemary
@KendallHelmstetterGelner Actually you have not. See my answer hereCharmian
Thanks, I took a look and commented on it. I like the idea of the try? wrapper but I really don't like calling something I know will mostly be throwing exceptions as I don't want that overhead.Rosemarierosemary
@KendallHelmstetterGelner Swift exceptions have no more overhead than 'if / then / else'. That why they must be dealt with in the same scope they are thrown. They are really still just return codes. See the 'Note:' in the swift book error handling section -> ... error handling in Swift does not involve unwinding the call stack, a process that can be computationally expensive. As such, the performance characteristics of a throw statement are comparable to those of a return statement.Mezcaline
R
5
if (![fileManager fileExistsAtPath:[storeURL path]]) 

is ok, but be carful : for an url like :

..../Documents/1158a3c96ca22c41b8e731b1d1af0e1e?d=mm&s=50

[storeURL path] will give you that path (it apply to [storeURL lastPathComponent] :

..../Documents/1158a3c96ca22c41b8e731b1d1af0e1e

but if you use lastPathComponent on a string like /var/mobile/Applications/DB92F4DC-49E4-4B4A-8271-6A9DAE6963BC/Documents/1158a3c96ca22c41b8e731b1d1af0e1e?d=mm&s=50, it will give you 1158a3c96ca22c41b8e731b1d1af0e1e?d=mm&s=50

And that's good, since in a url, '?' is used for GET parameters, but if you mix with string, you might have troubles.

Romeo answered 3/9, 2012 at 9:39 Comment(0)
T
2

For anyone reading this on Swift 5 days, I achieved it in this way:

func doesFileExist(url: URL) -> Bool {
    let fileManager = FileManager.default
    return fileManager.fileExists(atPath: url.path)
}
Taxation answered 27/9, 2022 at 16:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.