2014-07-01 16 views
7

sto guardando questo tutorial Swift e c'è questa linea:UIButton come UIButton in swift?

var button:UIButton = UIButton.buttonWithType(UIButtonType.System) as UIButton 

due domande:

  1. motivo è che la linea termina con as UIButton? La linea non è abbastanza chiara da consentire all'utente di creare un pulsante di tipo di sistema? Sembra essere ridondante.
  2. è necessario dichiarare il tipo UIButton sulla prima parte della linea? O in altre parole, non è sufficiente a dichiararla come

pulsante var = UIButton.buttonWithType (UIButtonType.System)

Voglio dire, se la parte dopo il segno di uguale è in fase di inizializzazione un pulsante del tipo di sistema non è abbastanza per il compilatore da dedurre button è un UIButton? Voglio dire, Apple ha detto che il compilatore è intelligente per inferire i tipi.

+0

Molte delle vostre domande ** ** * sono curiose domande fondamentali * che volevo anche chiedere (ma immagino sei 2 anni avanti a me nella curva di apprendimento). Normalmente non troverai risposte a tali domande se non ti viene chiesto su SO. – Honey

risposta

10

È necessario mantenere il downcast as UIButton. buttonWithType() restituisce AnyObject!, non UIButton, quindi il downcast è necessario. Oltre a ciò, non è necessario digitare la variabile in modo esplicito con : UIButton. Dal tipo di ritorno di buttonWithType() come downcast a UIButton, il tipo di variabile sarà dedotto per essere UIButton. Questo è ciò che si dovrebbe usare:

var button = UIButton.buttonWithType(UIButtonType.System) as UIButton 
+11

E il motivo di fondo sembra essere che il 'buttonWithType:' metodo Objective-C è dichiarato come restituito 'id' invece di 'instancetype'. –

+2

anser perfetto e commento perfetto da parte di Martin! Ora vedo, AnyObject! = id! Grazie!!! – SpaceDog

+0

A partire da Swift 1.2 è necessario usare 'as!' Per forzare un downcast –

2

Se si fa clic sul Cmd buttonWithType si vedrà che in rapida la sua dichiarata come

class func buttonWithType(buttonType: UIButtonType) -> AnyObject! 

Poiché il tipo restituisce è ANYOBJECT! devi digitare il cast per tornare a UIButton.

+3

è in realtà un optional e può essere nil – Sulthan

+0

Hai ragione, stavo pensando, modificherò il mio post, grazie per averlo preso. –

7

Alcuni retroscena supplementari in aggiunta alle risposte già date: Il metodo di Objective-C

+ (id)buttonWithType:(UIButtonType)buttonType 

rendimenti id. Questo era il modo "tradizionale" per dichiarare un "metodo di fabbrica" ​​in modo che fosse possibile utilizzare anche da sottoclassi. Non v'è alcun tipo di fusione necessaria

UIButton *button = [UIButton buttonWithType: UIButtonTypeSystem]; 

perché id possono essere convertiti in qualsiasi puntatore Objective-C.

Ora il tipo equivalente a id a Swift è AnyObject, e il metodo di cui sopra è mappato

class func buttonWithType(buttonType: UIButtonType) -> AnyObject! 

Swift è molto più severa e fa non convertire implicitamente tipi, quindi il valore di ritorno deve essere cast UIButton esplicitamente:

var button = UIButton.buttonWithType(UIButtonType.System) as UIButton 

La "moderna" appro per dichiarare i metodi di fabbrica è instancetype (vedere ad esempio http://nshipster.com/instancetype/ o Would it be beneficial to begin using instancetype instead of id?).Un semplice esempio è il NSString metodo

+ (instancetype)stringWithCString:(const char *)cString encoding:(NSStringEncoding)enc 

mappato in Swift a

class func stringWithCString(cString: CString, encoding enc: UInt) -> Self! 

Self è il tipo di oggetto su cui viene chiamato il metodo, in modo che il tipo di ritorno di

NSString.stringWithCString("foo", encoding: NSUTF8StringEncoding) 

è NSString! e il tipo di ritorno

NSMutableString.stringWithCString("bar", encoding: NSUTF8StringEncoding) 

è NSMutableString!. Non è necessario il cast di tipo in Swift. Nel seguente esempio, il compilatore Swift "sa" che è un strNSString:

var str = NSString.stringWithCString("foo", encoding: NSUTF8StringEncoding) 
var cs = str.UTF8String 

Le intestazioni quadro della Fondazione utilizzano già instancetype in molti luoghi, ma non ancora in tutto il mondo, ove possibile (come in buttonWithType:). Questo potrebbe essere migliorato nelle versioni future degli SDK .

+0

come sono i pulsanti i metodi * class *? O una ** istanza ** di un UIButton è uguale a uno dei metodi factory/metodi di classe di UIButton? – Honey

+0

@Honey: 'UIButton.buttonWithType (...)' è un metodo di classe (o meglio: era come metodo di classe in Swift 1). –

+0

Ricevo quella parte, ma non solo confuso come nel modo in cui qualcosa che si muta e cioè un'istanza deriva da un metodo di classe – Honey

0

Swift 2.1 è ora

var button = UIButton(type: .System) 

quindi nessun bisogno di downcast con .buttonWithType