"Execution was interrupted, reasno: EXC_BAD_INSTRUCTION" error as I try to make a GET request - swift

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.

Related

Making HTTP GET request with Swift 5

I am obviously missing something very fundamental/naïve/etc., but for the life of me I cannot figure out how to make simple GET requests.
I'm trying to make an HTTP GET request with Swift 5. I've looked at these posts/articles: one, two, but I can't get print() statements to show anything. When I use breakpoints to debug, the entire section within the URLSession.shared.dataTask section is skipped.
I am looking at the following code (from the first link, above):
func HTTP_Request() {
let url = URL(string: "http://www.stackoverflow.com")!
let task = URLSession.shared.dataTask(with: url) {(data: Data?, response: URLResponse?, error: Error?) in
guard let data = data else { return }
print(String(data: data, encoding: .utf8)!)
}
task.resume()
}
HTTP_Request()
I am running this in a MacOS Command Line Project created through XCode.
I would greatly appreciate any help I can get on this, thank you.
Right now, if there is an error, you are going to silently fail. So add some error logging, e.g.,
func httpRequest() {
let url = URL(string: "https://www.stackoverflow.com")! // note, https, not http
let task = URLSession.shared.dataTask(with: url) { data, response, error in
guard
error == nil,
let data = data,
let string = String(data: data, encoding: .utf8)
else {
print(error ?? "Unknown error")
return
}
print(string)
}
task.resume()
}
That should at least give you some indication of the problem.
A few other considerations:
If command line app, you have to recognize that the app may quit before this asynchronous network request finishes. One would generally start up a RunLoop, looping with run(mode:before:) until the network request finishes, as advised in the run documentation.
For example, you might give that routine a completion handler that will be called on the main thread when it is done. Then you can use that:
func httpRequest(completion: #escaping () -> Void) {
let url = URL(string: "https://www.stackoverflow.com")! // note, https, not http
let task = URLSession.shared.dataTask(with: url) { data, response, error in
defer {
DispatchQueue.main.async {
completion()
}
}
guard
error == nil,
let data = data,
let string = String(data: data, encoding: .utf8)
else {
print(error ?? "Unknown error")
return
}
print(string)
}
task.resume()
}
var finished = false
httpRequest {
finished = true
}
while !finished {
RunLoop.current.run(mode: .default, before: .distantFuture)
}
In standard macOS apps, you have to enable outgoing (client) connections in the “App Sandbox” capabilities.
If playground, you have to set needsIndefiniteExecution.
By default, macOS and iOS apps disable http requests unless you enable "Allow Arbitrary Loads” in your Info.plist. That is not applicable to command line apps, but you should be aware of that should you try to do this in standard macOS/iOS apps.
In this case, you should just use https and avoid that consideration altogether.
Make sure the response get print before exiting the process, you could try to append
RunLoop.main.run()
or
sleep(UINT32_MAX)
in the end to make sure the main thread won't exit. If you want to print the response and exit the process immediately, suggest using DispatchSemaphore:
let semphare = DispatchSemaphore(value: 0)
func HTTP_Request() {
let url = URL(string: "http://www.stackoverflow.com")!
let task = URLSession.shared.dataTask(with: url) {(data: Data?, response: URLResponse?, error: Error?) in
guard let data = data else { return }
print(String(data: data, encoding: .utf8)!)
semphare.signal()
}
task.resume()
}
HTTP_Request()
_ = semphare.wait(timeout: .distantFuture)
This works for me many times I suggest you snippet for future uses!
let url = URL(string: "https://google.com")
let task = URLSession.shared.dataTask(with: ((url ?? URL(string: "https://google.com"))!)) { [self] (data, response, error) in
do {
let jsonResponse = try JSONSerialization.jsonObject(with: data!, options: [])
print(jsonResponse)
guard let newValue = jsonResponse as? [String:Any] else {
print("invalid format")
}
}
catch let error {
print("Error: \(error)")
}
task.resume()
}

How to handle XPC connection interrupted in URLSession.shared.dataTask

