Swift crash when NSURLConnection.sendAsynchronousRequest returns an error - swift

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

Related

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

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.

error in swift when using loadDataFromURL in Xcode 8.3

I am testing this code from Ray Wenderlich to download data from URL. I got it working, but I updated to Xcode 8.3 and now suddenly it does not work any longer. I got the advise back that my problem has already been resolved in the following link SWIFT: Error EXC_BAD_INSTRUCTION, however, when adding the try! option or adding a do-catch as suggested, this did not make the error go away. Here is the code again:
class func loadDataFromURL(_ url: URL, completion:#escaping (_ data: Data?, _ error: NSError?) -> Void) {
let session = URLSession.shared
// Use NSURLSession to get data from an NSURL
let loadDataTask = try! session.dataTask(with: url, completionHandler: { (data: Data?, response: URLResponse?, error: NSError?) -> Void in
if let responseError = error {
completion(nil, responseError)
print("something went wrong 1")
//activityIndicator.stopAnimating()
} else if let httpResponse = response as? HTTPURLResponse {
if httpResponse.statusCode != 200 {
let statusError = NSError(domain:"com.raywenderlich", code:httpResponse.statusCode, userInfo:[NSLocalizedDescriptionKey : "HTTP status code has unexpected value."])
completion(nil, statusError)
} else {
completion(data, nil)
//activityIndicator.stopAnimating()
}
}
} as! (Data?, URLResponse?, Error?) -> Void) //error is thrown here!!
loadDataTask.resume()
}
}
When I run the code I get the error code in the last line: "Thread 1: EXEC_BAD_INSTRUCTION(code=EXC_I386_INVOP,subcode=0x0)"
I had this problem when I tried to parsing data Asynchronously it got rid of the error and worked fine. I'm not sure but it may solve your problem,too.

Swift: How to download synchronously?

I am using following code, to download some files:
let url = NSURL(string:"https://www.example.org/")!
let task = NSURLSession.sharedSession().dataTaskWithURL(url) { (data, response, error) in
if error != nil {
NSLog("%#", "Error: \(error)");
return
}
NSLog("Loaded %i bytes", data!.length)
}
task.resume()
I want to process some of the files and quit my application after downloading. Therefore I need to know, when the download process is finished. The best would be, if there is a way to do this synchronously (no problem, if UI is blocked - it is just a spash screen with a progressbar). But as far as I understood this topic after some research, this is not possible in Swift any more...
I did wrap this code in a function, therefore I can't just add some code after the NSLog statement. What I need to know is: When did the last file finish downloading? How can I retrive this information?
EDIT: This code did work for me (but be aware, its deprecated!):
// download file synchonously ////////////////////////////////////////////////////
func downloadSync(fromURL: String, toPath: String) {
let request = NSURLRequest(URL: NSURL(string: fromURL)!)
var response: NSURLResponse?
do {
let data = try NSURLConnection.sendSynchronousRequest(request, returningResponse: &response)
data.writeToFile(toPath, atomically: true)
} catch {
print("Error while trying to download following file: " + fromURL)
}
}
After you invoke task.resume(), the download starts.
When the download does complete (or an error is received) the code
inside the { } following dataTaskWithURL is called. That's a closure and it's called asynchronously.
let task = NSURLSession.sharedSession().dataTaskWithURL(url) { (data, response, error) in
// This code is executed asynchronously after data has been received
}
task.resume()
Inside the closure you receive 3 params:
data: the NSData you requested
response: the whole NSURLResponse
error: an NSError object
These 3 values are optional, so could be nil.
E.g. error could be populated and data could be nil.
The synchronous way [DEPRECATED in iOS 9]
This approach has been deprecated in iOS 9 and you should NOT use it, however here's the code
var response: NSURLResponse?
var error: NSError?
let urlData = try NSURLConnection.sendSynchronousRequest(request, returningResponse: &response)

Swift: Block mainThread until function finished loading data / NSURLSession with completionHandler

