I'm trying to get Dynamic Links to shorten my URL with the following code:
guard let link = URL(string: "https://myapp.com") else { return }
let dynamicLinksDomainURIPrefix = "https://app.myapp.com/link"
let linkBuilder = DynamicLinkComponents(link: link, domainURIPrefix: dynamicLinksDomainURIPrefix)
linkBuilder?.iOSParameters = DynamicLinkIOSParameters(bundleID: "com.myapp.ios")
guard let longDynamicLink = linkBuilder?.url else { return }
print("The long URL is: \(longDynamicLink)")
let options = DynamicLinkComponentsOptions()
options.pathLength = .short
linkBuilder?.options = options
linkBuilder?.shorten() { url, warnings, error in
guard let url = url, error != nil else { return }
print("The short URL is: \(url)")
}
It's printing the long URL fine, but the line below (for short URL) is never being called:
print("The short URL is: \(url)")
Because url returns nil and I have no idea why. Nothing I've found in the guides or online has lead me in the right direction.
What am I doing wrong??
I think it is because the following is incorrect:
guard let url = url, error != nil else { return }
You are saying make sure there is a non nil URL and make sure there is an error.
I think the Firebase docs are wrong. Instead, you want:
guard let url = url, error == nil else { return }
What you have done here :
linkBuilder?.shorten() { url, warnings, error in
guard let url = url, error != nil else { return }
print("The short URL is: \(url)")
}
is you are unwrapping the url and checking if error contains some Error, then you are printing 'The short URL is: (url)' it means if shorten() succeeds and there's no Error your print method will never be executed.
What you have to do is, First check if error doesn't contain any Error than call print()
linkBuilder?.shorten() { url, warnings, error in
guard error == nil else { return }
if let shortUrl = url {
print("The short url is \(shortUrl)")
}
}
Related
When passing the valid url of the string with the init the URL(string: urlString) returns nil. How to fix? When I enter a value from one word (for example, Moscow) everything works, when a city from two words is entered, I separate the request using split(separator: " ") and connect using .joined(separator: "%20") and get the city divided by %20 and return nil. How can this problem be solved?
enter image description here
enter image description here
You need to do addingPercentEncoding see my extension for that
extension String {
var url: URL? {
guard !isEmpty else { return nil }
if let url = URL(string: self) {
return url
} else if let urlEscapedString = addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed),
let escapedURL = URL(string: urlEscapedString) {
return escapedURL
}
return nil
}
}
Use the apiKey after encoding it:
let encodedKey = key.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
Essentially I am parsing JSON data and assigning it to a variable called addressPressNow I then have the following function that executes when a user taps on a UILabel:
The goal is to have Apple Maps open provided the variable value it contains.
Because I am assigning an address to a variable it will contain spaces
ex: 3981 Test Drive Cupertino CA 95014
NOTE: The value of the variable is being passed correctly because when I do print(addressPressNow) in func tapFunction it prints correctly.
#objc
func tapFunction(sender:UITapGestureRecognizer) {
let targetURL = NSURL(string: "http://maps.apple.com/?q=" + addressPressNow)!
UIApplication.shared.openURL(targetURL as URL)
}
The issue is I am having trouble applying the variable to the string URL with the following error:
Thread 1: Fatal error: Unexpectedly found nil while unwrapping an
Optional value
The following is how I am assigning the value to the variable:
struct FacilityInfo: Decodable {
let address: String
class infoViewController: UIViewController {
var addressPressNow : String = ""
override func viewDidLoad() {
super.viewDidLoad()
let tap = UITapGestureRecognizer(target: self, action: #selector(infoViewController.tapFunction))
addressInfo.isUserInteractionEnabled = true
addressInfo.addGestureRecognizer(tap)
let url = URL(string: "https://test/test/exampleā€¯)!
let task = URLSession.shared.dataTask(with: url) { data, response, error in
// ensure there is no error for this HTTP response
guard error == nil else {
print ("error: \(error!)")
return
}
// ensure there is data returned from this HTTP response
guard let data = data else {
print("No data")
return
}
// Parse JSON into array of Car struct using JSONDecoder
guard let cars = try? JSONDecoder().decode([FacilityInfo].self, from: data), let secondCar = cars.first
else {
print("Error: Couldn't decode data into cars array")
return
}
DispatchQueue.main.async {
self.addressPressNow = secondCar.facility_address
}
}
"I am assigning an address to a variable it will contain spaces"
If the address contains spaces then creating NSURL with the string will crash. You can use addingPercentEncoding to solve the problem
if let encodedAddress = addressPressNow.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) {
let targetURL = NSURL(string: "http://maps.apple.com/?q=" + encodedAddress)!
UIApplication.shared.openURL(targetURL as URL)
}
And don't use NSURL and force unwrapping. Update it like this
if let encodedAddress = addressPressNow.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed),
let targetURL = URL(string: "http://maps.apple.com/?q=" + encodedAddress) {
UIApplication.shared.openURL(targetURL)
}
As suggested by matt use URLComponents
let addressPressNow = "3981 Test Drive Cupertino CA 95014"
var components = URLComponents(string: "http://maps.apple.com")
components?.queryItems = [URLQueryItem(name: "q", value: addressPressNow)]
print(components?.url)//http://maps.apple.com?q=3981%20Test%20Drive%20Cupertino%20CA%2095014
if let targetURL = components?.url {
UIApplication.shared.open(targetURL, options: [:], completionHandler: nil)
}
You are saying
NSURL(string: "http://maps.apple.com/?q=" + addressPressNow)!
Notice the exclamation mark at the end. That means "if there's a problem, crash me". You can hardly complain if you do in fact crash; that is what you asked to do.
Basically, never use NSURL(string:) if you can avoid it. To form a valid URL, build it up using URLComponents. And form it out of valid components. (It is impossible to say whether facility_address is a valid URL query, because you have not shown what it is.)
Example:
var comp = URLComponents()
comp.scheme = "https"
comp.host = "maps.apple.com"
comp.queryItems = [URLQueryItem(name: "q", value: "1 Infinite Loop, Cupertino, CA")]
if let url = comp.url {
print(url) // https://maps.apple.com?q=1%20Infinite%20Loop,%20Cupertino,%20CA
}
That gives us a valid URL that actually works.
facing some issue to generate shortenURL from firebase dynamic-links , I am able to get longDynamicLink url . but
here is my code , I am using https://firebase.google.com/docs/dynamic-links/ios/create following steps DynamicLinkComponents.shortenURL completion not getting call and there is no error also
guard let longDynamicLink = linkBuilder.url else { return "test" }
print("The long URL is: \(longDynamicLink)")
DynamicLinkComponents.shortenURL(longDynamicLink, options: nil) { url, warnings, error in
guard let url = url, error != nil else { return }
print("The short URL is: \(url)")
}
DynamicLinkComponents.shortenURL this part is not executing
Try This Code. This Code Working Fine For Me.
let shareLink:String = "http://YourURL"
guard let newSharelink = URL(string: shareLink) else { return }
let components = DynamicLinkComponents.init(link: newSharelink, domain: "Your Domin From Genrated By Google Account(EX. = napu4u.app.goo.gl)")
let iOSParams = DynamicLinkIOSParameters(bundleID: "YourBundle ID")
iOSParams.appStoreID = "Your AppStore ID (Optional)"
components.iOSParameters = iOSParams
let options = DynamicLinkComponentsOptions()
options.pathLength = .short
components.options = options
components.shorten { (shortURL, warnings, error) in
if let error = error {
print(error.localizedDescription)
return
}
let shortLink = shortURL
print(shortLink)
}
Add this to to App Capabilities - Associated Domains and enter - applinks:yourdomain.com
In your ViewController add
guard let link = URL(string: "https://www.yourdomain.com/share_location.html?Id=\(RandomID)&uid=\(uid)") else { return }
let dynamicLinksDomain = "yourdomain.page.link"
let components = DynamicLinkComponents(link: link, domain: dynamicLinksDomain)
// [START shortLinkOptions]
let options = DynamicLinkComponentsOptions()
options.pathLength = .unguessable
components.options = options
// [END shortLinkOptions]
// [START shortenLink]
components.shorten { (shortURL, warnings, error) in
// Handle shortURL.
if let error = error {
print(error.localizedDescription)
return
}
print(shortURL?.absoluteString ?? "")
self.shortLink = shortURL
}
I'm calling a webpage in WKWebView but it always crashes when I launch the app, with this error message:
Thread 1: Fatal error: Unexpectedly found nil while unwrapping an
Optional value.
My code is below
let param = "https://myapp.mydomain.com/GameAPI/index.jsp?user=0202020767|0202020767"
let url = URL(string: param)
webView.load(URLRequest(url: url!))
At this point the nil is pointing to this code:
webView.load(URLRequest(url: url!))
I suspect that "|" character in the parameter is messing up your URL.
Try doing this:
let param = "user=0202020767|0202020767"
let escapedParam = param.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
let fullURLString = "https://myapp.mydomain.com/GameAPI/index.jsp?\(escapedParam)"
if let url = URL(string: fullURLString) {
webView.load(URLRequest(url: url))
} else {
Swift.print("url is nil for some reason")
}
This is happening, because the url that you have tried to reach could not be resolved.
Also, you better use optional binding rather than forcing unwrap.
Here the code that you can check with valid url:
if let url = URL(string: "your url") {
webView.load(URLRequest(url: url))
} else {
print("could not open url, it is nil")
}
I have a query on a Cloud CKRecord, which checks to see if a documents exists (i.e. has been uploaded as an CKAsset) and if not checks if a URL exists (i.e. has been uploaded as a String). All works well if either exist on their own for a given record, however if both exist when clicking on the link nothing happens.
I feel it is something to do with the if and else if statements -
if filename1 != nil {
let asset1 = record.object(forKey: "courseDocument1") as? CKAsset
let filename = record.object(forKey: "courseDocument1Filename") as! String
let path = (NSTemporaryDirectory() as NSString).appendingPathComponent(filename)
let doc1Data : NSData? = NSData(contentsOf:(asset1?.fileURL)!)
do {
try doc1Data!.write(to: URL(fileURLWithPath: path), options: .atomic)
let url = URL(fileURLWithPath: path)
let urlRequest = URLRequest(url: url)
self.courseDoc1WebView?.loadRequest(urlRequest)
self.venueDocButton1.setTitle(cseDocument1,for: [])
self.venueDocButton1.isHidden = false
self.courseDocumentLabel.isHidden = false
} catch {
print(error)
}
} else if cseDocument1URL != nil && filename1 == nil {
let url1 = URL (string: cseDocument1URL!)
let request1 = URLRequest(url: url1! as URL );
self.courseDoc2WebView.loadRequest(request1 as URLRequest);
self.venueDocButton1.setTitle(cseDocument1,for: [])
self.venueDocButton1.isHidden = false
self.courseDocumentLabel.isHidden = false
} else {
print("No Document Found")
}
Any thoughts?
This turned out to be a simple typo rather than logic -
self.courseDoc2WebView.loadRequest(request1 as URLRequest);
which should actually be -
self.courseDoc1WebView.loadRequest(request1 as URLRequest);
This was solved by printing responses and using the debugger - thanks Phillip Mills
Duncan C, you make a good point too - thank-you.