52

Sorry, dumb question number 2 today. Is it possible to determine if a file is contained within the App Bundle? I can access files no problem, i.e.,

NSString *pathAndFileName = [[NSBundle mainBundle] pathForResource:fileName ofType:@"plist"];

But can't figure out how to check if the file exists there in the first place.

Regards

Dave

Magic Bullet Dave
  • 9,006
  • 10
  • 51
  • 81
  • 4
    Since [[NSBundle mainBundle] pathForResource:fileName ofType:@"plist"] will return NULL if the file does not exist, so I usually just check if (pathAndFileName != NULL) { //file exists } – jsherk Jul 10 '12 at 21:07
  • You can do it without code, too. See my thread on another forum: http://forums.macrumors.com/threads/xcode-6-how-do-i-view-all-files-in-my-main-bundle.1904024/ –  Jul 28 '15 at 23:58
  • @moonman239 The check I need to do, needs to be in code as I am preloading the app with cached thumbnail images so the initial run of the app is fast. I have another thread that then downloads a new data file. As the data is displayed the app needs to check if the image is in the bundle (the preloaded cached image). If not then the image is retrieved from a server and saved to a disk cache. Hope that makes sense. – Magic Bullet Dave Jul 29 '15 at 13:56
  • @MagicBulletDave I still don't understand. Does the cached image come with the app, or is it downloaded? If it comes with the app, then the code should theoretically have no need to check if the picture's there - the app can just assume it is. –  Jul 29 '15 at 18:07
  • It's a general purpose algorithm. The app comes with a data file in the form of a plist. Each row of data has a thumbnail image. On first load everything is in the bundle so can be displayed directly from it. Regularly a new plist is downloaded (with some existing and some new data). The existing data's images will be in the bundle, the new data's images will need to be downloaded and then cached to disk. So the chain of events is: Look in bundle first, then disk cache, finally if still no image then try and download it from the server. Make sense? – Magic Bullet Dave Jul 29 '15 at 18:46

5 Answers5

71
[[NSFileManager defaultManager] fileExistsAtPath:pathAndFileName];
Rob Napier
  • 286,113
  • 34
  • 456
  • 610
  • Doh! thanks Rob, have been using that for files in the documents directory! It's getting late. Thanks again. – Magic Bullet Dave Jan 08 '10 at 00:13
  • 5
    According to [this answer](http://stackoverflow.com/a/7487235/1226722), however, even Apple is advising to actually __"attempt an operation (such as loading a file or creating a directory), check for errors, and handle any error gracefully than it is to try to figure out ahead of time whether the operation will succeed"__. – gregoltsov Jul 19 '12 at 10:24
16

This code worked for me...

NSString *pathAndFileName = [[NSBundle mainBundle] pathForResource:fileName ofType:nil];
if ([[NSFileManager defaultManager] fileExistsAtPath:pathAndFileName])
{
    NSLog(@"File exists in BUNDLE");
}
else
{
    NSLog(@"File not found");
}

Hopefully, it will help somebody...

Arkady
  • 3,196
  • 24
  • 19
10

pathForResource will return nil if the resource does not exist. Checking again with NSFileManager is redundant.

Obj-C:

 if (![[NSBundle mainBundle] pathForResource:@"FileName" ofType:@"plist"]) {                                              
      NSLog(@"The path could not be created.");
      return;
 }

Swift 5:

 guard Bundle.main.path(forResource: "FileName", ofType: "plist") != nil else {
      print("The path could not be created.")
      return
 }
dcrow
  • 570
  • 5
  • 11
4
NSFileManager *fileManager = [NSFileManager defaultManager];
    NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    NSString *path = [documentsDirectory stringByAppendingPathComponent:@"filename"];
    if(![fileManager fileExistsAtPath:path])
    {
        // do something
    }
Iggy
  • 8,463
  • 3
  • 31
  • 21
1

Same as @Arkady, but with Swift 2.0:

First, call a method on mainBundle() to help create a path to the resource:

guard let path = NSBundle.mainBundle().pathForResource("MyFile", ofType: "txt") else {
    NSLog("The path could not be created.")
    return
}

Then, call a method on defaultManager() to check whether the file exists:

if NSFileManager.defaultManager().fileExistsAtPath(path) {
    NSLog("The file exists!")
} else {
    NSLog("Better luck next time...")
}
sudo make install
  • 5,629
  • 3
  • 36
  • 48