BREAKING UPDATE: Actually comparing the -absoluteURL
or -absoluteString
of two NSURL
s that represent a file is not good enough. One may start file:///
, and the other file://localhost/
, and they will not be isEqual:
! A work around is to compare the path
of each NSURL
. I’m still looking into the issue, but for now I am using the following method to compare NSURL
s.
@implementation NSURL (IsEqualTesting) - (BOOL) isEqualToURL:(NSURL*)otherURL; { return [[self absoluteURL] isEqual:[otherURL absoluteURL]] || [self isFileURL] && [otherURL isFileURL] && ([[self path] isEqual:[otherURL path]]); } @end
[a isEqual:b]
may report NO
for two NSURL
s that both resolve to the same resource (website, file, whatever). So compare NSURL
s like [[a absoluteString] isEqual:[b absoluteString]]
. It’s important to be aware of this gotcha, because URLs are Apple’s preferred way to represent file paths, and APIs are starting to require them. Equality tests that worked for NSString
file-paths may fail with NSURL
file-paths.
The official documentation says
two
NSURLs
are considered equal if they both have the same basebaseURL
andrelativeString
.
Furthermore,
An
NSURL
object is composed of two parts—a potentially nil base URL and a string that is resolved relative to the base URL. AnNSURL
object whose string is fully resolved without a base is considered absolute; all others are considered relative.
In other words, two NSURL
objects can resolve to the same absolute URL, but have a different base URL, and be considered !isEqual:
.
An example should make this all clear,
NSURL *VGableDotCom = [NSURL URLWithString:@"http://vgable.com"]; NSURL *a = [[NSURL alloc] initWithString:@"blog" relativeToURL:VGableDotCom]; NSURL *b = [[NSURL alloc] initWithString:@"http://vgable.com/blog" relativeToURL:nil]; LOG_INT([a isEqual:b]); LOG_INT([[a absoluteURL] isEqual:[b absoluteURL]]); LOG_ID([a absoluteURL]); LOG_ID([b absoluteURL]);
[a isEqual:b] = 0
[[a absoluteURL] isEqual:[b absoluteURL]] = 1
[a absoluteURL] = http://vgable.com/blog
[b absoluteURL] = http://vgable.com/blog
Remember that collections use isEqual:
to determine equality, so you may have to convert an NSURL
to an absoluteURL
to get the behavior you expect, especially with NSSet
and NSDictionary
.