Вместо того, чтобы продолжать защищать, зачем мне это нужно, я решил просто написать это и поделиться.Я основал это на реализации Python os.path.relpath
на http://mail.python.org/pipermail/python-list/2009-August/1215220.html
@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
Обратите внимание, что в некоторых случаях это не будет правильно обрабатываться.Это случается со всеми делами, которые мне нужны.Вот скудный юнит-тест, который я использовал для проверки правильности:
@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