2

I can't convert this string to URL URL String: "http://someurl.com/Files/مواد غذایی/برنج و ماکارونی/6260100339286.jpg"

I tried with this codes but get an error (can't unwrap) :

let standardString = string.addingPercentEncoding(withAllowedCharacters: .alphanumerics) 
URL(String: standardString)!
rmaddy
  • 314,917
  • 42
  • 532
  • 579
omid shojaeyan
  • 57
  • 1
  • 10
  • 2
    Possible duplicate of [encoding url using swift code](https://stackoverflow.com/questions/29398678/encoding-url-using-swift-code) – BallpointBen Jun 07 '18 at 15:31
  • 1
    I tried to run your code and (apart from the wrong parameter name for `URL.init`, it's `string:` instead of `String:`) it worked fine. What version of Swift are you using? And following up on @BallpointBen 's comment, using `.urlFragmentAllowed` is better suited for you use case. – dr_barto Jun 07 '18 at 15:36
  • thanks, I did your choice but get this converted URL : http://example.com/Files/%D9%85%D9%88%D8%A7%D8%AF%20%D8%BA%D8%B0%D8%A7%DB%8C%DB%8C/%D8%A8%D8%B1%D9%86%D8%AC%20%D9%88%20%D9%85%D8%A7%DA%A9%D8%A7%D8%B1%D9%88%D9%86%DB%8C/6260100339286.jpg – omid shojaeyan Jun 07 '18 at 15:37
  • error: Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0). The process has been left at the point where it was interrupted, use "thread return -x" to return to the state before expression evaluation. – omid shojaeyan Jun 07 '18 at 15:48

2 Answers2

6

Your approach is encoding the : and / characters. Don't try to hand-encode complex URLs. Different parts have different legal characters. Let the system do it for you.

var components = URLComponents(string: "http://someurl.com")!
components.path = "/Files/6260100339286/مواد غذایی/برنج و ماکارونی.jpg"
components.url

This correctly encodes the URL:

http://someurl.com/Files/6260100339286/%D9%85%D9%88%D8%A7%D8%AF%20%D8%BA%D8%B0%D8%A7%DB%8C%DB%8C/%D8%A8%D8%B1%D9%86%D8%AC%20%D9%88%20%D9%85%D8%A7%DA%A9%D8%A7%D8%B1%D9%88%D9%86%DB%8C.jpg

Note that there is a subtle problem with the Arabic in your question which is likely the cause of confusion. It is unclear whether the encoding is supposed to be:

/Files and then /6260100339286 and then /برنج و ماکارونی and then /مواد غذایی.

or

/Files and then /برنج و ماکارونی and then /برنج و ماکارونی and then /6260100339286.jpg

The reason for this confusion is the Bidirectional rules that make these encodings ambiguous. Forgetting about URLs for a moment, what would you think the "first" hierarchical level of this string is:

ك \ كتب

I'd say we'd all agree it is "ك". So how about this one?

ك / كتب

The slash is backwards, but Unicode doesn't distinguish between / and \. And if that's "ك" first there, what about this one?

http://ك/كتب

What direction should this be parsed in? The URL spec is quite clear about this: this is an invalid URL. URLs cannot contain Arabic; it must be percent-encoded, which eliminates all ambiguity.

While the slash is backwards for Arabic, in Unicode there's no difference between \ and / for the purposes of letter-ordering (they're both considered "unordered"). This means that the correct in-memory layout of "ك/كتب" is ambiguous when you write it in a string. Should it be "ك" then "/" then "كتب" or "كتب" then "/" then "ك"?

(You'll notice I keep putting "then" between my Arabic. That's because if I used , it would cause the same ordering problem. I have to put some LTR text between Arabic that I want to order LTR.)

I've fixed the above code and encoding, but just by retyping the Arabic and making sure it's in the order I think you want it in. The better solution is to remove the ambiguity. Do not write your strings this way. Build them out of path components (which is what you really mean).

var path = URL(string:"/Files/6260100339286")!
path.appendPathComponent("برنج و ماکارونی")
path.appendPathComponent("مواد غذایی")
path.appendPathExtension("jpg")

var components = URLComponents(string: "http://someurl.com")!

components.path = path.absoluteString
components.url

print(components.url!)

This kind of approach removes all ambiguity from switching between LTR and RTL.

Rob Napier
  • 286,113
  • 34
  • 456
  • 610
  • Thank you but still not work, this is an image URL but after encoding doesn't work. Are there any library for creating URL from Arabic words ?? – omid shojaeyan Jun 08 '18 at 07:59
0
var str = "http://someurl.com/Files/مواد غذایی/برنج و ماکارونی/6260100339286.jpg"
str = str.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
let url = URL(string: str)
rmaddy
  • 314,917
  • 42
  • 532
  • 579
  • 1
    This isn't ideal because you are not encoding a URL query. It seems to work in this case but it is quite possible that it won't work correctly for some possible paths. – rmaddy Jun 07 '18 at 16:26