[英]Objective-C code to generate a relative path given a file and a directory
Given a file path and a directory path as NSString
s, does anyone have Objective-C code to generate a path to the file, relative to the directory?给定一个文件路径和一个目录路径作为NSString
s,有没有人有 Objective-C 代码来生成文件的路径,相对于目录?
For example, given the directory /tmp/foo
and the file /tmp/bar/test.txt
, the code should produce ../bar/test.txt
.例如,给定目录/tmp/foo
和文件/tmp/bar/test.txt
,代码应该生成../bar/test.txt
。
I know Python, at least, has a method to do this: os.path.relpath
.我知道 Python 至少有一种方法可以做到这一点: os.path.relpath
。
Rather than continue to defend why I need this, I decided to just write it and share.我没有继续捍卫我为什么需要这个,而是决定写下来并分享。 I based this off of an implementation of Python's os.path.relpath
at http://mail.python.org/pipermail/python-list/2009-August/1215220.html我基于 Python 的os.path.relpath
在http://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
Note that there are some cases this won't correctly handle.请注意,在某些情况下,这将无法正确处理。 It happens to handle all the cases I need.它恰好可以处理我需要的所有情况。 Here is the skimpy unit test I used to verify correctness:这是我用来验证正确性的简单单元测试:
@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
Here is a Swift version of Hilton's code这是希尔顿代码的 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)
}
}
Is there some reason you can't just use the full path?有什么原因你不能只使用完整路径吗? imageNamed:
totally supports that. imageNamed:
完全支持。 The root is your app's main bundle.根是您应用的主要捆绑包。
myImageView.image = [UIImage imageNamed:@"/Path/To/Some/File.png"];
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.