9

I'm trying to check if a url image exist using a if statement. However when trying to test it by wrong image url it keep returning:

fatal error: unexpectedly found nil while unwrapping an Optional value.

code:

var httpUrl = subJson["image_url"].stringValue
let url = NSURL(string: httpUrl)
let data = NSData(contentsOfURL: url!)

if UIImage(data: data!) != nil {
}
1
  • 2
    That's a basic feature of the Swift language. You need to seriously download the Swift books from the Apple bookstore and read them. When you write url! it means "please crash if url is nil". Commented Sep 30, 2015 at 7:49

4 Answers 4

10

You can do it this way:

var httpUrl = subJson["image_url"].stringValue
if let data = NSData(contentsOfURL: url) {

   //assign your image here 
}
Sign up to request clarification or add additional context in comments.

2 Comments

is this swift 2 compatible? I get complaints: Use of unresolved identifier: subJson.
Swift 3 and 4 is different, and so the "if let data = NSData(contentsOfURL: url) { ... }" lines should be replaced with: "do { let data = try Data(contentsOf: url) ... } catch { ... }"
6

Other answers are telling you to unwrap the optional, but really the issue is that you are force-unwrapping the optional with !, despite it being nil.

When you write something! what you are saying is “something might be nil, but if it is, I want my program to crash”.

The reason a call might return nil is if the result is not valid – for example, if you try to fetch a key from a dictionary that isn’t there, or that a URL doesn’t point to a valid downloadable image.

You can combine the check for nil with an if statement that unwraps the optional and returns a non-optional value so long as the value wasn’t nil. You can also chain them together, so if you need to unwrap a value, then pass it into a call that also returns an optional, you can do it all in one if statement:

if let httpUrl = subJson["image_url"].string,   
       url = NSURL(string: httpUrl),
       data = NSData(contentsOfURL: url),
       image = UIImage(data: data)
{
    // use image value
}
else {
    // log some error
}

Note, on the first line, the call is to .string rather than .stringValue – .string also returns an optional with nil if the value isn’t present.

Of course, combining all these unwraps together means you can’t tell which one failed, so you may want to break them out into separate statements instead.

Comments

2

This code is tested and successful: if image url not exists no crash.

let url: NSURL = NSURL(string: "http://www.example.com/images/image.png")!
    do {
        let imgData = try NSData(contentsOfURL: url, options: NSDataReadingOptions())
        ImageView?.image = UIImage(data: imgData)
    } catch {
        print(error)
    }

1 Comment

You are quite right, Kazaka - the following works in Swift 5. Compared to the example by Eric Aya I would recommend using URL and Data (instead of NSURL and NSData). For example: if let url = URL(string: "example.com/cabbage.jpg") { do { let data = try Data(contentsOf: url) if let image = NSImage(data: data) { print(" *** (image)") } } catch { print(error) } }
1

You have to unwrap the optional like this:

if let image = data {
    // use image here
} else {
    // the data is nil
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.