Reputation: 4533
I do some easy tasks with Firebase, set image url
into json
, download it and show it. But for some reason if the url
contains umlauts e.g(ö, ä, ü etc..) the url is set to wrong section.
Edit: I gotta clarify that I do the percent encoding with the url. So it actually doesn't contain any umlauts.
So the url
actually looks like this for example for Göteborgs Rapé Loose.png
: https://firebasestorage.googleapis.com/v0/b/snuspedia.appspot.com/o/Go%CC%88teborgs%20Rape%CC%81%20Loose.png?alt=media&token=e8f2219b-d14e-46f6-a90f-ee21f912af6c
With umlaut it does like this:
And without umlauts it does correct like this:
This is how I do all these steps what I described:
if productsValue[indexPath.row]["productUrl"] != nil {
cell.snusProductImageView!.kf_setImageWithURL(NSURL(string: productsValue[indexPath.row]["productUrl"] as! String)!)
}
else {
let productImageref = productsValue[indexPath.row]["Products"] as! String
let decomposedPath = productImageref.decomposedStringWithCanonicalMapping
cell.snusProductImageView.image = nil
cell.snusProductImageView.kf_showIndicatorWhenLoading = true
FIRStorage.storage().reference().child("\(decomposedPath).png").downloadURLWithCompletion({(url, error)in
FIRDatabase.database().reference().child("Snuses").child(decomposedPath).child("productUrl").setValue(url!.absoluteString)
let resource = Resource(downloadURL: url!, cacheKey: decomposedPath)
cell.snusProductImageView.kf_setImageWithURL(url)
})
What is the problem, can you tell me? I've been searching the problem for a good week.
Upvotes: 0
Views: 477
Reputation: 19144
A URL cannot directly contain "Umlauts". To put it simple, a URL is a sequence of restricted ASCII characters.
That means, characters which are not allowed (e.g., ö
, ä
, ü
etc.), need to be encoded properly. Since a URL is comprised of a couple of different components, each component may use a slightly different encoding. The details are covered here: Uniform Resource Identifier (URI): Generic Syntax.
In Cocoa and Cocoa Touch, there is a helper class, NSURLComponents
which let you easily compose a proper URL string from the given original components in their natural character encoding.
Please note, that simply applying "percent encoding" to the whole improper encoded URL usually yields another incorrect encoded URL. Don't do that! Use NSURLComponents
!
Edit:
Let me apply some - hopefully useful - comments to your code:
This expression is problematic:
NSURL(string: productsValue[indexPath.row]["productUrl"] as! String)!
It would be preferable, to explicitly initialise a URL
from the potentially missing value at index "productUrl"
and include proper error handling. Converting strings to URLs is notoriously error prone.
Then
let decomposedPath = productImageref.decomposedStringWithCanonicalMapping
This makes no sense, since per definition a URL string is composed of a restricted set of ASCII characters anyway.
So, in conclusion, check your given string which should become a URL, and ensure you can initialise a proper URL from it (as value of type URL
) and also convert it back again correctly to a string, respectively to an array of ASCII characters, when sending it over a network.
Edit 2:
The code below demonstrates how you can utilise NSURLComponents
to safely create a URL from a given base URL, a partial path component which refers to the endpoint and from a given set of parameters.
Copy/past this into playgrounds to try it out.
import Cocoa
extension String: ErrorType {}
// First, create a base URL and save it later for reuse:
// Caution: The given string must be properly encoded! But usually, the base address
// in native form should only use allowed characters anyway, so the encoded form
// should be equal to the native form (otherwise, you have to encode it per component).
let urlBaseString = "https://firebasestorage.googleapis.com/v0/b/snuspedia.appspot.com/o"
guard let urlBase = NSURL(string: urlBaseString) else {
throw "bad base URL"
}
print("Base URL path: \"\(urlBase.path!)\"")
// Get the current path and parameters using strings using their "native character set":
let itemPath = "Göteborgs Rapé Loose.png"
let params = ["alt": "media", "token": "e8f2219b-d14e-46f6-a90f-ee21f912af6c"]
// Create a partial URL components (representing a relative URL) with the given
// path and query component:
let components = NSURLComponents()
components.path = itemPath
components.queryItems = params.map { NSURLQueryItem(name: $0, value: $1) }
// Combine the base URL with the partial URL in order to get a fully specified URL:
guard let url = components.URLRelativeToURL(urlBase) else {
throw "Failed to create final URL"
}
print("URL: \(url.absoluteString)")
Output:
URL: https://firebasestorage.googleapis.com/v0/b/snuspedia.appspot.com/G%C3%B6teborgs%20Rap%C3%A9%20Loose.png?alt=media&token=e8f2219b-d14e-46f6-a90f-ee21f912af6c
Upvotes: 2