Type Casting
Introduction
Welcome to lesson 5 of The Swift Fundamentals with Bob. You’ve learned a number of !
and ?
since Lesson 1. These are language features that distinguish Swift from the rest, and you’ve got to know all, when, where, how, and, most importantly, why.
In this lesson, you learn how to convert types in objects that are created with classes and structs. In fact, if you use Storyboard
in iOS, you must know type casting
.
Problem
- How do you distinguish between
as
,as?
,as!
? - Why does Xcode keep telling me what to do?
Type Casting in UIKit
You might have seen,
import UIKit
let label = UILabel() as UIView
You’ve converted UILabel
to UIView
. UILabel
is a subclass of UIView
. Let us attempt to replicate the phenomenon with custom classes.
Human Class
Design a class called, Human
that contains a single method.
class Human {
func introduce() {
print("Hi, I'm a human")
}
}
Human Subclass
Design Korean
and Japanese
which inherit from the Human
class.
class Korean: Human {
func singGangNamStyle() {
print("Oppa Gangnam Style")
}
}
class Japanese: Human {
func doNinja() {
print("Shhh.....")
}
}
Check if all good
let bob = Korean()
bob.introduce() // "Hi, I'm a human"
bob.singGangNamStyle() // "Oppa Gangnam Style"
Type Casting
You may convert Korean
to Human
or vice versa. There are two ways: upcasting and downcasting.
Upcasting
Upcasting occurs when an object converts its type to the base class. In the early above, you’ve upcasted UILabel
to UIView
using as
.
The word “up” aligns with the structure in the graph above.
let newBob = bob as Human // Korean -> Human
newBob.introduce()
newBob.singGangNamStyle() // Does not exist
Upcasting Example in Swift Struct
var name = "Bob" as Any
var number = 20 as Any
var anyArray = [name, number] // [Any]
I forgot to mention that
Int
andString
are struct types which lack base classes. However, structs may only “upcast” toAny
.
Downcasting
Downcasting is the opposite. You may downcast Any
to String
. However, it may fail since Any
could contain many types. Analogous to optionals
, there are two ways to downcast: Force downcasting or Implicit downcasting
Force Downcasting
It does not return an optional
type. but if it fails, it crashes.
// Force Downcasting
let newValue = anyArray[0] as! String
let newValue = anyArray[1] as! String // Error
Downcasting is only available only after upcasting.
Implicit Downcasting
It returns an optional type. If it fails, it returns nil
.
let newNewValue = anyArray[0] as? Int
print(newNewValue) // Optional(20)
Type Casting in Practice
Create Instances
let shion = Japanese()
let lee = Korean()
let kenji = Japanese()
let park = Korean()
Create Array Using Upcasting
let humans: [Human] = [shion as Human, lee as Human, kenji as Human, park as Human]
Automatic upcasting
let humans: [Human] = [shion, lee, kenji, park]
let humans = [shion, lee, kenji, park]
Loop
for human in humans {
if let korean = human as? Korean {
korean.singGangNamStyle()
}
if let japanese = human as? Japanese {
japanese.doNinja()
}
}
Usage in iOS Development
Typecasting can be used to group UI Components and add attributes as a whole.
import UIKit
let loginButton = UIButton()
let loginMessage = UILabel()
let loginView = UIView()
let UIComponents = [loginButton, loginMessage, loginView]
for component in UIComponents {
if let button = component as? UIButton {
// Change background color
// Add Title
// ...
}
if let label = component as? UILabel {}
if let view = component as? UIView {}
}
Important: Upcasting is not a recommended practice since there is a better way to go about: Protocol Oriented Programming. I mention drawbacks of using type casting through comparison in Chapter 3 and 5.
Another Example
To fetch a view controller from Storyboard
, downcast to identify the designated view controller.
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard instantiateViewController(withIdentifier: "VC")
// type of vc = UIViewController
let vc = storyboard instantiateViewController(withIdentifier: "VC") as! VC
// type of vc = VC
Source Code
Reference
AnyObject and Any in Swift (Stack Overflow)
Conclusion
I lied. I said type casting allowed to convert types in classes. However, you may also convert Int
and String
to Any
even though they are made up of structs, not classes.
Unnecessary type casting is not recommended among iOS developers because it causes a massive headache from casting back and forth. There is an alternative to go about. You will learn how to group objects together through Protocol Oriented Swift in Chapter 3. I know you are excited. Learn fast, but stay patient and consistent.
In the next lesson, you will learn how to design reusable code through generics
. You will come out dry, not wet, a.k.a we enjoy typing.