thanks for any help upfront.
url session works perfect with connection, it prints the error as nil. but without it it prints the .localizedDescription just fine and shows me the right error, but then continues to do the do{ try } and crashes with this error in the try line:
Thread 6: Fatal error: Unexpectedly found nil while unwrapping an
Optional value
now I am not even sure if this has anything to do with the errorhandling. thanks for any help with understanding whats going on or just solving the problem!
func getData(completion: (() -> ())?) {
let urlString = URL(string: "https://api.coinmarketcap.com/v1/ticker/")
URLSession.shared.dataTask(with: urlString!, completionHandler: { (data, response , error) in
print("before entering do-try-catch", error?.localizedDescription)
do {
//create Dictionary
print("downloading content")
self.coinData = try JSONSerialization.jsonObject(with: data!) as! [[String:Any]]
//set connection status
self.connection = true
//update tableView
DispatchQueue.main.async {
completion?()
}
} catch {
print("catch", error.localizedDescription)
//set connection status
self.connection = false
//update tableView
DispatchQueue.main.async {
completion?()
}
}
}).resume()
}
Thread 6: Fatal error: Unexpectedly found nil while unwrapping an Optional value is a common problem for beginners.
You try to work with data that is not there.
So for example in your code you force to execute try JSONSerialization.jsonObject(with: data!)
When data is nil the code will crash.
The same at the beginning URLSession.shared.dataTask(with: urlString!, completionHandler: { (data, response, error) {}
When urlString is not a valid URL the code will be crash. (In this case the url seems to be valid).
For more information have a look here:
https://stackoverflow.com/a/24034551/4420355
Try the following snipped it should work
if let data = data {
self.coinData = try JSONSerialization.jsonObject(with: data) as? [[String:Any]]
//... work with coinData
}
Reason why it is crashing is because data is Optional and it should be nil or has some value. On line
self.coinData = try JSONSerialization.jsonObject(with: data!) as! [[String:Any]]
Compiler thinks:
Let's take a look and unwrap this Optianal variable. But it's nil, there is "nothing"! So what should I unwrap? Let's crash and throw Fatal Error message.
How to easily avoid this with Optional binding:
if let data = data {
....do something with data
} else {
...print error message
}
For more information take look at this brilliant answer.
https://stackoverflow.com/a/32170457/3046686
Related
I'm using Swift 4 and trying to get images from my server. Using ipconfig in terminal, I know my localhost's ip is 10.43.229.215.
the following code is to retrieve the image data and turn it into UIImage:
func GetImage(url:String) {
let image = String(localIP + url).addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
let url = URL(string: image)
print(image)
URLSession.shared.dataTask(with: url!, completionHandler: { (data, response, error) in
if error != nil {
print("Client error!")
return
}
guard let data = data else {
print("Error: did not receive data")
return
}
DispatchQueue.main.async {
self.LensImageView.image = UIImage(data: data)
}
}).resume()
}
What I don't understand is that, the image string did show the image I want if I copy/paste the string to my browser
(http://10.43.229.215:3000/lensPic/%E5%A4%AA%E5%A6%83%E7%B3%96%E6%9D%8F.png)
However, error appears at the line self.LensImageView.image = UIImage(data: data) saying Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value.
I'm really confused about:
How can data be nil if there is already a guard let method?
Why can the data be nil is I can show the image through my browser?
Any help is highly appreciated!
The problem lies in making a false assumption about what is nil. It has nothing to do with the image or the data. What’s nil is self.LensImageView, the outlet property.
I am trying to run this in my playground:
func getWeatherForecast(){
let Endpoint : String = "http://dataservice.accuweather.com/currentconditions/v1/{}"
let url = URL(string:Endpoint)
let parameters = ["apikey":"API_KEY"] as [String:Any?]
var urlRequest = URLRequest(url:url!)
do
{urlRequest.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted)
} catch {
print("error")
}
let task = URLSession.shared.dataTask(with: urlRequest) {(data, response, error) in
do {
let json = try JSONSerialization.jsonObject(with: data!, options: [])
print("The Response is : ",json)
} catch {
print("JSON error: \(error.localizedDescription)")
}
}
task.resume()
}
getWeatherForecast()
Then I keep getting the two following errors:
error: Execution was interrupted, reason: EXC_BAD_INSTRUCTION
(code=EXC_I386_INVOP, subcode=0x0).
The process has been left at the point where it was interrupted, use
"thread return -x" to return to the state before expression
I have tried many variations of running this API call and I cannot figure out what is wrong with my code. Can anyone help out here? I am just trying to make a simple GET but it seems to keep telling me "Fatal Error: Unexpectedly found nil while unwrapping an optional value" I feel that I have unwrapped correctly.
Any help would be much appreciated. Thank you!
You are calling an "http" url which is blocked by Apple, because it is insecure. You have to use "https" or temporary allow that in the plist file.
I am trying to use swiftyjson and I am getting an Error:
Call can throw, but it is marked with 'try' and the error is not
handled.
I have validated that my source JSON is good. I've been searching and cannot find a solution to this problem
import Foundation
class lenderDetails
{
func loadLender()
{
let lenders = ""
let url = URL(string: lenders)!
let session = URLSession.shared.dataTask(with: url)
{
(data, response, error) in
guard let data = data else
{
print ("data was nil?")
return
}
let json = JSON(data: data)
print(json)
}
session.resume()
}
}
Thank you for all the help!
The SwiftyJSON initializer throws, the declaration is
public init(data: Data, options opt: JSONSerialization.ReadingOptions = []) throws
You have three options:
Use a do - catch block and handle the error (the recommended one).
do {
let json = try JSON(data: data)
print(json)
} catch {
print(error)
// or display a dialog
}
Ignore the error and optional bind the result (useful if the error does not matter).
if let json = try? JSON(data: data) {
print(json)
}
Force unwrap the result
let json = try! JSON(data: data)
print(json)
Use this option only if it's guaranteed that the attempt will never fail (not in this case!). Try! can be used for example in FileManager if a directory is one of the default directories the framework creates anyway.
For more information please read Swift Language Guide - Error Handling
You should wrap it into a do-catch block. In your case:
do {
let session = URLSession.shared.dataTask(with: url) {
(data, response, error) in
guard let data = data else {
print ("data was nil?")
return
}
let json = JSON(data: data)
print(json)
}
} catch let error as NSError {
// error
}
Probably you need to implement do{} catch{} block. Inside do block you have to call throwable function with try.
I'm a newbie to Swift. I'm trying to simply read in a web page and I am getting the error "Initialization of immutable value 'task' was never used; consider replacing it with assignment to '_' or removing it" error on the "let task = " statement. Here's my code (please excuse my debugging statements). What am I doing wrong?
let urlPath = "http://www.stackoverflow.com"
let url = URL(string: urlPath)
let session = URLSession.shared
let task = session.dataTask(with:url!) { (data, response, error) -> Void in
if (error == nil) {
print("inside If")
print(data)
} else {
print("inside Else")
print(error)
}
print("after If Else")
}
What you are seeing is actally a warning, the compiler is telling you that you initialized a varaible but never used it. In general you can either replace the variable name with _ or remove the declaration entirely since you are not using it (or just ignore the warning). However in your case you actually need it, after you initialize the data task, you are not actually using it, which is why you aren't seeing any of your print statements being output. To fix this, call task.resume(). Doing this will also remove the warning since you are now actually using that variable.
let urlPath = "http://www.stackoverflow.com"
let url = URL(string: urlPath)
let session = URLSession.shared
let task = session.dataTask(with:url!) { (data, response, error) -> Void in
if (error == nil) {
print("inside If")
print(data)
} else {
print("inside Else")
print(error)
}
print("after If Else")
}
task.resume()
For some reason whenever I try to update my label with the current temperature using self.infoLabel.text = String(temp!) inside of the DispatchQueue code block, I get the following fatal error message:
unexpectedly found nil while unwrapping an Optional value.
I'd appreciate if someone could help me figure out why the code below isn't working. Thanks.
func getCurrentTemp(city: String){
let weatherRequestURL = URL(string: "\(openWeatherMapBaseURL)?APPID=\(openWeatherMapAPIKey)&q=\(city)")!
// The data task retrieves the data.
URLSession.shared.dataTask(with: weatherRequestURL) { (data, response, error) in
if let error = error {
// Case 1: Error
print("Error:\n\(error)")
}
else {
//print("Raw data:\n\(data!)\n")
//let dataString = String(data: data!, encoding: String.Encoding.utf8)
//print("Human-readable data:\n\(dataString!)")
do {
// Try to convert that data into a Swift dictionary
let weather = try JSONSerialization.jsonObject(with: data!, options:.allowFragments) as! [String:AnyObject]
if let main = weather["main"] as? [String: Any] {
let temp = main["temp"] as? Double
print("temp\(temp!)")
DispatchQueue.main.sync(execute: {
self.infoLabel.text = String(temp!)
})
//return temp as? String
//let temp_max = main["temp_max"] as? Double
//print("temp\(temp_max!)")
//let temp_min = main["temp_min"] as? Double
//print("temp\(temp_min!)")
}
}
catch let jsonError as NSError {
// An error occurred while trying to convert the data into a Swift dictionary.
print("JSON error description: \(jsonError.description)")
}
}
}
.resume()
}
There are two possibilities here: 1) either temp is nil (and it shouldn't be because you already force unwrap it in the print statement above) 2) or infoLabel is nil which happens if you broke your outlet connection.
Its easy to check; make a breakpoint above your assignment and in the debug console you can type:
po self.infoLabel
to see if its nil. For good measure you an also check temp.
You can also add a print statement to check self.infoLabel or an assert.
Alright, so I found a makeshift solution to this issue (See Below). Rather than placing the code inside of the function I made, I placed it in the viewDidLoad() function. For whatever reason, self.infoLabel? would be nil anywhere inside of the function I made.
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
print("Sucessful launched weather page.")
let weatherRequestURL = URL(string: "\(openWeatherMapBaseURL)?APPID=\(openWeatherMapAPIKey)&q=\(city)")!
// The data task retrieves the data.
URLSession.shared.dataTask(with: weatherRequestURL) { (data, response, error) in
if let error = error {
// Case 1: Error
print("Error:\n\(error)")
}
else {
//print("Raw data:\n\(data!)\n")
//let dataString = String(data: data!, encoding: String.Encoding.utf8)
//print("Human-readable data:\n\(dataString!)")
do {
// Try to convert that data into a Swift dictionary
let weather = try JSONSerialization.jsonObject(with: data!, options:.allowFragments) as! [String:AnyObject]
if let main = weather["main"] as? [String: Any] {
let temp = main["temp"] as? Double
print("temp\(temp!)")
var tempInFarenheit = ((9/5)*((temp!)-273) + 32).rounded()
DispatchQueue.main.sync(execute: {
self.infoLabel.text = "\(tempInFarenheit) + °"
})
}
}
catch let jsonError as NSError {
// An error occurred while trying to convert the data into a Swift dictionary.
print("JSON error description: \(jsonError.description)")
}
}
}
.resume()
}
Although this isn't the most effective way of doing things, hopefully it can help others who are having the same problem. If I find a more effective way of doing this, I'll be sure to edit this post and include it.