0

Hi i try to find a way to parse JSON in SWIFT, this works great for me but i run into a problem.

I let the user enter a username that is used for the JSON URL -> if the user type in a valid username all works fine.

But if he enter a wrong username my parsing fails, this is correct too, but for now my app only crashes and i looking for a way to make a work around.

This is my Code where it crashes,

 let url0 = NSURL(string: newUrlPath!)
        let session0 = NSURLSession.sharedSession()
        let task0 = session0.dataTaskWithURL(url0!, completionHandler: {data, response, error -> Void in
            if (error != nil) {
                println(error)
            } else {
                let summonorID_JSON = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary

The Xcode Error

Error Domain=NSURLErrorDomain Code=-1002 "The operation couldn’t be completed. (NSURLErrorDomain error -1002.)" UserInfo=0x7c12d610 {NSErrorFailingURLKey=XX, NSErrorFailingURLStringKey=XX, NSUnderlyingError=0x7c12c8d0 "The operation couldn’t be completed. (kCFErrorDomainCFNetwork error -1002.)"} fatal error: unexpectedly found nil while unwrapping an Optional value

All is fine cause this is the return page i get from my Request

https://br.api.pvp.net/api/lol/br/v1.4/summoner/by-name/smirknaitiax?api_key=5c7d4d4f-f320-43d5-8647-643c9f6ee5de

And yes he can't parse this into a NSDirectory as its no JSON that returns (as its normally is) is there a way to take care that if this page comes up (so the user entered a wrong username) that i can exit my loop/take a other way ;)?

4 Answers 4

3
+50

You are using many operations which could all fail, and Swift is quite unforgiving about failure. Your code will crash if newURLPath is nil, if url0 is nil because newURLPath wasn't a valid URL.

So your URL request might return an error (the request itself failed), but you have the case that the URL request succeeded but gives unexpected results (not a JSON dictionary). Your code ending in "as NSDictionary" tells Swift: "I know I might not get a dictionary, but convert what you get to a dictionary and crash if this doesn't work". Just change this to

if let parsedJSON = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil)
{
    // Will still crash if the server sends a valid JSON array
    let summonorID_JSON = parsedJSON as NSDictionary
}
else
{
    // data wasn't valid JSON, handle it. 
}

The difference is that the optional value returned by the JSON parser will be accepted without crashing, and you check whether you received valid JSON or not.

Sign up to request clarification or add additional context in comments.

Comments

2

Since you are getting 404 on this request, I assume that this will happen every time something is bad with username, you should handle server response to fit that. First thing will be to check what server returned:

let httpResp: NSHTTPURLResponse = response as NSHTTPURLRespons

At this point you can access statusCode property, that will tell you if request was good or not (404). Having that information you can decide what to do, and for example, you can modify your code something like this:

let url0 = NSURL(string: newUrlPath!)
let session0 = NSURLSession.sharedSession()
let task0 = session0.dataTaskWithURL(url0!, completionHandler: {data, response, error -> Void in
    if (error != nil) {
        println(error)
    } else {
        let httpResp: NSHTTPURLResponse = response as NSHTTPURLRespons
        httpResp.statusCode != 404 {
            let summonorID_JSON = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary
        } else {
            // Handle error at this point, tell user to retype username etc.
        }
    })

Comments

0

NSURL is a failable initializer and exactly this happens when you give an invalid url: It fails to initialize.

So wrap your code in an conditional unwrap:

if let url0 = NSURL(string: newUrlPath!) {
    ...
}

2 Comments

Well but this won't fix the problem if the user enter a wrong username and i won't get a JSON back right?
If you can't transform newUrlPath! into an URL because the string is an invalid URL, then you have to stop there and ask the user to enter a valid username. You cannot fetch the JSON from the server without getting a valid URL first...
-1

The url0 becomes nil if user enter wrong data. If you use the nil value as url0! app will crash.

When you add a ! after a variable you tell the compiler the value will not be nil.

so to avoid the crash, you have to check for nil condition before calling

  let task0 = session0.dataTaskWithURL(url0!, completionHandler: {data, response, error -> Void in

1 Comment

Well with that i run into "Operand of postfix "!" should have optional type; type is NSURL

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.