unexpectedly found nil - error on File Upload with NSURLConnection - ios

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.

Related

iOS Swift Json Serialization breaking on strings with a return

If I return "test" with/without spaces it works. But when I return a value that a user stored using a return in the string then it fails with a nil error but when I look in the NSLog the value is there....
Code Before Failure
var url:NSURL = NSURL(string:PassURL)!
var postData:NSData = post.dataUsingEncoding(NSASCIIStringEncoding)!
var postLength:NSString = String( postData.length )
var request:NSMutableURLRequest = NSMutableURLRequest(URL: url)
request.HTTPMethod = "POST"
request.HTTPBody = postData
request.setValue(postLength as String, forHTTPHeaderField: "Content-Length")
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.setValue("application/json", forHTTPHeaderField: "Accept")
var reponseError: NSError?
var response: NSURLResponse?
var urlData: NSData? = NSURLConnection.sendSynchronousRequest(request, returningResponse:&response, error:&reponseError)
if ( urlData != nil ) {
let res = response as! NSHTTPURLResponse!;
NSLog("Response code: %ld", res.statusCode);
if (res.statusCode >= 200 && res.statusCode < 300)
{
var responseData:NSString = NSString(data:urlData!, encoding:NSUTF8StringEncoding)!
NSLog("Response ==> %#", responseData);
var error: NSError?
//FAILS HERE
let jsonData:NSDictionary = NSJSONSerialization.JSONObjectWithData(urlData!, options:NSJSONReadingOptions.MutableContainers , error: &error) as! NSDictionary
NSLog
2015-07-29 08:52:26.622 testApp[20648:187508] Response ==> {"success":1, "test": "Going to Return Now
Second Line"}
fatal error: unexpectedly found nil while unwrapping an Optional value
But the value is not nil...
NSError
Optional(Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldn’t be completed. (Cocoa error 3840.)" (Unescaped control character around character 41.) UserInfo=0x7f9c9942b050 {NSDebugDescription=Unescaped control character around character 41.})
The unescaped character is the return, how can I allow json to accept this?
var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary
OR
var error:NSError? = nil
var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options:nil, error: &error) as? NSDictionary
Since you can't post the actual string from the URLRequest, I can't say exactly what's wrong with it. But it sounds like characters no. 24 and 41 are not JSON compliant.
I'd review: json.org. And paste it into: jsonlint.com which'll give you more specifics. And find out why your endpoint is returning invalid JSON.
If you'd like to handle NSJSONSerialization returning nil, simply wrap it in an if let:
if let jsonData:NSDictionary = NSJSONSerialization.JSONObjectWithData(urlData!, options:NSJSONReadingOptions.MutableContainers , error: &error) as? NSDictionary {
/* It's a valid JSON object */
} else {
/* It's not a valid JSON object */
}
Note: Having an array at the root of the json, is not handled by this. If you want to handle that, just expand an else if let as? NSArray. Also, if urlData is nil, this will crash since we're force unwrapping it still.

Swift: Unexpectedly found nil

I'm not sure where the nil value is here. I also tried explicitly allocating the error var and still had the issue. The code is taken almost directly from Twitter documentation.
let statusesShowEndpoint = "https://api.twitter.com/1.1/users/profile_banner.json?"
let params = ["screen_name":"twitter"]
var clientError :NSError?
let request = Twitter.sharedInstance().APIClient.URLRequestWithMethod(
"GET", URL: statusesShowEndpoint, parameters: params,
error: &clientError)
if request != nil {
Twitter.sharedInstance().APIClient.sendTwitterRequest(request) {
(response, data, connectionError) -> Void in
if (connectionError == nil) {
var jsonError : NSError?
let json : AnyObject? =
NSJSONSerialization.JSONObjectWithData(data,
options: nil,
error: &jsonError)
}
else {
println("Error: \(connectionError)")
}
}
}
else {
println("Error: \(clientError)")
}
I get this error on the request:
fatal error: unexpectedly found nil while unwrapping an Optional value
I haven't spent much time with the twitter api, but the http endpoint you are trying to access requires that you have the qAuth authority have you done this? as the http link is coming back "bad authentication data" when i try to access it

Error while casting value to string with Swift IOS8

I'm new to programming for ios so my question may be silly ;-) I'm trying to parse some JSON data. My code look's like:
var task = session.dataTaskWithURL(url!, completionHandler: { (data, response, error) -> Void in
if(error != nil){
println("error")
}else{
var error: NSError?
var wetherData = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &error) as NSMutableDictionary
var wd = wetherData["current_observation"] as NSMutableDictionary
var xd = wd["temp_c"]! as String
println(xd);
}
})
I want xd variable to be a string but while casting i have an error
println(wd["temp_c"]) returns "Optional(4)"
wd["temp_c"] look's like this

iOS - Synchronous Request with Timeout failing

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)

Swift can't send URLRequest at all?

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.

Resources