views:

340

answers:

1

Hi,

For my app I need to use the Carbon file manager API to get the size of a folder (NSEnumerator is slow, and using NSTask with a shell command is even worse). I've imported the Carbon framework, and I'm using this method to get the size of a folder:

http://www.cocoabuilder.com/archive/message/cocoa/2005/5/20/136503

It uses an FSRef as an argument, and my path string is currently an NSString. I tried using this to convert the NSString to an FSRef:

FSRef f;
     OSStatus os_status = FSPathMakeRef((const UInt8 *)[filePath fileSystemRepresentation], &f, NULL);

     if (os_status != noErr) {
      NSLog(@"fsref creation failed");
     }

And then I called the folder size method:

[self fastFolderSizeAtFSRef:f];

However when I try to build, I get this error regarding the above line:

error: incompatible type for argument one of 'fastFolderSizeAtFSRef:'

Any help would be appreciated. Thanks

+3  A: 

Hi PCWiz,

The "fastFolderSizeAtFSRef" method takes an FSRef* (FSRef pointer). You're giving it an FSRef. It's a one character fix, luckily enough. You have:

[self fastFolderSizeAtFSRef:f];

Simply change that to:

[self fastFolderSizeAtFSRef:&f];

And you should be good to go. However, I was implementing this same method yesterday but was having trouble creating the FSRef itself. I eventually went with the following code:

FSRef convertNSStringToFSRef(NSString * theString) {
    FSRef output;
    const char *filePathAsCString = [theString UTF8String];
    CFURLRef url = CFURLCreateWithBytes(kCFAllocatorDefault, 
                                        (const UInt8 *)filePathAsCString, 
                                        strlen(filePathAsCString),
                                        kCFStringEncodingUTF8,
                                        NULL);
    CFURLGetFSRef(url, &output);
    CFRelease(url);
    return output;
}

This has been working flawlessly for me.

EDIT: I just open sourced the code that I'm using this in. It's these files:

This file adds a method to NSFileManager that uses an FSRef to find the complete size of a directory. This file adds a method to NSString that will convert it to an FSRef.
Everything happens on line 46 of this file.

Dave DeLong
Hi Dave,Thanks for that method. I put it in my class and then tried this:[self fastFolderSizeAtFSRef:[self convertNSStringToFSRef:filePath]];Where filePath is my NSString containing the path. And I get a "warning 'AppController' may not respond to '-convertNSStringToFSRef'". I have a feeling that I'm calling your method the wrong way...Thanks
macatomy
Yeah, I wrote it as a C function. If you want it as a method, change the first line to `- (FSRef) convertNSStringToFSRef:(NSString *)theString {`. Then don't forget that ampersand! This method returns an FSRef, and like I answered above, the fastFolderSize method wants an FSRef pointer. I'm editing my answer with a bit more information...
Dave DeLong
Thanks Dave, can I have permission to use those 2 methods in my app? The ones in NSFileManager+FileSize.m?P.S. My app is freeware (and possibly Open source) :)
macatomy
Also, I tried those 2 methods and they do work (very fast as well). The only problem is that for certain folders (.app bundles in my case) there's a slight discrepancy in the size that Finder reports and the size that the method returns.For example, I tried the app bundle Acorn.app. Finder reports 15.8MB, the method reports 14.6MB.Any ideas? Thanks
macatomy
Yeah, feel free to use them. I'll look into the size discrepancy and see if I can figure anything out.
Dave DeLong
Thanks :) I also do have a theory about the size discrepancy. If I'm not mistaken, Finder has a minimum file size for all files. For example a text file that is 8 bytes in reality would show as 4KB in Finder. I guess these could be adding up, creating the size problem.
macatomy