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
letorvarkeyword. Variables initialized withletcannot be mutated.The following code will throw an error.
However, variables initialized with the
varkeyword can be mutated. Keep this difference in mind, and useletwherever you can; usingvaron 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
nilfor you.Now, let’s imagine that a user has filled out our sign-up form. If the user has filled out the
middleNameorwebsitefield, we’ve bound their input to the variables above. To display this information on their profile, we have to unwrap both themiddleNameandwebsitevariables. 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
middleNameis non-nil, its value is assigned tomN, and subsequently printed. Crucially, ifmiddleNameis nil, the code inside the if statement does not get executed.mNis a temporary variable, its scope is only inside theifstatement.guardYou can use a
guardstatement if you want the value of an optional to be available outside the scope of anifstatement, and you wish to terminate execution if the optional is nil.In this case,
mNis available outside the scope of theguardclause, but we are forbidden from continuing execution ifmiddleNameis nil.Functions
Functions can be defined in Swift in the manner indicated below:
In Swift,
inputis known as an argument label, anduserInputis 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
Diceenumeration (such asone,two, etc.) are called enumeration cases. You can use thecasekeyword to introduce new cases.Now that we have the basic behavior of a die, we can use a
switchstatement 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
structkeyword: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
UIViewis a blank view inside which other UI elements can be placed. You can useUIViewsto invisibly group together elements; or to create custom reusable UI elements.Initialization
UILabel
A
UILabelis a block of static text. The text displayed by aUILabelcannot be edited by the end-user, but can be dynamically changed in your app’s code.Initialization
numberOfLinesThe
numberOfLinespropery of aUILabelrefers 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 = 0UITextField
A
UITextFielddisplays 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:ViewControllertoUITextFieldDelegatetextField.delegate = selfinside theviewDidLoadof yourViewControllerExample
The code above will print
Text field did begin editingwhenever the user taps into the text field, and begins to type. The functiontextFieldDidBeginEditingis called by the system.UITextView
A
UITextViewdisplays an area of multi-line text. This element can be used to present large bodies of editable, attributed text.Initialization
Delegation
See
UITextFieldfor delegation steps, here are the available methods.UIImageView
A
UIImageViewdisplays an image within its bounds.Initialization
Remember to place your image within the
Assets.xcassetsfolder before attempting to display it!UIStackView
A
UIStackViewarranges 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
axisproperty of a stack view can be set to either.horizontalor.vertical, depending on the orientation you want the stack view to usedistributionproperty of a stack view can be set to several predefined options.fillEquallywill fill the stack view equally along its axis. Setting thedistributionto this option will cause the system to ignore any constraints you set along the stack view’s axis.fillwill cause the stack view to resize its subviews to fill the available space along its axis..fillProportionallywill cause the stack view to resize subviews proportionally based on their intrinsic size..equalSpacingcauses 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..equalCenteringattempts 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