As I don't have enough rep points for comment for this question URL Encoding swift IOS, I created a new question. I would like to receive feedback on making it more swifty for use cases like this one.
My understanding of OP question is inside API response or from data, there is multiple links of URLs for image, with possibility of different host domains.
In such cases, the host URL could be first retrieved like in this answer. In similar way, the path can also be retrieved separately.
The path can be encoded like as below and concat back to host string later.
addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)
This is what I initially tried out in playground.
import Foundation
extension String {
var encoded: String? {
return self.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed)
}
}
let urlStrings:[String] = ["https://example.com/test.jpg"
"https://example.cc/test2.jpg",
"https://example.dev.cc/test3.jpg"]
var encodedUrlStrings: [String] = []
urlStrings.forEach { urlString in
print(urlString)
guard let url = URL(string: urlString),
let domain = url.host,
let encodedPath = url.path.encoded else { return }
let encodedUrlString = domain + encodedPath
encodedUrlStrings.append(encodedUrlString)
}
encodedUrlStrings.count
encodedUrlStrings.forEach { print($0) }
But the weird thing I notice from OP's question is the url itself should not be already including character like space or any unicode character.
https://ftximages.apk.in/test Fretailer_Point-6685.jpg
For such string, converting into URL will always return nil with URL(String:) method. Same result for using URLComponents as well as the characters in path are still not usable in URL. So this need to make more agreements with backedn dev or anyone who's sending such URL string without encoded characters.
Just in case the backend dev is making a fuss, following codes will gives example of encoded URL strings.
String extension from @Claudio's answer.
import Foundation
extension String {
var encoded: String? {
return self.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed)
}
}
let urlStrings:[String] = ["https://example.com.cc/folder/test.jpg",
"https://example.com/test.jpg",
"https://Ftximages.apk.in/test Fretailer_Point-6685.jpg",
"https://example.com/원 더 우먼.jpg",
"https://example.dev.cc/刺客聶隱娘-6685.jpg",
"https://example.cc/बाजीराव मस्तानी.jpg"]
var encodedUrlStrings: [String] = []
func encodeURL(scheme: String, host: String, path: String) -> String? {
var components = URLComponents()
components.scheme = scheme
components.host = host
components.path = path
return components.url?.absoluteString ?? URL(string: "\(scheme)://\(host)/\(path)")?.absoluteString
}
func encodeWeirdUrlString(_ urlString: String) -> String? {
var urlSplitStrings = urlString.components(separatedBy: ["/"])
urlSplitStrings.removeAll(where: { $0.isEmpty })
guard urlSplitStrings.indices.contains(0), urlSplitStrings.indices.contains(1) else { return nil }
let scheme = String(urlSplitStrings[0].dropLast())
let host = urlSplitStrings[1]
urlSplitStrings.remove(at: 1)
urlSplitStrings.remove(at: 0)
guard let path = urlSplitStrings.joined(separator: "/").encoded else { return nil}
let encodedUrlString = encodeURL(scheme: scheme, host: host, path: path)
return encodedUrlString
}
urlStrings.forEach { urlString in
print(urlString)
guard let url = URL(string: urlString),
let scheme = url.scheme,
let host = url.host,
let encodedPath = url.path.encoded,
let encodedUrlString = encodeURL(scheme: scheme, host: host, path: encodedPath) else {
if let encodedUrlString = encodeWeirdUrlString(urlString) {
encodedUrlStrings.append(encodedUrlString)
}
return
}
encodedUrlStrings.append(encodedUrlString)
}
encodedUrlStrings.count
encodedUrlStrings.forEach { print($0) }
Are there any improvements to make this solution more swifty?