I have code that looks like this:
let urlPath: String = "https://github.com/zemirco/sf-city-lots-json/raw/master/citylots.json"
var url: NSURL = NSURL(string: urlPath)!
var request1: NSURLRequest = NSURLRequest(URL: url,
cachePolicy: NSURLRequestCachePolicy.ReturnCacheDataElseLoad,
timeoutInterval: 1)
var response:NSURLResponse?;
var error:NSError?;
/*** the follow line is giving the error ***/
var data:NSData = NSURLConnection.sendSynchronousRequest(
request1,
returningResponse: &response,
error: &error)!
if( error != nil) {
println ("ERROR")
} else {
println(response)
self.config = (NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary)
}
println("Done with Synchronous Request")
If the request takes too long, there's a fatal error: unexpectedly found nil while unwrapping an Optional value for the NSURLConnection.sendSynchronousRequest(...) call. I'm not sure what is going on. When I looked at the debug window, the only variable that is nil is response. This code looks very similar to the examples I've seen across the web.
If the request is finished within the time, no fatal error happens.
I want to be able to catch the timeout error. Anyone know what's wrong with the code?
You have the exclamation mark in the wrong place in this line,
var data:NSData = NSURLConnection.sendSynchronousRequest(request1, returningResponse: &response, error: &error)!
It should be,
var data:NSData! = NSURLConnection.sendSynchronousRequest(request1, returningResponse: &response, error: &error)
Related
I'm working on a passbook capable swift application and i'm in front of a strange problem.
Randomly, the passbook i download from my server is corrupted (the same downloaded can be good or corrupted).
Here is the code :
func openPass(pass: PKPass)
{
let passname = "Benight Ticket"
var passcontroller = PKAddPassesViewController(pass: pass)
passcontroller.delegate = self
self.presentViewController(passcontroller, animated: true, completion: nil)
}
func getTicketPassbook()
{
let TicketID: String = "2gBOZqWwNj"
let sessionConfig = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: sessionConfig, delegate: nil, delegateQueue: nil)
let request = NSMutableURLRequest(URL: NSURL(string: "https://exemple.com/index.php")!)
request.HTTPMethod = "POST"
let postString: String = "ObjectId=" + TicketID + "&authKey=\"exemple\""
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
let task = session.dataTaskWithRequest(request, completionHandler: { (data: NSData!, response: NSURLResponse!, error: NSError!) -> Void in
println("response = \(response)")
if (error == nil) {
// Success
let statusCode = (response as! NSHTTPURLResponse).statusCode
if (statusCode == 200)
{
println("Success: \(statusCode)")
var pkfile : NSData = NSData(data: data)
var pass: PKPass = PKPass(data: pkfile, error: nil)
self.openPass(pass)
}
// This is your file-variable:
// data
}
else {
// Failure
println("Faulure: %#", error.localizedDescription);
}
})
task.resume()
}
The error is the following : 2015-08-22 16:18:28.328 Application[10302:1018965] BOM could not extract archive: Couldn't read PKZip signature
And other times it works.... It's really at random times that it works or fail...
EDIT : Sometis i've also the following error : 2015-08-23 01:19:19.483 Benight[3467:994898] Invalid data error reading pass pass.com.apple.demo/8j23fm3. The passTypeIdentifier or teamIdentifier provided may not match your certificate, or the certificate trust chain could not be verified.
fatal error: unexpectedly found nil while unwrapping an Optional value
I was reading the different ways to parse REST API calls in Swift and came across the following:
var url : String = "http://google.com?test=toto&test2=titi"
var request : NSMutableURLRequest = NSMutableURLRequest()
request.URL = NSURL(string: url)
request.HTTPMethod = "GET"
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue(), completionHandler:{ (response:NSURLResponse!, data: NSData!, error: NSError!) -> Void in
var error: AutoreleasingUnsafeMutablePointer<NSError?> = nil
let jsonResult: NSDictionary! = NSJSONSerialization.JSONObjectWithData(data, options:NSJSONReadingOptions.MutableContainers, error: error) as? NSDictionary
if (jsonResult != nil) {
// process jsonResult
} else {
// couldn't load JSON, look at error
}
})
The one line that makes no sense to me is var error: AutoreleasingUnsafeMutablePointer<NSError?> = nil. We already captured our NSError parameter and stored it in a variable called error, and now we're overwriting that and making it nil in our first line in the closure? Or if somehow Swift then performs a downcast of the error from type NSError! to AutoreleasingUnsafeMutablePointer<NSError?>, then can someone explain how that happens?
Thanks!
AutoreleasingUnsafeMutablePointer is the equivalent to NSError** in Objective-C, which is used in methods as an inout expression. The syntax looks very strange.
The most reliable way is to consider both errors and define a second error variable. As GET is the default HTTP method of NSURLRequest, an immutable request is sufficient.
let url = "http://google.com?test=toto&test2=titi"
let request = NSURLRequest(URL: NSURL(string: url)!)
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue(), completionHandler:{ (response:NSURLResponse!, data: NSData!, error: NSError!) -> Void in
if error != nil {
// handle NSURLConnection error
} else {
var jsonError : NSError?
if let jsonResult = NSJSONSerialization.JSONObjectWithData(data, options:NSJSONReadingOptions.MutableContainers, error: &jsonError) as? NSDictionary {
// process jsonResult
} else {
// couldn't load JSON, look at jsonError
}
}
})
Any idea why sendSynchronousRequest not work, and returns nil. Error and response is nil as well.
let url = NSURL(fileURLWithPath: "http://google.com")!
let ur = NSMutableURLRequest(URL: url)
let response: AutoreleasingUnsafeMutablePointer<NSURLResponse?> = nil
let errorPtr = NSErrorPointer()
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
let data = NSURLConnection.sendSynchronousRequest(ur, returningResponse: response, error: errorPtr)
if errorPtr != nil {
var error: NSError = errorPtr.memory!
}
})
UPDATE
I tried in the async way:
var oq = NSOperationQueue()
NSURLConnection.sendAsynchronousRequest(ur, queue: oq, completionHandler: {response, data, error in
let ii = 7
})
Here I get an error:
(lldb) po error
Error Domain=NSURLErrorDomain Code=-1100 "The requested URL was not found on this server." UserInfo=0x1567f9d0 {NSErrorFailingURLStringKey=file:///http:/google.com, NSErrorFailingURLKey=file:///http:/google.com, NSLocalizedDescription=The requested URL was not found on this server., NSUnderlyingError=0x15691880 "The requested URL was not found on this server."}
Strange google is not available?
You are using fileURLWithPath and that will return the URL
file:///private/var/folders/xs/6k9v2g217155wr9vgb3xrg_80000gn/T/com.apple.dt.Xcode.pg/containers/com.apple.dt.playground.stub.iOS_Simulator.MyPlayground-F81D60A5-6797-4BEB-8AB9-2D156E2B6771/http:/google.com
What you need is let url = NSURL(string: "http://google.com")!
and that will return the URL:
http://google.com
No matter what I do it seems I'm unsuccessful in sending requests. Given the below sample code I copied word for word just to see the results. Yet nothing happens, I'm really confused and need help figuring out why i can send requests fine with objective c but no matter how many variations NSURLRequest NSURLSession I try it never works on swift.
var url : String = "http://google.com?test=toto&test2=titi"
var request : NSMutableURLRequest = NSMutableURLRequest()
request.URL = NSURL(string: url)
request.HTTPMethod = "GET"
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue(),
completionHandler:{ (response:NSURLResponse!, data: NSData!, error: NSError!) -> Void in
var error: AutoreleasingUnsafeMutablePointer<NSError?> = nil
let jsonResult: NSDictionary! = NSJSONSerialization.JSONObjectWithData(data, options:NSJSONReadingOptions.MutableContainers, error: error) as? NSDictionary
if (jsonResult != nil) {
println("help me")
// process jsonResult
} else {
println("hmmm")
// couldn't load JSON, look at error
}
})
DO NOT test network asynchronous requests on a commande line project.
The execution flow will stop before the asynchronousRequest terminates... You would need to add a run loop for that. Check out this link for an example.
You should take the habit to print out everything you get from a request, to understand what is going on. You can comment out everything after you are sure the request is working as expected.
var url : String = "http://google.com?test=toto&test2=titi"
var request : NSMutableURLRequest = NSMutableURLRequest()
request.URL = NSURL(string: url)
request.HTTPMethod = "GET"
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue(),
completionHandler:{ (response:NSURLResponse!, data: NSData!, error: NSError!) -> Void in
println("OK")
var strData = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Body: \(strData)\n\n")
println("Response: \(response)")
var err:NSError?
let jsonResult: NSDictionary! = NSJSONSerialization.JSONObjectWithData(data, options:NSJSONReadingOptions.MutableContainers, error: &err) as? NSDictionary
if (jsonResult != nil) {
println("jsonresult : \(jsonResult)")
// process jsonResult
} else {
println(err.debugDescription)
// couldn't load JSON, look at error
}
})
I added a line to print the NSData converted to a NSString.
Here the data is nil.
That explains the JSON parsing error.
Also, the way you create the error is not right. Check out my version to correct it.
You aren't checking for the results of your various variables. If you're trying to diagnose problems, you have to look at each critical variable. For example, first check to see if the request succeeded and if not, quit immediately. Otherwise, try parsing the JSON, showing the resulting object if successful, but showing the parsing error on failure. If the JSON parsing fails (as it will with this URL), you might even look at the string representation of the returned data.
FYI, the handling of the NSError object with NSJSONSerialization is also incorrect. It should look like:
var parsingError: NSError?
if let jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: &parsingError) as? NSDictionary {
// success, use `jsonResult`
} else {
// failure, look at `parsingError`
}
Putting that all together:
let url = "http://google.com?test=toto&test2=titi"
let request = NSMutableURLRequest(URL: NSURL(string: url)!)
request.HTTPMethod = "GET"
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue()) {
response, data, error in
if data == nil {
println("request error: \(error)")
return
}
var parsingError: NSError?
if let jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: &parsingError) as? NSDictionary {
println("json parsed: \(jsonResult)")
} else {
println("parsing error: \(parsingError)")
let responseString = NSString(data: data, encoding: NSUTF8StringEncoding)
println("data: \(responseString)")
}
}
This will, with this particular URL, fail, because the response is not JSON, but this will also show you the string representation of the response.
I am using the following function to upload a image to a given url.
I built this function based on the answers given to these to questions:
NSURLConnection Using iOS Swift and How to send UIImage in JSON format, by filling a NSDictionary
func uploadFileToUrl(url:NSURL){
var request = NSMutableURLRequest(URL:url)
request.HTTPMethod = "POST"
request.HTTPBody = NSData.dataWithData(UIImagePNGRepresentation(image))
var response: AutoreleasingUnsafeMutablePointer<NSURLResponse?>=nil
var error: AutoreleasingUnsafeMutablePointer<NSErrorPointer?> = nil
var dataVal: NSData = NSURLConnection.sendSynchronousRequest(request, returningResponse: response, error:nil)!
var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(dataVal, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary
if (error != nil) {
println("Request didn't go through")
}
println("Synchronous\(jsonResult)")
}
However when I run my app I always get an "fatal error: unexpectedly found nil while unwrapping an Optional value" on the following line:
var dataVal: NSData = NSURLConnection.sendSynchronousRequest(request, returningResponse: response, error:nil)!
What am I doing wrong? Thanks
First off, you aren't passing your error pointer when you make the request, so you will never know if that failed.
Secondly, as already mentioned, you are force unwrapping your dataVal variable without checking the value. So if your request did error and you don't handle it, you end up with the error you showed.
See the code below for a working example.
func uploadFileToUrl(url:NSURL){
var request = NSMutableURLRequest(URL:url)
request.HTTPMethod = "POST"
request.HTTPBody = NSData.dataWithData(UIImagePNGRepresentation(image))
var response: AutoreleasingUnsafeMutablePointer<NSURLResponse?>=nil
var HTTPError: NSError? = nil
var JSONError: NSError? = nil
var dataVal: NSData? = NSURLConnection.sendSynchronousRequest(request, returningResponse: response, error: &HTTPError)
if ((dataVal != nil) && (HTTPError == nil)) {
var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(dataVal!, options: NSJSONReadingOptions.MutableContainers, error: &JSONError) as NSDictionary
if (JSONError != nil) {
println("Bad JSON")
} else {
println("Synchronous\(jsonResult)")
}
} else if (HTTPError != nil) {
println("Request failed")
} else {
println("No Data returned")
}
}
If there's a problem, NSURLConnection.sendSynchronousRequest returns nil. You do have a problem, and it is returning nil. You are then force-unwrapping that nil with your exclamation mark. Hence the crash.
Instead, type dataVal as an NSData? which is what you are getting back (and remove the exclamation mark). Now you won't crash. Now in the next line look to see whether dataVal is nil. If it is, you know you've got a problem, and now you can read the error to see what the problem was.
If it isn't, now you can unwrap it and hand it off to NSJSONSerialization for interpretation.