Swift - Parse a String Which Contains a Url

Swift - Parse a string which contains a URL

The query part of an URL can be parsed with URLComponents

let yourTargetUrl = URL(string:"http://www.foo.ir/baz/result_false.php?error=Canceled%20By%20User")!

var dict = [String:String]()
let components = URLComponents(url: yourTargetUrl, resolvingAgainstBaseURL: false)!
if let queryItems = components.queryItems {
for item in queryItems {
dict[item.name] = item.value!
}
}
print(dict)

How to parse a url to get key and value

The answer you are referring to is outdated and has been updated accordingly by the writer himself. Apple added [URLQueryItem] in the URLComponent object.

Try this.

Swift

    let urlString = "https://www.example.com/product-detail?journey_id=123456&iswa=1"
var dict: [String : String] = [:]
if let urlComponents = URLComponents(string: urlString), let queryItems = urlComponents.queryItems {
for item in queryItems {
dict[item.name] = item.value
}
}
print("dict : \(dict)")

Objective - C

NSString *urlString = @"https://www.example.com/product-detail?journey_id=123456&iswa=1";
NSMutableDictionary *dict = [NSMutableDictionary dictionary];

NSURLComponents *urlComponents = [NSURLComponents componentsWithString:urlString];
NSArray *queryItems = [urlComponents queryItems];

for (NSURLQueryItem *item in queryItems) {
[dict setValue:item.value forKey:item.name];
}

NSLog(@"dict %@", dict);

How to parse URL with # in Swift?

The problem you're running into is that # isn't part of the path but introducing a new component of the URL, stored in url.fragment. It's similar to if you had https://example.com/foo/?test=/bar. ?test= isn't a path component but the beginning of the query.

You have two approaches you can take.

If https://something.com/room/order/12345555/product/543333?is_correct=true and https://something.com/room/#/order/12345555/product/543333?is_correct=true can be used interchangeably, as in viewing either page in the browser will land you on the same page, you could have a sanitizing step in your process:

var rawUrl = ...
var sanitizedUrl = url.replacingOccurrences(of: "/#/", with: "/")
var url = URL(string: url)

How much sanitization you do depends on your application. It could be that you only want to do (of: "/room/#/", with: "/room/")

Another option, if you know your fragment will always look like a partial URL would be to pass the fragment into URL:

let url = URL(string: rawUrl)!
let fragmentUrl = URL(string: url.fragment!, relativeTo: url)!

let fullPathComponents = url.pathComponents + fragmentUrl.pathComponents[1...];
var query = fragmentUrl.query

The above approach yields: ["/", "room", "order", "12345555", "product", "543333"] for the joined URL.

Which approach and how much sanitization you do will depend on your use-case.

Best way to parse URL string to get values for keys?

edit (June 2018): this answer is better. Apple added NSURLComponents in iOS 7.

I would create a dictionary, get an array of the key/value pairs with

NSMutableDictionary *queryStringDictionary = [[NSMutableDictionary alloc] init];
NSArray *urlComponents = [urlString componentsSeparatedByString:@"&"];

Then populate the dictionary :

for (NSString *keyValuePair in urlComponents)
{
NSArray *pairComponents = [keyValuePair componentsSeparatedByString:@"="];
NSString *key = [[pairComponents firstObject] stringByRemovingPercentEncoding];
NSString *value = [[pairComponents lastObject] stringByRemovingPercentEncoding];

[queryStringDictionary setObject:value forKey:key];
}

You can then query with

[queryStringDictionary objectForKey:@"ad_eurl"];

This is untested, and you should probably do some more error tests.

How can I convert the string to URL which include a ? in the string by Swift 4.2

You are supposed to encode only the query parameters (although probably only keyword actually needs encoding), not the whole URL.

func urlEncode(_ string: String) -> String {
var allowed = CharacterSet.urlQueryAllowed
allowed.remove(charactersIn: "!*'();:@&=+$,/?%#[]")
return string.addingPercentEncoding(withAllowedCharacters: allowed) ?? ""
)

let urlString = "\(GOOGLE_MAP_API_BASEURL)key=\(urlEncode(GMS_HTTP_KEY))&input=\(urlEncode(keyword))&sessiontoken=\(urlEncode(ver4uuid!))"
print(urlString)

Also see Swift - encode URL about the correct way to encode URL parameters.

How to parse partial link in swift 4?

You can get the url components of your api link and use your icon "partial link" to set the path property of the URL components. After that you just need to get the resulting url of the url components:

let apiLink = "https://api.opendota.com/api/heroStats"
let apiURL = URL(string: apiLink)!
if var urlComponents = URLComponents(url: apiURL, resolvingAgainstBaseURL: false) {
let iconString = "/apps/dota2/images/heroes/antimage_icon.png"
urlComponents.path = iconString
if let iconURL = urlComponents.url {
print(iconURL.absoluteString)
}
}

This will print

https://api.opendota.com/apps/dota2/images/heroes/antimage_icon.png




You can create a custom method to return a new URL based on the new path string as follow:

extension URL {
var urlComponents: URLComponents? {
return URLComponents(url: self, resolvingAgainstBaseURL: false)
}
func bySettingNew(path: String) -> URL? {
guard var urlComponents = urlComponents else { return nil }
urlComponents.path = path
return urlComponents.url
}
}


let apiLink = "https://api.opendota.com/api/heroStats"
let apiURL = URL(string: apiLink)!
let iconString = "/apps/dota2/images/heroes/antimage_icon.png"

if let iconURL = apiURL.bySettingNew(path: iconString) {
print(iconURL.absoluteString)
}



You can also add this helper to your project to make it easier for you to download an image asynchronously into your image view:

extension UIImageView {
func downloaded(from url: URL, contentMode mode: UIView.ContentMode = .scaleAspectFit) {
URLSession.shared.dataTask(with: url) { data, response, error in
guard
let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200,
let mimeType = response?.mimeType, mimeType.hasPrefix("image"),
let data = data, error == nil,
let image = UIImage(data: data)
else { return }
DispatchQueue.main.async() { [weak self] in
self?.contentMode = mode
self?.image = image
}
}.resume()
}
}


if let imageURL = apiURL.bySettingNew(path: heroes[indexPath.row].icon) {
cell.charIcon.downloaded(from: imageURL)
}


Related Topics



Leave a reply



Submit