On the initial stage type casting seems very ok, but on the long run it always bites us back. Lack of knowledge on type casting can drive us to some serious bugs those are nightmare for any developer, senior or junior. Swift has some very cool techniques for handling type casting, on its arsenal. One of them is is
which is the type checker. Swift also provides us three as
variance for type Casting. Some five minutes reading can save some long anxious hours. So let us not delay on type casting deep dive.
In the simplest term, type casting is to convert one type of instance to another. Type casting has two of its kind:
- UpCast: Child to Parent conversion
- DownCast: Parent to Child conversion
Type Casting on Swift:
Today we gonna talk about type casting, one little road I will never want to cross. Once you start to make a habit of crossing that road times to times, you will find yourself on deep pitfall very soon.
But anyway here we are on that difficult road, to understand:
- the basic of how type cast works on Swift.
- how to check type
- At the end we will have a small talk on how to avoid type cast.
as variance
On swift we use as
as the type cast operator. as
has three different variance based on operation they perform.
- For upcasting
as
is used - In order to downcast
as?
is Used - For force downcast
as!
is used.
UpCast through as
as
is the Upcast operator on Swift.
//: Playground - noun: a place where people can play import UIKit //: Up Cast let label = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 100)) let labelView = label as UIView
On the above example we are upcasting the label
, which itself is a UILabel
, to its parent class UIView
. The labelView
is the UIView
instance. As we know UILabel
is inherited from UIView
on UIKit
framework. So this is a child to parent conversion.
DownCast through as?
as?
is used on DownCast by an implicit way or a safe way. On successful conversion it will return the child object; on failure case will return nil
. Basically an optional type cast.
//: Playground - noun: a place where people can play import UIKit //: Up Cast let label = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 100)) let labelView = label as UIView //: Down cast let childLabel = labelView as? UILabel // success childLabel?.text // prints "Hello" let childButton = labelView as? UIButton // fails childButton?.tintColor // prints nil
As we can see on the above example, label
is type casted to UIView
. Then we start to convert the labelView
again to UILabel
through as?
which successes and we can print the text
property of UILabel
. But when we try to convert the labelView
to UIButton
, which is also a subclass of UIView
, through as?
we are getting a nil
. as?
is down casting in a safer way.
Force downcast through as!
as!
is used for forced downcast. Will potentially crash the app when force downcast will return nil.
//: Playground - noun: a place where people can play import UIKit //: Up Cast let label = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 100)) label.text = "Hello" let labelView = label as UIView //: Down cast let childLabel = labelView as! UILabel childLabel.text let childButton = labelView as! UIButton childButton.tintColor //error: Execution was interrupted, reason: signal SIGABRT.
The most dangerous type casting operator.
On the above example when we are force down casting the labelView
to UILabel
then it seems very ok, but things will get messy when we try to convert the wrong type cast. Force down casting the labelView
to UIButton
causes a nil
instance. And finally accessing the property of a nil
instance causing the crash.
By the way we have already a blog post on optional, force unwrapping and etc. Fell free to have a look on that.
Type checking through is
is
is the type check operator.
//: Playground - noun: a place where people can play import UIKit let label = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 100)) let valid = label is UIView // true
On the above example we are just checking if the label
is a UIView
or not. Finally returns a Bool
value.
Best practice
This is a heavily opinion based practice, you are always welcome to discard or embrace the following practice. But I can confirm life will be much more easier if you start to follow the practice for type casting.
The very first practice is to avoid type cast. But unless you can’t
- It is almost ok to use
as
when it comes to upcasting. - For down casting the very first and last choice should be to use
as?
, as it will give us the chance to verify at-lest the return instance is nil or not. - Never use
as!
for down casting, even if you are pretty sure.
The root of this blog post is from my github q/a