繁体   English   中英

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

[英]Objective-C code to generate a relative path given a file and a directory

给定一个文件路径和一个目录路径作为NSString s,有没有人有 Objective-C 代码来生成文件的路径,相对于目录?

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

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

我没有继续捍卫我为什么需要这个,而是决定写下来并分享。 我基于 Python 的os.path.relpathhttp://mail.python.org/pipermail/python-list/2009-August/1215220.ZFC35FZ30D5FC69D2368C

@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

这是希尔顿代码的 Swift 版本

extension String {
    var pathComponents: [String] {
        return (self as NSString).pathComponents
    }

    static func pathWithComponents(components: [String]) -> String {
        return NSString.pathWithComponents(components)
    }

    func stringWithPathRelativeTo(anchorPath: String) -> String {
        let pathComponents = self.pathComponents
        let anchorComponents = anchorPath.pathComponents

        var componentsInCommon = 0
        for (c1, c2) in zip(pathComponents, anchorComponents) {
            if c1 != c2 {
                break
            }
            componentsInCommon += 1
        }

        let numberOfParentComponents = anchorComponents.count - componentsInCommon
        let numberOfPathComponents = pathComponents.count - componentsInCommon

        var relativeComponents = [String]()
        relativeComponents.reserveCapacity(numberOfParentComponents + numberOfPathComponents)
        for _ in 0..<numberOfParentComponents {
            relativeComponents.append("..")
        }
        relativeComponents.appendContentsOf(pathComponents[componentsInCommon..<pathComponents.count])

        return String.pathWithComponents(relativeComponents)
    }
}

有什么原因你不能只使用完整路径吗? imageNamed:完全支持。 根是您应用的主要捆绑包。

myImageView.image = [UIImage imageNamed:@"/Path/To/Some/File.png"];

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM