Reliable way to compare two NSURL or one NSURL and an NSString?
Asked Answered
V

4

22

I recently had a problem when comparing two NSURLs and compare one NSURL with an NSString(which is a URL address), the situation is I got an NSURLRequest from somewhere, I may or may not know the URL address it points to, and I have an URL NSString, say "http://m.google.com", now I need to check if the URL in that NSURLRequest is the same as the URL string I had:

[[request.URL.absoluteString lowercaseString] isEqualToString: [self.myAddress lowercaseString]];

this returns NO as the absoluteString gives me "http://m.google.com/" whereas my string is "http://m.google.com" without a slash in the end, even if I create the NSURLRequest using

[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://m.google.com"]]

it still gives me "http://m.google.com/" for absoluteString, I wonder is there any reliable way to compare to NSURL or one NSURL and one NSString?

  1. check if one 'contains' another, but this is not reliable as 'http://m.google.com/blabla' contains 'http://m.google.com'.

  2. convert the NSString to NSURL and use the isEqual method to compare two NSURL and hopefully NSURL's implementation of isEqual can figure it out?

  3. based on step 2, but convert each NSURL to a standard URL using standardizedURL?

Thanks a lot!

Villasenor answered 7/9, 2012 at 0:33 Comment(4)
does the second NSURL have a '/' at the end of it? that would be enough to throw off the isEqualToString methodApplegate
Yes, but what I am asking is a reliable way which allows me not have to make sure there is a '/' at then end, as the actual URL is the same no matter you have or not have a '/' at the end.Villasenor
No, isEqual: of the NSURL does not "figure it out" :(Washery
possible duplicate of How to compare two NSURLs that are practically equivalent but have cosmetic string differences?Darees
J
28

If you care only about the trailing slash ambiguity, you can dispense with this question quickly by knowing that NSURL path trims the trailing slash.

But I like the idea of a category method on NSURL that implements some standards-based equivalence ("equivalence" is probably a better term than equality in this case).

@RobNapier refers to a related question with a good answer that points to RFC2616. Another relevant standard for url syntax is RFC1808.

The tough part is deciding what we mean by equivalence, for example, what about differing queries or fragments (anchor links)? The code below errs on the side of permissiveness for most of these ambiguities...

// in NSURL+uriEquivalence.m

- (BOOL)isEquivalent:(NSURL *)aURL {

    if ([self isEqual:aURL]) return YES;
    if ([[self scheme] caseInsensitiveCompare:[aURL scheme]] != NSOrderedSame) return NO;
    if ([[self host] caseInsensitiveCompare:[aURL host]] != NSOrderedSame) return NO;

    // NSURL path is smart about trimming trailing slashes
    // note case-sensitivty here
    if ([[self path] compare:[aURL path]] != NSOrderedSame) return NO;

    // at this point, we've established that the urls are equivalent according to the rfc
    // insofar as scheme, host, and paths match

    // according to rfc2616, port's can weakly match if one is missing and the
    // other is default for the scheme, but for now, let's insist on an explicit match
    if ([self port] || [aURL port]) {
        if (![[self port] isEqual:[aURL port]]) return NO;
        if (![[self query] isEqual:[aURL query]]) return NO;
    }

    // for things like user/pw, fragment, etc., seems sensible to be
    // permissive about these.
    return YES;
}
Jolynnjon answered 8/9, 2012 at 15:39 Comment(7)
Where should this be implemented in the application structure?Eda
@Ben, objective-c gives you a way to extend (add methods to) classes. (See doc here developer.apple.com/library/mac/documentation/Cocoa/Conceptual/…). The file naming convention is ExistingClass+DescriptionOfAddition.h and .mJolynnjon
This is method is not really safe to use. If self.query == nil but aURL.query isn't the method return YES;Proctoscope
@melbic, Yes, I should have used isEqual test on the optional properties. Good catch.Jolynnjon
Another issue, if both ports or both queries are nil, this logic will return NO.Suet
You've added the check for port, but this code will still return NO if the queries are nil.Baiss
Caveat: This may work well for web URLs but NOT for file URLs - there, the paths may vary despite pointing to the same file, due to (a) symlinks (which can be resolved by getting the canonical path) and (b) unicode composition differences (resolved by using 'fileSystemReference). A combined solution is to invoke NSURL's URLByStandardizingPath`.Ara
T
2

I know this is answered. But i don't think , its clear.

I would like to recommend the following.

if ([[url1 absoluteString] isEqualToString:[url2 absoluteString]]) 
{
   //Add your implementation here
}
Typhus answered 9/6, 2017 at 9:40 Comment(0)
U
2

Having recently encountered the situation where the [NSURL isEqual] method returns false when comparing two URLs like https://www.google.com/ and https://www.google.com I have found that applying the URLByAppendingPathComponent with an empty-string as the parameter to both URLs will return the correct result.

So something like:

[[urlOne URLByAppendingPathComponent:@""] isEqual:[urlTwo URLByAppendingPathComponent:@""]]

will add the trailing slash if missing and leave it alone if it is already included and so the comparison will work as expected.

Seems to me like I am relying on one strange behavior to work-around another strange behavior but this is what I am going with unless I can be convinced otherwise ;-).

Unworthy answered 15/1, 2019 at 0:34 Comment(0)
G
-10

Easy way is:

NSString*urlString=[NSString stringWithFormat:@"%@",request.URL];

so you compare with NSString method isEqual:

BOOL equalty=[urlString isEqual:anotherNSString];

XD

Georgeannageorgeanne answered 19/12, 2012 at 19:53 Comment(3)
This is bad code. It depends in the implementation of -description (NSURL) and it uses -isEqual: instead of -isEqualToString:. In addition two "equal" URLs can yield different descriptions thus your solution will break. No need to "XD".Melaniamelanic
NSURL absoluteString would be better than this implementation.Dillydally
Im thinking delete my comment but I ratter take the comments that Cristian Kienle and Kessedc posted.Georgeannageorgeanne

© 2022 - 2024 — McMap. All rights reserved.