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")
}
Related
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)")
}
}
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.
I have Medicine struct that holds image_origin URL of image I want to download and set to the ImageView.
For downloading/caching purposes I'm using Kingfisher framework.
let m = medicines[indexPath.row]
cell.medicineImage.kf.setImage(with: URL(string: m.value(forKeyPath: "image_origin") as! String)!)
cell.medicineName.text = m.value(forKeyPath: "i_name") as? String
In the code above m is an NSManagedObject of CoreData. I try to get image URI from the CoreData and set it to the ImageView, but every time at the line 2 I get the following error message: Unexpectedly found nil while unwrapping an Optional value
I have tried changing variables and Optinal types, tried to hardcode URI but without success.
What am I doing wrong?
P.S. Im using Swift4
Just unwrap safely to fix the crash and check your database if you are not getting the urlString properly,
if let urlString = m.value(forKeyPath: "image_origin") as? String {
print(urlString)
guard let url = URL(string: urlString) else { return }
cell.medicineImage.kf.setImage(with: url)
}
There might be a problem with image_origin key that I may have value as string or may not have. So, just need to confirm the value and use it
let m = medicines[indexPath.row]
cell.medicineName.text = m.value(forKeyPath: "i_name") as? String
guard let urlPath = m.value(forKeyPath: "image_origin") as? String, let url = URL(string: urlPath) else { return }
cell.medicineImage.kf.setImage(with: url)
Really cannot figure this one out, the URL prints and is not equal to nil, and it works in the browser when I paste it in. Any ideas?
import UIKit
class WebViewController: UIViewController {
var postLink: String = String()
#IBOutlet weak var mywebView: UIWebView!
override func viewDidLoad() {
super.viewDidLoad()
print(postLink)
let attempt = postLink
let url: URL = URL(string: attempt)!
let request: URLRequest = URLRequest(url: url)
mywebView.loadRequest(request)
}
The error occurs at:
let url: URL = URL(string: attempt)!
I am guess you are passing the urlString from another controller, do that instead
var postUrlString:String? //<-- make it optional
override func viewDidLoad() {
super.viewDidLoad()
guard let urlString = postUrlString, // forced unwrapped
let url = URL(string: urlString)
else { return } // if there is any optional we return
// else continue
let request: URLRequest = URLRequest(url: url)
mywebView.loadRequest(request)
}
The error is simple, postLink, you are providing to create URL is not correct. My guess is its empty.(Just a guess) and you have forgot to set it.
Avoid using force unwrapping ! in your code as much as possible.
You should either use guard let or if let in the scenarios.
In your case you might want to show some error to user when you are unable to load. Instead of
let url: URL = URL(string: attempt)!
use
if let url = URL(string: attempt) {
let request = URLRequest(url: url)
mywebView.loadRequest(request)
} else {
// Do something like. Show an alert that could not load webpage etc.
}
Alternatively you can use guard let, but it would require to return from the function where it is used. To know more about uses of if and guard let you can go through by blog post here.
Getting an "unexpected found nil" error, but when checking the value - its there:
override func viewDidLoad() {
super.viewDidLoad()
if whichLink == "official link" {
let urlStr = videoGame.offLink!
let url = NSURL(string: urlStr)!
let request = NSURLRequest(URL: url)
webView.loadRequest(request)
}
else if whichLink == "moby game link" {
print("yo yo yo, value is here! \(videoGame.mgLink) ")
let urlStr1 = videoGame.mgLink!
let url1 = NSURL(string: urlStr1)!
let request = NSURLRequest(URL: url1)
webView.loadRequest(request)
}
}
I'm suspecting an error in storyboard... but can't locate anything.
Did anyone has a clue what can be wrong?
The full project can be found # https://github.com/flostik2008/Favorite-Games
Your URL string is incorrectly formatted with the space at the end, so the NSURL initialization is returning nil.
You should URL encode all raw strings before trying to create an NSURL:
let urlStr1 = videoGame.mgLink!.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())! should work