I want to create a function which loads data from an url and then returns the responseData as NSData. I want to block the mainThread until the data is finished. Here is what I have so far:
Function:
typealias CompletionBlock = (NSData!, NSURLResponse!, NSError!) -> NSData
func requestURL(targetUrl: String, httpMethod: String, httpBody: String, completion: CompletionBlock){
// REQUEST
let target = NSURL(string: targetUrl) // URL
let request = NSMutableURLRequest(URL: target!) // REQUEST
// HTTP-METHOD
var method = httpMethod
if method != "POST" { method = "GET" } // STANDARD: GET
request.HTTPMethod = method
// HTTP-BODY
let body = httpBody
if body != "" {
request.HTTPBody = body.dataUsingEncoding(NSUTF8StringEncoding)
}
// NSURLSession
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(request, completionHandler: completion) // Compiler error!
task.resume()
}
Call:
requestURL(targetURL, "GET", "", { (responseData: NSData!, response: NSURLResponse!, error: NSError!) -> NSData in
if responseData != nil {
let resultString = NSString(data: responseData, encoding: NSUTF8StringEncoding) // NSASCIIStringEncoding
println("DATA:\n\(resultString)")
}
if error != nil {
println("ERROR:\n\(error)")
}
return responseData
})
I get an error at within the func in line 21:
let task = session.dataTaskWithRequest(request, completionHandler: completion)
Compiler: "Cannot invoke 'dataTaskWithRequest' with an argument list of type '(NSMutableURLRequest, completionHandler: completionBlock)"
As for question issue: typealias CompletionBlock = (NSData!, NSURLResponse!, NSError!) -> NSData
Your completion handler returns NSData but it shouldn't return anything as in declaration:
func dataTaskWithRequest(_ request: NSURLRequest,
completionHandler completionHandler: ((NSData!,
NSURLResponse!,
NSError!) -> Void)?) -> NSURLSessionDataTask
This caused a type error, because you had provided a wrong closure type.
And it is quite reasonable, because dataTaskWithRequest is designed to be asynchronous. It creates an HTTP request for the specified URL request object, and calls a handler upon completion.
If you really want to make a synchronous request you can use an old NSURLConnection API with sendSynchronousRequest, but you shouldn't do it, because synchronous requests are a very bad design choice: they block main UI thread and there is no way to cancel that request except when it errors on its own. That's why Apple created a new NSURLSession API, based on completion handlers and now deprecated synchronous requests in iOS 9.
Doing synchronous request is very bad, but this will do
let request = NSURLRequest() //set all url and method and so
var response: NSURLResponse?
var error: NSError?
NSURLConnection.sendSynchronousRequest(request, returningResponse: &response, error: &error)
important synchronous requests was removed in swift 2.0.
As Daniel said, this is a bad practice in general. Any time, you have to go out and get data and wait for a response, you should be handling that asynchronously. If not, your UI is going to hang up on the main thread, and the user is likely to think that your app has crashed.
Working asynchronously, you will have to keep in mind that your main thread is still working and won't have that data until it receives it in the completion block. If it's imperative, you should throw up a UI element to let the user know you are waiting ie. UIActivityIndicatorView

NSURLConnection sendAsynchronousRequest returning all nil in Completion Block (Swift)

I'm trying to ween myself off AFNetworking and use NSURLConnection from Swift. Although seemingly simple, I can't get this short block of code to return anything in the completion handler block. All three objects (response, data, error) are nil when I break within the completion handler block and po them in the console. It's definitely making the connection, as I can see it happen on the server end.
let url = NSURL(string: "http://192.168.0.5:8081/ac")
let urlR = NSURLRequest(URL: url)
let q = NSOperationQueue()
NSURLConnection.sendAsynchronousRequest(urlR, queue: q, completionHandler: { (response: NSURLResponse!, data: NSData!, error:NSError!) -> Void in
})
I can't seem to find anyone else having this issue, and have found several examples of people successfully using what as far as I can see is exactly this code. What am I doing wrong here?