I am watching this Swift tutorial and there is this line:
var button:UIButton = UIButton.buttonWithType(UIButtonType.System) as UIButton
two questions:
as UIButton
? Isn't the line clear enough that the user wants to create a button of system type? It appears to be redundant.var button = UIButton.buttonWithType(UIButtonType.System)
I mean, if the part after the equal sign is initializing a button of system type is not that enough for the compiler to infer button
is a UIButton
? I mean, Apple said the compiler is smart to infer types.
You need to keep the as UIButton
downcast. buttonWithType()
return AnyObject!
, not UIButton
, so the downcast is necessary. Other than that, you don't need to explicitly type the variable with : UIButton
. Since the return type of buttonWithType()
as downcast to UIButton, the variables type will be inferred to be UIButton
. This is what you should use:
var button = UIButton.buttonWithType(UIButtonType.System) as UIButton
Some additional background in addition to the already given answers: The Objective-C method
+ (id)buttonWithType:(UIButtonType)buttonType
returns id
. This was the "traditional" way to declare a "factory method" in a way that it
can be used from subclasses as well. There is no type cast necessary in
UIButton *button = [UIButton buttonWithType: UIButtonTypeSystem];
because id
can be converted to any Objective-C pointer.
Now the equivalent type to id
in Swift is AnyObject
, and the above method is mapped to
class func buttonWithType(buttonType: UIButtonType) -> AnyObject!
Swift is much more strict and does not implicitly convert types, therefore the return value has to be cast to UIButton
explicitly:
var button = UIButton.buttonWithType(UIButtonType.System) as UIButton
The "modern" approach to declare factory methods is instancetype
(see for example http://nshipster.com/instancetype/ or Would it be beneficial to begin using instancetype instead of id?). A simple example is
the NSString
method
+ (instancetype)stringWithCString:(const char *)cString encoding:(NSStringEncoding)enc
which is mapped in Swift to
class func stringWithCString(cString: CString, encoding enc: UInt) -> Self!
Self
is the type of the object on which the method is called, so that
the return type of
NSString.stringWithCString("foo", encoding: NSUTF8StringEncoding)
is NSString!
and the return type of
NSMutableString.stringWithCString("bar", encoding: NSUTF8StringEncoding)
is NSMutableString!
. No type cast is necessary in Swift. In the following
example, the Swift compiler "knows" that str
is an NSString
:
var str = NSString.stringWithCString("foo", encoding: NSUTF8StringEncoding)
var cs = str.UTF8String
The Foundation framework headers already use instancetype
in many places, but not
yet everywhere where possible (as in buttonWithType:
). This may be improved in
future releases of the SDKs.
If you cmd click the buttonWithType you will see that in swift its declared as
class func buttonWithType(buttonType: UIButtonType) -> AnyObject!
Since the type it returns is AnyObject! you need to type cast it back to UIButton.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With