问题
let testurl = "http://akns-
images.eonline.com/eol_images/Entire_Site/2018029/rs_1024x759-
180129200032-1024.lupita-nyongo-angela-bassett-black-panther-
premiere.ct.012918.jpg?fit=inside|900:auto"
if let url = URL(string: testurl){
print("valid")
}else {
print("invalid")
}
This prints as an invalid URL. But shows the image in web browser. I have seen lot of methods but it throws Apple warning to use stringByAddingPercentEncodingWithAllowedCharacters
and this doesn't work always.
I would prefer a solution to clean-up the url without encoding the complete urlstring. Encoding it at initial step can be a friction when passing to external libraries which will re-encode the url and make it invalid.
回答1:
Use URLComponents
, it will handle escape characters automatically and encodes the url correct. no need to use addingPercentEncoding
func computeURL() {
let testurlStr = "http://akns-images.eonline.com/eol_images/Entire_Site/2018029/rs_1024x759-180129200032-1024.lupita-nyongo-angela-bassett-black-panther-premiere.ct.012918.jpg?fit=inside|900:auto"
let components = transformURLString(testurlStr)
if let url = components?.url {
print("valid")
} else {
print("invalid")
}
}
func transformURLString(_ string: String) -> URLComponents? {
guard let urlPath = string.components(separatedBy: "?").first else {
return nil
}
var components = URLComponents(string: urlPath)
if let queryString = string.components(separatedBy: "?").last {
components?.queryItems = []
let queryItems = queryString.components(separatedBy: "&")
for queryItem in queryItems {
guard let itemName = queryItem.components(separatedBy: "=").first,
let itemValue = queryItem.components(separatedBy: "=").last else {
continue
}
components?.queryItems?.append(URLQueryItem(name: itemName, value: itemValue))
}
}
return components!
}
回答2:
URL encoding is compulsory for building a URL from a string in case it contains special characters.
Why we need URL encoding
From this answer:
A URI is represented as a sequence of characters, not as a sequence of octets. That is because URI might be "transported" by means that are not through a computer network, e.g., printed on paper, read over the radio, etc.
And
For original character sequences that contain non-ASCII characters, however, the situation is more difficult. Internet protocols that transmit octet sequences intended to represent character sequences are expected to provide some way of identifying the charset used, if there might be more than one [RFC2277]. However, there is currently no provision within the generic URI syntax to accomplish this identification. An individual URI scheme may require a single charset, define a default charset, or provide a way to indicate the charset used.
In the IOS SDK we have the following:
User: URLUserAllowedCharacterSet
Password: URLPasswordAllowedCharacterSet
Host: URLHostAllowedCharacterSet
Path: URLPathAllowedCharacterSet
Fragment: URLFragmentAllowedCharacterSet
Query: URLQueryAllowedCharacterSet
You can use addingPercentEncoding(withAllowedCharacters:)
to encode a string correctly.
One important note according to the apple docs for that method:
Entire URL strings cannot be percent-encoded, because each URL component specifies a different set of allowed characters. For example, the query component of a URL allows the “@” character, but that character must be percent-encoded in the password component.
UTF-8 encoding is used to determine the correct percent-encoded characters. Any characters in allowedCharacters outside of the 7-bit ASCII range are ignored.
An example:
let encodedURL = testurl.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
if let url = URL(string: finalUrl) {
print("valid url")
} else {
print("invalid url")
}
I hope this is helpful.
回答3:
I think I have found my answer. Still will be checking for any side effects, comments are welcome:
let urlst = "http://akns-
images.eonline.com/eol_images/Entire_Site/2018029/rs_1024x759-
180129200032-1024.lupita-nyongo-angela-bassett-black-panther-
premiere.ct.012918.jpg?fit=inside|900:auto"
extension String {
func getCleanedURL() -> URL? {
guard self.isEmpty == false else {
return nil
}
if let url = URL(string: self) {
return url
} else {
if let urlEscapedString = self.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed) , let escapedURL = URL(string: urlEscapedString){
return escapedURL
}
}
return nil
}
}
This does not encode the complete URL but encodes only the invalid query characters (in eg url its '|'). Thus it can still be passed around as a string or a valid URL.
回答4:
Please replace your line with:
let finalUrl = testurl.addingPercentEncoding( withAllowedCharacters: .urlUserAllowed)
if let url = URL(string: finalUrl){
print("valid")
} else {
print("invalid")
}
来源:https://stackoverflow.com/questions/48576329/ios-urlstring-not-working-always