{"id":299,"date":"2009-04-22T19:05:07","date_gmt":"2009-04-23T00:05:07","guid":{"rendered":"http:\/\/vgable.com\/blog\/2009\/04\/22\/nsurl-isequal-gotcha\/"},"modified":"2009-04-23T01:51:32","modified_gmt":"2009-04-23T06:51:32","slug":"nsurl-isequal-gotcha","status":"publish","type":"post","link":"https:\/\/vgable.com\/blog\/2009\/04\/22\/nsurl-isequal-gotcha\/","title":{"rendered":"-[NSURL isEqual:] Gotcha"},"content":{"rendered":"<p>BREAKING UPDATE: Actually comparing the <code>-absoluteURL<\/code> or <code>-absoluteString<\/code> of two <code>NSURL<\/code>s that represent a file is <em>not good enough<\/em>.  One may start <code>file:\/\/\/<\/code>, and the other <code>file:\/\/localhost\/<\/code>, and <em>they will not be <code>isEqual:<\/code><\/em>!  A work around is to compare the <code>path<\/code> of each <code>NSURL<\/code>. I&#8217;m still looking into the issue, but for now I am using the following method to compare <code>NSURL<\/code>s.<\/p>\n<pre>@implementation NSURL (IsEqualTesting)\n- (BOOL) isEqualToURL:(NSURL*)otherURL;\n{\n\treturn [[self absoluteURL] isEqual:[otherURL absoluteURL]] || \n\t[self isFileURL] && [otherURL isFileURL] &&\n\t([[self path] isEqual:[otherURL path]]);\n}\n@end\n<\/pre>\n<p><code>[a isEqual:b]<\/code> may report <code>NO<\/code> for two <code>NSURL<\/code>s that both resolve to the same resource (website, file, whatever). So <strong>compare <code>NSURL<\/code>s like <code>[[a absoluteString] isEqual:[b absoluteString]]<\/code><\/strong>. It&#8217;s important to be aware of this gotcha, because URLs are Apple&#8217;s preferred way to represent file paths, and APIs are starting to require them. <strong>Equality tests that worked for <code>NSString<\/code> file-paths may fail with <code>NSURL<\/code> file-paths.<\/strong><\/p>\n<p><a href=\"http:\/\/developer.apple.com\/DOCUMENTATION\/Cocoa\/Reference\/Foundation\/Classes\/NSURL_Class\/Reference\/Reference.html#\/\/apple_ref\/occ\/instm\/NSURL\/isEqual:\">The official documentation says<\/a><\/p>\n<blockquote><p> two <code>NSURLs<\/code> are considered equal if they both have the same base <a href=\"http:\/\/developer.apple.com\/DOCUMENTATION\/Cocoa\/Reference\/Foundation\/Classes\/NSURL_Class\/Reference\/Reference.html#\/\/apple_ref\/occ\/instm\/NSURL\/baseURL\"><code>baseURL<\/code><\/a> and <a href=\"http:\/\/developer.apple.com\/DOCUMENTATION\/Cocoa\/Reference\/Foundation\/Classes\/NSURL_Class\/Reference\/Reference.html#\/\/apple_ref\/occ\/instm\/NSURL\/relativeString\"><code>relativeString<\/code><\/a>.<\/p><\/blockquote>\n<p>Furthermore,<\/p>\n<blockquote><p>An <code>NSURL<\/code> object is composed of two parts\u2014a potentially nil base URL and a string that is resolved relative to the base URL. An <code>NSURL<\/code> object whose string is fully resolved without a base is considered absolute; all others are considered relative.\n<\/p><\/blockquote>\n<p>In other words, two <code>NSURL<\/code> objects can resolve to the same absolute URL, but have a different base URL, and be considered <code>!isEqual:<\/code>.<\/p>\n<p>An example should make this all clear,<\/p>\n<pre>\nNSURL *VGableDotCom = [NSURL URLWithString:@\"http:\/\/vgable.com\"];\nNSURL *a = [[NSURL alloc] initWithString:@\"blog\" relativeToURL:VGableDotCom];\nNSURL *b = [[NSURL alloc] initWithString:@\"http:\/\/vgable.com\/blog\" relativeToURL:nil];\n<a href=\"http:\/\/vgable.com\/blog\/2008\/08\/05\/simpler-logging-2\/\">LOG_INT<\/a>([a isEqual:b]);\n<a href=\"http:\/\/vgable.com\/blog\/2008\/08\/05\/simpler-logging-2\/\">LOG_INT<\/a>([[a absoluteURL] isEqual:[b absoluteURL]]);\n<a href=\"http:\/\/vgable.com\/blog\/2008\/08\/05\/simpler-logging-2\/\">LOG_ID<\/a>([a absoluteURL]);\n<a href=\"http:\/\/vgable.com\/blog\/2008\/08\/05\/simpler-logging-2\/\">LOG_ID<\/a>([b absoluteURL]);\n<\/pre>\n<blockquote><p>\n[a isEqual:b] = 0<br \/>\n[[a absoluteURL] isEqual:[b absoluteURL]] = 1<br \/>\n[a absoluteURL] = http:\/\/vgable.com\/blog<br \/>\n[b absoluteURL] = http:\/\/vgable.com\/blog\n<\/p><\/blockquote>\n<p>Remember that <strong>collections use <code>isEqual:<\/code> to determine equality, so you may have to convert an <code>NSURL<\/code> to an <code> absoluteURL<\/code> to get the behavior you expect, especially with <code>NSSet<\/code> and <code>NSDictionary<\/code>.<\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"<p>BREAKING UPDATE: Actually comparing the -absoluteURL or -absoluteString of two NSURLs 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&#8217;m still looking into the issue, but for now I am [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[18,6,203,3,4,13],"tags":[241,395,107,108,109,78,396],"class_list":["post-299","post","type-post","status-publish","format-standard","hentry","category-bug-bite","category-cocoa","category-iphone","category-macosx","category-programming","category-sample-code","tag-best-practices","tag-isequal","tag-nsarray","tag-nsdictionary","tag-nsset","tag-nsstring","tag-nsurl"],"_links":{"self":[{"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/posts\/299","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/comments?post=299"}],"version-history":[{"count":0,"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/posts\/299\/revisions"}],"wp:attachment":[{"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/media?parent=299"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/categories?post=299"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/tags?post=299"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}