I am creating a manual Firebase Dynamic Link
https://firebase.google.com/docs/dynamic-links/create-manually
I have a url in the format of https://test.page.link/?link=https://test.page.link/register?accessCode%3DAA000000&apn=com.test.foo&ibi=com.test.bar&ofl=https://www.google.com.
How can I get the value of accessCode?
extension URL {
func valueOf(_ queryParameterName: String) -> String? {
guard let url = URLComponents(string: self.absoluteString) else { return nil }
return url.queryItems?.first(where: { $0.name == queryParameterName })?.value
}
}
Using this extension the query items are link, apn, and ofl.
url.valueOf("link") returns:
https://test.page.link/?link=https://test.page.link/register?accessCode=AA000000
I only need the AA000000 returned.
Since link is of the format of a url, create a URL instance from it and then get the accessCode value using valueOf(_:) method like so,
if let link = url.valueOf("link"), let linkUrl = URL(string: link) {
let accessCode = linkUrl.valueOf("accessCode")
print(accessCode)
}
You have an URL inside an URL, more precisely, an URL inside a value of a query, so what about using:
extension URL {
func valueOf(_ queryParameterName: String) -> String? {
guard let url = URLComponents(string: self.absoluteString) else { return nil }
guard let queryItems = url.queryItems else { return nil }
for aQueryItem in queryItems {
if aQueryItem.name == queryParameterName {
return aQueryItem.value
} else if let subvalue = aQueryItem.value, let subURL = URL(string: subvalue), let found = subURL.valueOf(queryParameterName) {
return found
}
}
return nil
}
}
Now you can use url.valueOf("accessCode")
Related
This question already has answers here:
Swift - encode URL
(19 answers)
Closed 1 year ago.
I have a string that can include any characters, from alphanumeric to special chars like "&,.:/!" etc. I need to encode that string and send it to twitter. I tried the following but as soon as theres an & character in text, it doesn't work properly:
static func shareToTwitter(text: String) {
guard let urlEscaped = text.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else {
return
}
guard let url = URL(string: "twitter://post?message=\(urlEscaped)") else {
return
}
if UIApplication.shared.canOpenURL(url) {
UIApplication.shared.open(url)
} else {
guard let twitterUrl = URL(string: "https://twitter.com/intent/tweet?text=\(urlEscaped)") else {
return
}
UIApplication.shared.open(twitterUrl)
}
}
So an example sentence might be: "I'm here & there". Instead, Twitter will receive "I'm here". How can I fix this?
As suggested by Alexander the most reliable way is to use URLComponents and URLQueryItem
static func shareToTwitter(text: String) {
var components = URLComponents(string: "twitter://post")!
components.queryItems = [URLQueryItem(name: "message", value: text)]
if let url = components.url, UIApplication.shared.canOpenURL(url) {
UIApplication.shared.open(url)
} else {
components = URLComponents(string: "https://twitter.com/intent/tweet")!
components.queryItems = [URLQueryItem(name: "text", value: text)]
guard let twitterUrl = components.url else { return }
UIApplication.shared.open(twitterUrl)
}
}
I'm building an app that can receive Firebase's Dynamic Links and redirects it into a certain UIViewController. I've followed the steps on this video, but there's something that I still don't understand. So after I followed the steps above, I print my link on the debug area to something like this:
Incoming link parameter is https://play.google.com/store/apps/details?id=com.xxx.xxx&referrer=utm_source%3DXXX%26utm_medium%3Dxxx%26utm_campaign%3DXXX
Parameter id has a value of com.xxx.xxx
Parameter referrer has a value of utm_source=XXX&utm_medium=xxx&utm_campaign=XXX
This works perfectly, but what I want to do is I want to get the values of utm_source, utm_medium and utm_campaign and store it into a variable. I'm still uncertain on how do I manage to achieve this. Here is my code:
func handleIncomingDynamicLink(_ dynamicLink: DynamicLink) {
guard let url = dynamicLink.url else {
print("Dynamic Link has no URL")
return
}
print("Incoming link parameter is \(url.absoluteString)")
guard let components = URLComponents(url: url, resolvingAgainstBaseURL: false), let queryItems = components.queryItems else { return }
for queryItem in queryItems {
print("Parameter \(queryItem.name) has a value of \(queryItem.value ?? "")")
}
}
So how do I manage to do this? Feel free to ask if you need any more information. Thank you.
I don't know if this is the best answer or the right code design but fortunately I managed to solve by changing handleIncomingDynamicLink function to something like this:
func handleIncomingDynamicLink(_ dynamicLink: DynamicLink) {
guard let url = dynamicLink.url else {
print("Dynamic Link has no URL")
return
}
print("Incoming link parameter is \(url.absoluteString)")
guard let components = URLComponents(url: url, resolvingAgainstBaseURL: false), let queryItems = components.queryItems else { return }
for queryItem in queryItems {
if queryItem.name == "referrer" {
print("Referrer found")
let referrerString = "https://xxx.page.link/details?\(queryItem.value ?? "")"
let referrerUrl = URL(string: referrerString)
guard let queryItemComponents = URLComponents(url: referrerUrl!, resolvingAgainstBaseURL: false), let itemComponents = queryItemComponents.queryItems else {
print("Referrer string couldn't be casted as a URL")
return
}
for item in itemComponents {
print("Parameter \(item.name) has a value of \(item.value ?? "")")
}
}
}
}
So basically what I did was I take the referrer value of the main URL and make it a "custom URL" so that I could parse the values by using the URLComponents function. The output is exactly what I expected to be.
Incoming link parameter is https://play.google.com/store/apps/details?id=com.xxx.xxx&referrer=utm_source%3Dxxx%26utm_medium%3Dxxx%26utm_campaign%3Dxxx
Referrer found
Parameter utm_source has a value of xxx
Parameter utm_medium has a value of xxx
Parameter utm_campaign has a value of xxx
Here's is how you can make a struct and assign the values to it.
struct MyVariable {
var referrer: String?, utm_source: String?, utm_medium: String?, utm_campaign: String?
}
func handleIncomingDynamicLink(_ dynamicLink: URL?) {
guard let string = dynamicLink?.absoluteString.removingPercentEncoding,
let url = URL(string: string) else {
print("Dynamic Link has no URL")
return
}
var myVariable = MyVariable()
guard let components = URLComponents(url: url, resolvingAgainstBaseURL: false),
let queryItems = components.queryItems else { return }
for queryItem in queryItems {
if queryItem.name == "referrer" {
myVariable.referrer = queryItem.value
} else if queryItem.name == "utm_source" {
myVariable.utm_source = queryItem.value
} else if queryItem.name == "utm_medium" {
myVariable.utm_medium = queryItem.value
} else if queryItem.name == "utm_campaign" {
myVariable.utm_campaign = queryItem.value
}
}
print("MyVariable: \(myVariable)")
}
I am trying to get parameters for urls and I try to get only the date not time the URL.
http://aa.no-ip.biz:8001/hf_tracker/api/history.php?accesskey=12345&Vehilce=1618&FromDate=2018-05-10 13:11&ToDate=2018-05-14 12:11
Code:
extension URL {
func valueOf(_ queryParameterName: String) -> String? {
guard let url = URLComponents(string: self.absoluteString) else {
return nil
}
return url.queryItems?.first(where: { $0.name == queryParameterName})?.value
}
}
let newURL = URL(string: "assetlinkasia.no-ip.biz:8001/hf_tracker/api/…)!
newURL.valueOf("toDate")
newURL.valueOf("fromDate")
How can I only get the date and not time?
This is the way you can do it,
Your URL extension here, from here
extension URL {
func valueOf(_ queryParamaterName: String) -> String? {
guard let url = URLComponents(string: self.absoluteString) else { return nil }
return url.queryItems?.first(where: { $0.name == queryParamaterName })?.value
}
}
Your code goes here,
let string = "http://aa.no-ip.biz:8001/hf_tracker/api/history.php?accesskey=12345&Vehilce=1618&FromDate=2018-05-10 13:11&ToDate=2018-05-14 12:11"
let test = string.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
let url = URL(string: test!)!
let fromDate = url.valueOf("FromDate")
let toDate = url.valueOf("ToDate")
let date1 = fromDate?.components(separatedBy: " ").first
print(date1)
let date2 = toDate?.components(separatedBy: " ").first
print(date2 )
Output will be below,
2018-05-10
2018-05-14
In my apps a use a helper function that parses the url and returns an optional dictionary:
func parameters(for url: URL) -> [String: String]? {
guard let urlQuery = url.query else { return nil }
// Create all parameters dictionary
let queryArray = urlQuery.split { $0 == "&" }.map(String.init)
var parametersDict: [String: String] = [:]
for queryParameter in queryArray {
// split the queryParam into key / value
let keyValueArray = queryParameter.split{ $0 == "=" }.map(String.init)
let key = keyValueArray.first!
let value = keyValueArray.last!.removingPercentEncoding!
parametersDict.updateValue(value, forKey: key)
}
return parametersDict
}
And use it like this:
let params = parameters(for: URL(string: "https://someurl.com?name=john")!)
if let name = params?["name"] {
print(name)
}
Or you can add a var to URL extension:
extension URL {
var parameters: [String: String]? {
guard let urlQuery = self.query else { return nil }
// Create all parameters dictionary
let queryArray = urlQuery.split { $0 == "&" }.map(String.init)
var parametersDict: [String: String] = [:]
for queryParameter in queryArray {
// split the queryParam into key / value
let keyValueArray = queryParameter.split{ $0 == "=" }.map(String.init)
let key = keyValueArray.first!
let value = keyValueArray.last!.removingPercentEncoding!
parametersDict.updateValue(value, forKey: key)
}
return parametersDict
}
}
And get the parameter:
let params = URL(string: "https://someurl.com?name=john")!.parameters
if let name = params?["name"] {
print(name)
}
I have a URL String "http:///blaBla?id=Testid851211" and I just want to get "851211".
Below is my code :-
let url: NSURL = NSURL(string: urlString)!
Helper.sharedInstance.Print(url.query as AnyObject)
if (url.query?.localizedStandardContains("testKey"))! {
//TestKey
Helper.sharedInstance.Print(url.query as AnyObject)
let testValue = getQueryStringParameter(url: urlString, param: "testKey")
Helper.sharedInstance.Print(testValue as AnyObject)
}
else if (url.query?.localizedStandardContains("testID"))! {
//TestID
Helper.sharedInstance.Print(url.query as AnyObject)
}
func getQueryStringParameter(url: String, param: String) -> String? {
guard let url = URLComponents(string: url) else { return nil }
return url.queryItems?.first(where: { $0.name == param })?.value
}
I am getting id = Testid851211 but I want only "851211".
Use a regular expression filtering out numbers only:
let urlString = "http:///blaBla?id=Testid851211"
let pattern = "[0-9]+"
if let matchRange = urlString.range(of: pattern, options: .regularExpression) {
print(urlString[matchRange])
}
Works as long as your URLs don’t have numbers anywhere else.
Try this extension:
extension String {
func getNeededText(for url: String) -> String {
guard range(of: url) != nil else { return "" }
return replacingOccurrences(of: url, with: "")
}
}
Usage:
let predefinedHost = "http:///blaBla?id=Testid"
let url = "http:///blaBla?id=Testid851211"
url.getNeededText(for: predefinedHost) // prints "851211"
I am trying to get the parameters from a URL using Swift. Let's say I have the following URL:
http://mysite3994.com?test1=blah&test2=blahblah
How can I get the values of test1 and test2?
You can use the below code to get the param
func getQueryStringParameter(url: String, param: String) -> String? {
guard let url = URLComponents(string: url) else { return nil }
return url.queryItems?.first(where: { $0.name == param })?.value
}
Call the method like let test1 = getQueryStringParameter(url, param: "test1")
Other method with extension:
extension URL {
public var queryParameters: [String: String]? {
guard
let components = URLComponents(url: self, resolvingAgainstBaseURL: true),
let queryItems = components.queryItems else { return nil }
return queryItems.reduce(into: [String: String]()) { (result, item) in
result[item.name] = item.value
}
}
}
Step 1: Create URL extension
extension URL {
func valueOf(_ queryParameterName: String) -> String? {
guard let url = URLComponents(string: self.absoluteString) else { return nil }
return url.queryItems?.first(where: { $0.name == queryParameterName })?.value
}
}
Step 2: How to use the extension
let newURL = URL(string: "http://mysite3994.com?test1=blah&test2=blahblah")!
newURL.valueOf("test1") // Output i.e "blah"
newURL.valueOf("test2") // Output i.e "blahblah"
I also made a URL extension, but put the query param lookup into a subscript.
extension URL {
subscript(queryParam:String) -> String? {
guard let url = URLComponents(string: self.absoluteString) else { return nil }
return url.queryItems?.first(where: { $0.name == queryParam })?.value
}
}
Usage:
let url = URL(string: "http://some-website.com/documents/127/?referrer=147&mode=open")!
let referrer = url["referrer"] // "147"
let mode = url["mode"] // "open"
It appears that none of existing answers work when the link leads to a web site created on Angular. This is because Angular's paths often include a # (hash) symbol in all links, which results in url.queryItems always returning nil.
If a link looks like this: http://example.com/path/#/morepath/aaa?test1=blah&test2=blahblah
Then the parameters can only be obtained from url.fragment. With some additional parsing logic added to #Matt's extension, a more universal code would look like this:
extension URL {
subscript(queryParam: String) -> String? {
guard let url = URLComponents(string: self.absoluteString) else { return nil }
if let parameters = url.queryItems {
return parameters.first(where: { $0.name == queryParam })?.value
} else if let paramPairs = url.fragment?.components(separatedBy: "?").last?.components(separatedBy: "&") {
for pair in paramPairs where pair.contains(queryParam) {
return pair.components(separatedBy: "=").last
}
return nil
} else {
return nil
}
}
}
Usage remains same:
let url = URL(string: "http://example.com/path/#/morepath/aaa?test1=blah&test2=blahblah")!
let referrer = url["test1"] // "blah"
let mode = url["test2"] // "blahblah"
Another way of doing this is to create an extension on URL to return the components, and then create an extension on [URLQueryItem] to retrieve the value from the queryItems.
extension URL {
var components: URLComponents? {
return URLComponents(url: self, resolvingAgainstBaseURL: false)
}
}
extension Array where Iterator.Element == URLQueryItem {
subscript(_ key: String) -> String? {
return first(where: { $0.name == key })?.value
}
}
And this is an example of how this could be used:
if let urlComponents = URL(string: "http://mysite3994.com?test1=blah&test2=blahblah")?.components,
let test1Value = urlComponents.queryItems?["test1"] {
print(test1Value)
}