Dave
Dave

Reputation: 88

NSFileManager not providing correct URLs when calling URLsForDirectory:inDomains:

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/Cac‌​hes/Experimental%20Post.cnt  

When I create a URL for searching:

file:///var/mobile/Applications/C63B378E-5EBE-417C-A465-8C3A3DCE013A/Library/Cac‌​hes/Experimental%20Post.cnt  

What the enumerator sees:

file:///private/var/mobile/Applications/C63B378E-5EBE-417C-A465-8C3A3DCE013A/Lib‌​rary/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.

Upvotes: 1

Views: 757

Answers (2)

Bart
Bart

Reputation: 21

/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?

Upvotes: 2

Shamim
Shamim

Reputation: 444

in the for loop, see if the url object have some return characters (like \r or \n) and remove it before proceeding.

Upvotes: 0

Related Questions