Objective-C代码,用于生成给定文件和目录的相对路径

Hil*_*ell 11 iphone file objective-c ios

给定文件路径和目录路径为NSStrings,是否有人使用Objective-C代码生成相对于目录的文件路径?

例如,给定目录/tmp/foo和文件/tmp/bar/test.txt,代码应该生成../bar/test.txt.

我知道Python至少有一种方法可以做到这一点:os.path.relpath.

Hil*_*ell 27

我决定只写它并分享,而不是继续捍卫我为什么需要这个.我的基础是os.path.relpathhttp://mail.python.org/pipermail/python-list/2009-August/1215220.html上的Python实现

@implementation NSString (Paths)

- (NSString*)stringWithPathRelativeTo:(NSString*)anchorPath {
    NSArray *pathComponents = [self pathComponents];
    NSArray *anchorComponents = [anchorPath pathComponents];

    NSInteger componentsInCommon = MIN([pathComponents count], [anchorComponents count]);
    for (NSInteger i = 0, n = componentsInCommon; i < n; i++) {
        if (![[pathComponents objectAtIndex:i] isEqualToString:[anchorComponents objectAtIndex:i]]) {
            componentsInCommon = i;
            break;
        }
    }

    NSUInteger numberOfParentComponents = [anchorComponents count] - componentsInCommon;
    NSUInteger numberOfPathComponents = [pathComponents count] - componentsInCommon;

    NSMutableArray *relativeComponents = [NSMutableArray arrayWithCapacity:
                                          numberOfParentComponents + numberOfPathComponents];
    for (NSInteger i = 0; i < numberOfParentComponents; i++) {
        [relativeComponents addObject:@".."];
    }
    [relativeComponents addObjectsFromArray:
     [pathComponents subarrayWithRange:NSMakeRange(componentsInCommon, numberOfPathComponents)]];
    return [NSString pathWithComponents:relativeComponents];
}

@end
Run Code Online (Sandbox Code Playgroud)

请注意,在某些情况下,这将无法正确处理.它碰巧处理我需要的所有情况.这是我用来验证正确性的轻薄单元测试:

@implementation NSStringPathsTests

- (void)testRelativePaths {
    STAssertEqualObjects([@"/a" stringWithPathRelativeTo:@"/"], @"a", @"");
    STAssertEqualObjects([@"a/b" stringWithPathRelativeTo:@"a"], @"b", @"");
    STAssertEqualObjects([@"a/b/c" stringWithPathRelativeTo:@"a"], @"b/c", @"");
    STAssertEqualObjects([@"a/b/c" stringWithPathRelativeTo:@"a/b"], @"c", @"");
    STAssertEqualObjects([@"a/b/c" stringWithPathRelativeTo:@"a/d"], @"../b/c", @"");
    STAssertEqualObjects([@"a/b/c" stringWithPathRelativeTo:@"a/d/e"], @"../../b/c", @"");
    STAssertEqualObjects([@"/a/b/c" stringWithPathRelativeTo:@"/d/e/f"], @"../../../a/b/c", @"");
}

@end
Run Code Online (Sandbox Code Playgroud)