9

Is the NSSearchPathForDirectoriesInDomains function still the best way to get the path of the iPhone Documents directory? I ask because most topics I see on this are dated last year, and it still seems like a pretty cumbersome way of getting to a directory that is used commonly on iPhones. You'd think that there'd be a convenience method for this by now, similar to NSBundle's bundlePath, executablePath, etc.

Just to be clear, this means calling "NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)" and getting back an array with the Documents path at index 0.

iPhoneToucher
  • 299
  • 1
  • 3
  • 17

3 Answers3

22

The Core Data-based application template in Xcode provides this method:

- (NSString *)applicationDocumentsDirectory {

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
return basePath;
}

So it would seem that Apple continues to endorse getting the documents directory that way. You could put it into a category, I suppose, but I have found it is enough to include that method in the small handful of classes in a given app that need to do work in the documents directory. If you're doing a lot of file stuff all over the place, you might consider refactoring your code a bit to confine those tasks to one or two manager classes.

For me, at least, the third or fourth time I said "Hey, getting the docs directory is a pain in the neck" was the point where I realized some opportunities to shift the file juggling into a dedicated class.

Danilo Campos
  • 6,430
  • 2
  • 25
  • 19
17

The current Core Data iOS app template in Xcode provides this method:

// Returns the URL to the application's Documents directory.
- (NSURL *)applicationDocumentsDirectory
{
    return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}
Ivan Kovacevic
  • 1,322
  • 12
  • 30
  • Since Xcode 5, you should use `firstObject` instead of `lastObject` here. – Cœur Feb 19 '14 at 13:05
  • Well, I don't think that is true. I've just tried creating an 'Empty Application' new project in Xcode 5.0.2. I've checked the 'Use Core Data' checkmark. And inside the AppDelegate.m file I see that Xcode has generated the same method(using lastObject) for documents directory retrieval that I have provided in my answer. So using lastObject must be the correct way to do it. If you think otherwise, maybe you can elaborate it a bit more and provide a full answer to this question. – Ivan Kovacevic Feb 19 '14 at 13:46
  • 1
    `-lastObject` is an easy workaround from pre-Xcode 5 and is compatible with iOS2 while firstObject is only compatible with iOS4. The truth here is you want some `-anyObject` because the order of the returned objects is undocumented. But logic suggests that most suitable result was the first one added to the array, thus many people using `[0]`. Unfortunately, if array is empty, an exception would occur, so `-lastObject` was easier (not better) for some time, until `-firstObject` was made public with Xcode 5. Apple probably didn't update all the examples yet. – Cœur Feb 19 '14 at 15:15
  • 1
    I never actually bothered to think why Apple used lastObject instead, for example, objectAtIndex:0. So thanks for that explanation. However your initial comment("you SHOULD use" instead of "you can use") implies that using lastObject is wrong/deprecated and could produce an error. From everything I see it is irrelevant in this case weather you use lastObject or firstObject. Maybe Apple intends to return more objects from URLsForDirectory:inDomains: method in some case and will leave the actual document directory at the last place ;)So sticking to what they provide in the template may be better – Ivan Kovacevic Feb 19 '14 at 15:38
2

This works for me, pretty short and sweet

   #define kDOCSFOLDER [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"]

Cheers!

Jordan
  • 21,746
  • 10
  • 51
  • 63
  • 7
    Isn't the problem with this that it isn't guaranteed to be device-universal if Apple makes framework changes in the future? – iPhoneToucher Dec 04 '09 at 07:02
  • double bad. 1: hard coding the name means it will break when Apple changes it. 2: this is an abuse of the C preprocessor. Use a function instead. You might even make it an inline function, but that reeks of premature optimization – Jean-Denis Muys Mar 12 '15 at 10:02