Resources
This page will collect important notes and code snippets from lectures. Feel free to refer back to this
page for syntax/conceptual help.
Swift
Variable Initialization
Variables in Swift can be initialized with either the let
or
var
keyword. Variables initialized with let
cannot be mutated.
The following code will throw an error.
However, variables initialized with the var
keyword can be mutated. Keep this
difference in mind, and use let
wherever you can; using
var
on variables that are never mutated can have a detrimental effect on
performance.
Swift is a statically-typed language (like Java). This means
that variable types generally have to be explicitly declared. Swift also has a
type-inference feature, which explains why the code snippet above
does not require us to declare a type. When we provide a variable with a value, Swift can infer the type
of that value. However, when we decline to provide a value to a variable at initialization,
we must provide a type. For example:
Optionals
You can use optionals in situations when a value might be absent. An optional represents two
possibilities: either there is a value (and you can unwrap the optional to access it), or there isn’t a
value.
Say we’re creating a sign-up form for a social-media application. Some fields may not be mandatory for
the successful creation of an account (middle name, website, etc.). We can use optionals to model this
behavior in Swift:
var middleName: String?
var website: String?
If you define an optional variable without providing a value (like the situation above), then the
variable is automatically set to nil
for you.
Now, let’s imagine that a user has filled out our sign-up form. If the user has filled out the
middleName
or website
field, we’ve bound their input to
the variables above. To display this information on their profile, we have to
unwrap both the middleName
and
website
variables. There are a number of different ways to unwrap optional
variables.
Unwrapping Optionals
Force Unwrapping
You can access an optional’s underlying value by adding an exclamation point (!) to the end of the
optional’s name. If the optional does not have a value associated with it, your
application will crash.
print(middleName!)
print(website!)
Do not force-unwrap optionals.
Any oversight will cause your application to crash without warning.
Optional Binding (if-let)
You can use optional binding to check if an optional value, and if so, make that value available as a
temporary variable.
if let mN = middleName {
print(mN)
}
In the block of code above, if middleName
is non-nil, its value is assigned
to mN
, and subsequently printed. Crucially, if
middleName
is nil, the code inside the if statement does not
get executed.
mN
is a temporary variable, its scope is only inside the if
statement.
guard
You can use a guard
statement if you want the value of an optional to be
available outside the scope of an if
statement, and you
wish to terminate execution if the optional is nil.
guard let mN = middleName else {
return
}
print(mN)
In this case, mN
is available outside the scope of the
guard
clause, but we are forbidden from continuing execution if
middleName
is nil.
Functions
Functions can be defined in Swift in the manner indicated below:
func hello(input userInput: String) -> String {
return "Hello, \(userInput)"
}
In Swift, input
is known as an argument label, and
userInput
is known as a parameter label. The argument label is used when the
function is called (see the code below), and the parameter label is used inside the scope of the
function to refer to the parameter.
The function signature below is also valid:
func hello(input: String) -> String {
return "Hello, \(input)"
}
In this case, both the parameter label and argument label are input
.
Finally, if you want to be able to call your function without an argument label, you can place an
_
in the signature:
func hello(_ input: String) -> String {
return "Hello, \(input)"
}
hello("World!")
Enumerations
An enumeration allows you to group a set of related values, and work with those values in a type-safe
fashion. For example, let’s assume we want to model a dice roll, and perform an action based on the
result.
enum Dice {
case one
case two
case three
case four
case five
case six
}
The values defined in the Dice
enumeration (such as
one
, two
, etc.) are called enumeration cases. You can
use the case
keyword to introduce new cases.
Now that we have the basic behavior of a die, we can use a switch
statement
to match enumeration cases.
func diceRollToAction(roll: Dice) {
switch roll {
case .one:
print("one")
case .two:
print("two")
case .three:
print("three")
default:
print("four or more")
}
}
Structures
Swift structures are a flexible construct (similar to classes). Structures can be created in an
identical fashion to classes, with the struct
keyword:
However, structures are pass-by-reference in Swift while
classes are pass-by-value. This means that when structures
are passed to functions or assigned to variables, the entirety of their contents are copied over. In
contrast, classes only pass a reference to the functions or variables they are assigned to.
Basic UIKit Elements
UIView
AUIView
is a blank view inside which other UI elements can be placed. You can
use UIViews
to invisibly group together elements; or to create custom reusable
UI elements.
Initialization
lazy var customView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = .black
return view
}()
UILabel
A UILabel
is a block of static
text. The text displayed by a UILabel
cannot be edited by the end-user, but
can be dynamically changed in your app’s code.
Initialization
lazy var label: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.text = "Hello, world!"
label.textColor = .black
label.font = UIFont.boldSystemFont(ofSize: 12)
return label
}
numberOfLines
The numberOfLines
propery of a UILabel
refers to
the maximum number lines the system can use to fit the label’s text into its bounding rectangle. By
default, this property will be set to 1. If you want your label to span multiple lines (as allowed by
the space allocated), set this property to 0
label.numberOfLines = 0
UITextField
A UITextField
displays an area to gather single-line textual input from the
user. Do not use this element if you’re expecting multi-line text
input!
Initialization
lazy var textField: UITexField = {
let textField = UITextField()
textField.translatesAutoresizingMaskIntoConstraints = false
textField.attributedPlaceholder = NSAttributedString(string: "Placeholder")
return textField
}()
Delegation
To respond to changes in a UITextField
, take the following steps:
- Conform your
ViewController
to UITextFieldDelegate
- Set
textField.delegate = self
inside the
viewDidLoad
of your ViewController
- Implement the relevant method listed here
Example
class ViewController: UIViewController {
lazy var textField: UITextField = {
let textField = UITextField()
textField.translatesAutoresizingMaskIntoConstraints = false
textField.attributedPlaceholder = NSAttributedString(string: "Placeholder")
return textField
}()
override func viewDidLoad() {
textField.delegate = self
}
}
extension ViewController: UITextFieldDelegate {
func textFieldDidBeginEditing(UITextField) {
print("Text field did begin editing")
}
}
The code above will print Text field did begin editing
whenever the user taps
into the text field, and begins to type. The function textFieldDidBeginEditing
is called by the system.
UITextView
A UITextView
displays an area of multi-line text. This element can be used to
present large bodies of editable, attributed text.
Initialization
lazy var textView: UITextView = {
let textView = UITextView()
textView.translatesAutoresizingMaskIntoConstraints = false
textView.attributedText = NSAttributedString(string: "Hello,\n\nworld!")
return textView
}()
Delegation
See UITextField
for delegation steps, here are the available methods.
UIImageView
A UIImageView
displays an image within its bounds.
Initialization
Remember to place your image within the Assets.xcassets
folder before
attempting to display it!
lazy var imageView: UIImageView = {
let imageView = UIImageView()
imageView.translatesAutoresizingMaskIntoConstraints = false
let image = UIImage(named: "test-image")
imageView.image = image
return imageView
}()
UIStackView
A UIStackView
arranges a collection of views in either a column or a row.
Stack views can handle large amounts of UI complexity without constraints, and are often an excellent
tool for interface creation.
Important Properties and Methods
- The
axis
property of a stack view can be set to either
.horizontal
or .vertical
, depending on the
orientation you want the stack view to use
- The
distribution
property of a stack view can be set to several
predefined options
.fillEqually
will fill the stack view equally along its axis. Setting the
distribution
to this option will cause the system to ignore any
constraints you set along the stack view’s axis
.fill
will cause the stack view to resize its subviews to fill the available
space along its axis.
.fillProportionally
will cause the stack view to resize subviews
proportionally based on their intrinsic size.
.equalSpacing
causes the stack view to position its subviews such that they
fill the available space along the stack view’s axis. When the subviews do not fill the
stack view, it pads the spacing between the views evenly.
.equalCentering
attempts to position the subviews such that they have an
equal center-to-center spacing along the stack view’s axis.
- Use the
.addArrangedSubview(_ view: UIView)
method to add subviews to a
stack view
Initialization
lazy var stackView: UIStackView = {
let stack = UIStackView()
stack.axis = .horizontal
stack.distribution = .fillEqually
stack.spacing = 5
stack.addArrangedSubview(label)
stack.addArrangedSubview(textField)
}()
Resources
This page will collect important notes and code snippets from lectures. Feel free to refer back to this page for syntax/conceptual help.
Swift
Variable Initialization
Variables in Swift can be initialized with either the
let
orvar
keyword. Variables initialized withlet
cannot be mutated.The following code will throw an error.
However, variables initialized with the
var
keyword can be mutated. Keep this difference in mind, and uselet
wherever you can; usingvar
on variables that are never mutated can have a detrimental effect on performance.Swift is a statically-typed language (like Java). This means that variable types generally have to be explicitly declared. Swift also has a type-inference feature, which explains why the code snippet above does not require us to declare a type. When we provide a variable with a value, Swift can infer the type of that value. However, when we decline to provide a value to a variable at initialization, we must provide a type. For example:
Optionals
You can use optionals in situations when a value might be absent. An optional represents two possibilities: either there is a value (and you can unwrap the optional to access it), or there isn’t a value.
Say we’re creating a sign-up form for a social-media application. Some fields may not be mandatory for the successful creation of an account (middle name, website, etc.). We can use optionals to model this behavior in Swift:
If you define an optional variable without providing a value (like the situation above), then the variable is automatically set to
nil
for you.Now, let’s imagine that a user has filled out our sign-up form. If the user has filled out the
middleName
orwebsite
field, we’ve bound their input to the variables above. To display this information on their profile, we have to unwrap both themiddleName
andwebsite
variables. There are a number of different ways to unwrap optional variables.Unwrapping Optionals
Force Unwrapping
You can access an optional’s underlying value by adding an exclamation point (!) to the end of the optional’s name. If the optional does not have a value associated with it, your application will crash.
Do not force-unwrap optionals.
Any oversight will cause your application to crash without warning.
Optional Binding (if-let)
You can use optional binding to check if an optional value, and if so, make that value available as a temporary variable.
In the block of code above, if
middleName
is non-nil, its value is assigned tomN
, and subsequently printed. Crucially, ifmiddleName
is nil, the code inside the if statement does not get executed.mN
is a temporary variable, its scope is only inside theif
statement.guard
You can use a
guard
statement if you want the value of an optional to be available outside the scope of anif
statement, and you wish to terminate execution if the optional is nil.In this case,
mN
is available outside the scope of theguard
clause, but we are forbidden from continuing execution ifmiddleName
is nil.Functions
Functions can be defined in Swift in the manner indicated below:
In Swift,
input
is known as an argument label, anduserInput
is known as a parameter label. The argument label is used when the function is called (see the code below), and the parameter label is used inside the scope of the function to refer to the parameter.The function signature below is also valid:
In this case, both the parameter label and argument label are
input
.Finally, if you want to be able to call your function without an argument label, you can place an
_
in the signature:Enumerations
An enumeration allows you to group a set of related values, and work with those values in a type-safe fashion. For example, let’s assume we want to model a dice roll, and perform an action based on the result.
The values defined in the
Dice
enumeration (such asone
,two
, etc.) are called enumeration cases. You can use thecase
keyword to introduce new cases.Now that we have the basic behavior of a die, we can use a
switch
statement to match enumeration cases.Structures
Swift structures are a flexible construct (similar to classes). Structures can be created in an identical fashion to classes, with the
struct
keyword:However, structures are pass-by-reference in Swift while classes are pass-by-value. This means that when structures are passed to functions or assigned to variables, the entirety of their contents are copied over. In contrast, classes only pass a reference to the functions or variables they are assigned to.
Basic UIKit Elements
UIView
A
UIView
is a blank view inside which other UI elements can be placed. You can useUIViews
to invisibly group together elements; or to create custom reusable UI elements.Initialization
UILabel
A
UILabel
is a block of static text. The text displayed by aUILabel
cannot be edited by the end-user, but can be dynamically changed in your app’s code.Initialization
numberOfLines
The
numberOfLines
propery of aUILabel
refers to the maximum number lines the system can use to fit the label’s text into its bounding rectangle. By default, this property will be set to 1. If you want your label to span multiple lines (as allowed by the space allocated), set this property to 0label.numberOfLines = 0
UITextField
A
UITextField
displays an area to gather single-line textual input from the user. Do not use this element if you’re expecting multi-line text input!Initialization
Delegation
To respond to changes in a
UITextField
, take the following steps:ViewController
toUITextFieldDelegate
textField.delegate = self
inside theviewDidLoad
of yourViewController
Example
The code above will print
Text field did begin editing
whenever the user taps into the text field, and begins to type. The functiontextFieldDidBeginEditing
is called by the system.UITextView
A
UITextView
displays an area of multi-line text. This element can be used to present large bodies of editable, attributed text.Initialization
Delegation
See
UITextField
for delegation steps, here are the available methods.UIImageView
A
UIImageView
displays an image within its bounds.Initialization
Remember to place your image within the
Assets.xcassets
folder before attempting to display it!UIStackView
A
UIStackView
arranges a collection of views in either a column or a row. Stack views can handle large amounts of UI complexity without constraints, and are often an excellent tool for interface creation.Important Properties and Methods
axis
property of a stack view can be set to either.horizontal
or.vertical
, depending on the orientation you want the stack view to usedistribution
property of a stack view can be set to several predefined options.fillEqually
will fill the stack view equally along its axis. Setting thedistribution
to this option will cause the system to ignore any constraints you set along the stack view’s axis.fill
will cause the stack view to resize its subviews to fill the available space along its axis..fillProportionally
will cause the stack view to resize subviews proportionally based on their intrinsic size..equalSpacing
causes the stack view to position its subviews such that they fill the available space along the stack view’s axis. When the subviews do not fill the stack view, it pads the spacing between the views evenly..equalCentering
attempts to position the subviews such that they have an equal center-to-center spacing along the stack view’s axis..addArrangedSubview(_ view: UIView)
method to add subviews to a stack viewInitialization