Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

stringByAppendingPathComponent, hows it work?

EDIT_v002

I have had a look at all the comments and I am starting to see what I should be doing. To that end I have modified my code (see below) I have changed newPath to a NSString, removed the [[alloc] init] and the end [release] as its now handled by the system. I am using stringByAppendingPathComponent, letting it add a separator between rootPath and fileName before its assigned to the NSString. It does work, and I ran it through the static analyser with no problems.

// ------------------------------------------------------------------- **
// DISC: FILEWALKER ..... (cocoa_fileWalker.m)
// DESC: List all "*.png" files in specified directory
// ------------------------------------------------------------------- **
#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    NSString *fileName;
    NSDictionary *attrDir;
    NSError *myError;
    NSNumber *fileSize;
    NSFileManager *manager = [NSFileManager defaultManager];
    NSString *rootPath = [@"~/Pictures/Ren/PRMan" stringByExpandingTildeInPath];
    NSString *newPath;

    NSLog(@"Home: %@",rootPath);

    for(fileName in [manager enumeratorAtPath:rootPath]){
        if ([[fileName pathExtension] isEqual:@"png"]) {    

            newPath = [rootPath stringByAppendingPathComponent:fileName];   
            attrDir = [manager attributesOfItemAtPath:newPath error:&myError];
            fileSize = [attrDir objectForKey: @"NSFileSize"];
            NSLog(@"File: %@ Size: %@", newPath, fileSize);
        }
    }
    [pool drain];
    return 0;
}
// ------------------------------------------------------------------- **

gary

like image 861
fuzzygoat Avatar asked Sep 28 '09 21:09

fuzzygoat


2 Answers

stringByAppendingPathComponent, hows it work?

Simple. You want to append a path component. You send that message to the string you want to append a path component to, passing the path component you want to append.

Path components are not the slashes; if they were, the pathComponents method would return nothing but an array of slashes. Path components are the parts between the slashes (although there is a special case, described in the definition of pathComponents).

The slash is the path separator. This is hard-coded inside of Cocoa; it's currently (and likely to always be) a slash. So, if you really wanted to append a slash to a string, the most likely reason would be that you want to append a path separator, not a path component.

    [newPath setString:rootPath];
    [newPath appendString:@"/"];
    [newPath appendString:fileName];

fileName is the component you want to add. Use stringByAppendingPathComponent: and pass fileName, not a slash.

As for whether your example leaks: Well, does an object fall out of scope without getting released? The answer to that question is the answer to whether it's a leak. If you're not sure, review the memory management rules.

like image 99
Peter Hosey Avatar answered Oct 17 '22 23:10

Peter Hosey


All the existing answers are leaking the original testPath string. For something as simple as this, why has nobody recommended -[NSMutableString appendString:] intead?

[testPath appendString:@"/"];

There's no equivalent to -stringByAppendingPathComponent: for NSMutableString, but it looks like he's just trying to add a slash, not a path component anyway. If you really wanted to add a path component, you could do this:

[testPath setString:[testPath stringByAppendingPathComponent:@"..."]];

It's an annoying workaround, but as @dreamlax points out, -stringByAppendingPathComponent: always returns an immutable string, even when called on an NSMutableString object. :-(

like image 37
Quinn Taylor Avatar answered Oct 17 '22 23:10

Quinn Taylor