1

After checking how others try to do URL encoding in Cocoa (like How do I URL encode a string, Swift - encode URL, etc.) I still have no clue how to correctly URL encode in Cocoa if

  • URLs come from externally therefore their structure (parts) not known ahead
  • can be encoded or pure URL strings
  • BONUS can be relative and local file URLs
  • I do not want to encode blindly always all the characters but according to rfc3986 (rfc2396, rfc1738, rfc1808)

The catch 22:

  • stringByAddingPercentEscapesUsingEncoding: converts lazily so the preferred method would be using stringByAddingPercentEncodingWithAllowedCharacters: for each url components one by one

  • [NSURL URLWithString:], [NSURLComponents componentsWithString:] and companions will fail if the incoming string is not (at least partially) encoded, but if I pass a stringByAddingPercentEscapesUsingEncoding: encoded string than the component splitting will fail (f.e. the encoded # will confuse the splitter and the fragment will be treated the part of a possible query section

How to URL encode correctly in this case without writing my own URL parser, encoder?

Community
  • 1
  • 1
Hofi
  • 945
  • 1
  • 6
  • 18

1 Answers1

2

You should read all of Apple's release note discussion of this subject, but in particular this part may be most relevant for your case:

If you need to percent-encode an entire URL string, you can use this code to encode a NSString intended to be a URL (in urlStringToEncode):

    NSString *percentEncodedURLString =
       [[NSURL URLWithDataRepresentation:[urlStringToEncode dataUsingEncoding:NSUTF8StringEncoding] relativeToURL:nil] relativeString];

(The CoreFoundation equivalent to URLWithDataRepresentation: is CFURLCreateWithBytes() using the encoding kCFStringEncodingUTF8 with a fall back to kCFStringEncodingISOLatin1 if kCFStringEncodingUTF8 fails.)

Basically, +URLWithDataRepresentation:relativeToURL: does its best to make a proper URL from the provided bytes. Given that you can't guarantee almost anything about the input, there can't be any promises that it will get it "right" (because "right" isn't well defined in that case), but it's probably your best hope.

Ken Thomases
  • 88,520
  • 7
  • 116
  • 154
  • you made my day, thanks a lot, I have not tried correctly `URLWithDataRepresentation` your sample saved me! – Hofi May 06 '16 at 08:24
  • Just for the record `URLWithDataRepresentation` is a OSX 10.11+ and iOS 9+ solution only! – Hofi May 11 '16 at 22:16
  • 1
    You can fall back to the Core Foundation equivalent mentioned in the quote. That goes all the way back to 10.0. – Ken Thomases May 11 '16 at 22:45