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