This is my code, by which I am trying to catch the error, when server is down:
let task = URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in
if error != nil
{
self.displayMessage(userMessage: "Could not successfully perform this request. Please check yourr internet connection.")
print("error=\(String(describing: error))")
return
}
do {
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary
if let parseJSON = json {
if parseJSON["errorMessageKey"] != nil
{
self.displayMessage(userMessage: parseJSON["errorMessage"] as! String)
return
}
...
} else {
self.displayMessage(userMessage: "Could not successfully perform this request. Please try again later")
}
} catch {
self.displayMessage(userMessage: "Could not successfully perform this request. Please try again later")
print(error)
}
}
task.resume()
But in console I get "XPC connection error", instead of displaying alert.
How can I display Alert, when this error occures?
My environment:
Swift: 5
Xcode: 11.5
Target deployment: 13.4
Assuming displayMessage has no problem as you have not provided the code.
I would suggest you call the code which has the UIKit API, on the main thread. As the dataTask completion block is always called on a background thread. I would suggest you while calling the function which further has the code related to UIKit should always run on the main thread
Use UIKit classes only from your app’s main thread or main dispatch
queue, unless otherwise indicated. This restriction particularly
applies to classes derived from UIResponder or that involve
manipulating your app’s user interface in any way.
Have a look at the updated code snippet.
let task = URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in
// It ensure rest code placed inside run on the main thread. I assume displayMessage function having the code related to UIKit framework.
DispatchQueue.main.async {
if error != nil
{
self.displayMessage(userMessage: "Could not successfully perform this request. Please check yourr internet connection.")
print("error=\(String(describing: error))")
return
}
do {
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary
if let parseJSON = json {
if parseJSON["errorMessageKey"] != nil
{
self.displayMessage(userMessage: parseJSON["errorMessage"] as! String)
return
}
} else {
self.displayMessage(userMessage: "Could not successfully perform this request. Please try again later")
}
} catch {
self.displayMessage(userMessage: "Could not successfully perform this request. Please try again later")
print(error)
}
}
}
task.resume()

do - try - catch code doesnt try or catch. just do's

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

Snap to Roads in Swift

I am trying to implement a method that uses Googles snap to roads API however I have been unable to achieve any results.
I was able to successfully implement the directions API in to my Swift project using
https://maps.googleapis.com/maps/api/directions/json?origin=xyz
let request = NSURLRequest(URL: NSURL(string:directionURL)!)
let session = NSURLSession.sharedSession()
session.dataTaskWithRequest(request,
completionHandler: {(data: NSData!, response: NSURLResponse!, error: NSError!) in
if error == nil {
let object = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: nil) as! NSDictionary
println(object)
let routes = object["routes"] as! [NSDictionary]
for route in routes {
println(route["summary"])
}
dispatch_async(dispatch_get_main_queue()) {
//update your UI here
}
}
else {
println("Direction API error")
}
}).resume()
however if the GPS coordinates are even slightly different I get an entirely different result.
What I am trying to do is plot a users path the same each time even if the start/end coordinates a slightly different.
The error I am getting is
fatal error: unexpectedly found nil while unwrapping an Optional value
Any suggestions?
Thanks
EDIT:
I am trying this but this is what is causing the error
func directionAPITest() {
let directionURL = "https://roads.googleapis.com/v1/snapToRoads?path=-35.27801,149.12958|-35.28032,149.12907|-35.28099,149.12929|-35.28144,149.12984|-35.28194,149.13003|-35.28282,149.12956|-35.28302,149.12881|-35.28473,149.12836&interpolate=true&key=xyz"
let request = NSURLRequest(URL: NSURL(string:directionURL)!)
let session = NSURLSession.sharedSession()
}
I was able to resolve this after finding this post NSURL found nil while unwraping an Optional value
Basically had to escape the string.

Swift crash when NSURLConnection.sendAsynchronousRequest returns an error

Using the following code works fine UNLESS there is an error, then
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue(), completionHandler: {(response: NSURLResponse!,data: NSData!, error: NSError!) -> Void in
if error? {
...
}
else {
...
}
when is crashes with
"EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0"
on the if error? line.
Does anybody know why ?
Now NSURLConnection is deprecated now you should use NSURLSession instead still I am posting an example of NSURLConnection
in your code you are forcefully unwrap value of error: NSError! response: NSURLResponse!,data: NSData! is creating problem
let request = URLRequest(url: URL.init(string: "yourURL")!)
NSURLConnection.sendAsynchronousRequest(request, queue: OperationQueue.main) { (request, data, error) in
// Here you can check error with guard and data also
}
Hope it is helpful to you