2014-11-13 7 views
19

Sto creando un UIButton con un'immagine,Downcast da "UIImage?" a 'UIImage' scarta solo optional

ho scritto il codice qui sotto per questo:

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) 

Ma ho avuto l'errore sotto al let img = UIImage(named: "turn_left") as UIImage:

Swift Compiler error: 
Downcast from 'UIImage?' to 'UIImage' only unwraps optionals; did you mean to use '!'? 

risposta

36

Come errore Dice Devi usare '!' ,

Prova Di seguito il codice,

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

O

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

Modifica

Dopo aver creato img è necessario controllare per nil prima di utilizzarlo.

+0

Grazie! Funziona per me .. :) – NetDemo

+2

Diffida di questa soluzione. Mentre funzionerebbe, stai ancora esplicitamente lanciando il tuo UIImage a un UIImage (codice superfluo), e non sfruttando la digitazione implicita Swifty. Devi anche controllare che "img" non sia nulla prima di fare qualcosa con esso. – jonogilmour

2

Se l'initialiser UIImage non riesce a trovare il file specificato (o qualche altro errore è accaduto), tornerà nil, come da documentazione di Apple

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

quindi è necessario mettere i controlli in:

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

Non è necessario trasmettere un UIImage a un UIImage, questo è uno spreco.

Edit: codice completo

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) 
} 

Si consiglia di porre else in per impostare il pulsante per una forma o qualcosa d'altro che è più probabile che il lavoro nel caso "turn_left" non esiste.

+0

Grazie per la risposta. – NetDemo

+1

Swift non usa parentesi in un'istruzione 'if'. – davidgoli

2

Dal UIImage(named:"something") restituisce un opzionale (perché potrebbe essere nullo se i metodi non trova un'immagine appropriata il meglio non è quello di scartare esplicitamente il risultato (altrimenti l'app si bloccherà) ma per verificare immediatamente il risultato con qualcosa di simile:

 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! :) 

l'approccio è il seguente: se l'immagine è facoltativo significa che può essere nullo Funzioni che prende in input un optional in grado di gestire che, altrimenti di solito hanno un comportamento imprevisto il UIImage(named:).. può restituire nil e tu DEVI gestire questo problema. Se lo scarti esplicitamente potresti avere problemi dopo.

Con if let something = ...qualcosa di verrà scartato automaticamente in runtime e sarà possibile utilizzarlo in modo sicuro.

15

È sempre possibile farlo in un 'se', ma notare la differenza di sintassi a seconda della versione di swift.

Swift < 2.0:

if let img = img as? UIImage { 

Swift 2.0:

if let img = img as UIImage! { 

Nota la posizione del punto esclamativo

+0

Qualcuno potrebbe pubblicare le motivazioni per questo cambiamento? –