Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Downcast from 'UIImage?' to 'UIImage' only unwraps optionals

I'm creating a UIButton with an image,

I have written the below code for that:

    let btnImg=UIButton.buttonWithType(UIButtonType.Custom) as UIButton
    let img  = UIImage(named: "turn_left") as UIImage
    btnImg.setTitle("Turn left", forState: UIControlState.Normal)
    btnImg.setImage(img, forState: UIControlState.Normal)
    btnImg.frame = CGRectMake(10, 150, 200, 45)
    self.view.addSubview(btnImg)

But I got the error below at let img = UIImage(named: "turn_left") as UIImage:

Swift Compiler error:
 Downcast from 'UIImage?' to 'UIImage' only unwraps optionals; did you mean to use '!'?
like image 376
NetDemo Avatar asked Nov 13 '14 05:11

NetDemo


4 Answers

As error Says You have to use '!' ,

Try Below code,

   let img  = UIImage(named: "turn_left") as UIImage!  // implicitly unwrapped

OR

   let img : UIImage? = UIImage(named: "turn_left")  //optional

Edit

After creating img you need to check it for nil before using it.

like image 114
Toseef Khilji Avatar answered Nov 17 '22 10:11

Toseef Khilji


You can always do it in an 'if let' but note the difference in syntax depending on the version of swift.

Swift < 2.0:

if let img = img as? UIImage {

Swift 2.0:

if let img = img as UIImage! {

Note the position of the exclamation

like image 28
Dustin Williams Avatar answered Nov 17 '22 10:11

Dustin Williams


If the UIImage initialiser cannot find the file specified (or some other error happened), it will return nil, as per Apple's documentation

Return Value
The image object for the specified file, or nil if the method could not find the specified image.

So you need to put checks in:

let img  = UIImage(named: "turn_left")
if(img != nil) {
    // Do some stuff with it
}

You don't need to cast a UIImage to a UIImage, that's a waste.

Edit: Full code

let img  = UIImage(named: "turn_left")
if(img != nil) {
    let btnImg = UIButton.buttonWithType(UIButtonType.Custom) as UIButton
    btnImg.setTitle("Turn left", forState: UIControlState.Normal)
    btnImg.setImage(img, forState: UIControlState.Normal)
    btnImg.frame = CGRectMake(10, 150, 200, 45)
    self.view.addSubview(btnImg)
}

You may want to put an else in to set the button to a shape or something else that is more likely to work in the case "turn_left" doesn't exist.

like image 28
jonogilmour Avatar answered Nov 17 '22 10:11

jonogilmour


Since UIImage(named:"something") returns an optional (because it could be nil if the methods doesn't find an appropriate image the best this is not to explicitly unwrap the result (otherwise your app will crash) but to check for the result immediately with something like that:

        if let image = UIImage(named: "something"){
        // now you can use image without ? because you are sure to have an image here!
        image.description
        }

    // continue your code here using the optional power of swift's vars! :)

The approach is the following: If the image is optional means that it can be null. Functions that takes in input an optional can handle that, otherwise they usually have unexpected behavior. The UIImage(named:) can return nil and you HAVE to handle this. If you explicitly unwrap it you could have problems later.

With if let something = ... something will be automatically unwrapped in runtime and you can use it safely.

like image 2
GrizzlyBear Avatar answered Nov 17 '22 08:11

GrizzlyBear