IOS Mobile System - Swift basics
Swift Background
- Apple first released Swift in 2014 to replace Objective-C in iOS app and MAC app development.
- According to Apple, Swift is “friendly” to new programmers.
You can use Playground
in Xcode for learning purpose, which is only available in MacOS.
Swift Syntax
- Variables are always initialized before use.
- Array indices are checked for out-of-bounds errors.
- Integers are checked for overflow.
- Optionals ensure that
nil
values are handled explicitly - Memory is managed automatically.
1 | import UIKit |
Basic Syntax
Semicolon
- Swift does not require a semicolon after each statement
- Require semicolon only for multiple statements in the same line
Comments
- Comments are ignored by the compiler
- Single-line
//
, Multi-line/* */
, same as most of the languages
Identifiers
An identifier is to identify a variable, function, or user-defined item.
- case sensitive
- starts with an alphabet A to Z or a to z or an underscore _ followed by letters, underscore and digits
- does not allow special characters within identifiers
Keywords
Data Types
- Int or UInt
- Float
- Double
- Bool
- String
- Character
- Optional
- Tuples
Variable declaration
1 | var num:Int = 0 |
:Int
is to state the type of variable (not necessary)var
is to define a variable
1 | var <variable name>:<data type> = <value> |
Constants
Constants are like variables except their values cannot be modified after declaration
1 | let fixed_num = 0 |
let
is the keyword to make variable cannot be modified after declaration
Operators
- Same as C++, nothing special
- Operators can only work with operands of the same type
- You need to convert values before applying to operands
To Join Two Strings together:
1 | let age = 20 |
another way:
String interpolation is done by typing the name of a constant or variable between “(” and “)” in a string.
1 | let age = 20 |
Whitespaces
Yeah, this is dumb
Controls
If Else statement
- No need to use ( ) for the condition
1 | var str:String? = "Hello!" |
Switch statement
- No need to use
break
after each case - Every switch statement consists of multiple possible cases, each of which begins with the case keyword
- Every switch statement must be exhaustive
- Consider every element in the case
Loops
For-in loop
1 | for _ in 0...5 { |
- The
_
is used to define that the parameter is not named
While loop
1 | var sum = 1 |
Repeat-while loop
1 | var sum = 1 |
The Optional Type
Every variable needs to be initialized, optional variables are automatically initialized as nil (not set).
Swift allow you to declare a variable without a value only when the type is optional.
- Denote optional with
?
- the value of the variable will be
nil
if no value given - you need to unwrap the associated value with
!
- the value of the variable will be
1 | var str:String? |
1 | var str:String? = "Something Here" |
Automatic Unwrapping
- or you can Declare an Optional with
!
instead of?
for automatic unwrapping
1 | var str:String! |
1 | var str:String! = "Something Here" |
- Note it crashes your app if you try to unwrap an optional in the not set state (the value is
nil
)
Conditional Binding
Optional Binding uses if statement to find out whether an optional contains a value or not
1 | var str:String? = "Hello!" |
1 | var str:String? |
With this, you can see whether an optional contains a value or not.
Optional operator ??
There is also an Optional “defaulting” operator ??
The aim to provide a default value if the Optional is nil
1 | let s: String? //might be nil |
Array
An array stores values of the same type in an ordered list
The same value can appear in an array multiple times at different positions
1 | var arr1 = Array<String>() |
Common Array Accessing Methods
.append()
.insert()
.count
.first
.last
.isEmpty
Looping through an array
1 | var animals = ["Giraffe", "Cow", "Doggie", "Bird"] |
One Tricky Example
1 | var animals = ["Giraffe", "Cow", "Doggle", "Bird"] |
Tuples
- a group of values
- The tuple elements can be named when the tuple is declared
1 | let x: (w: String, i:Int, v: Double) = ("hello", 5, 0.85) |
Dictionary
- used to store unordered lists of values of the same type
- use unique identifier known as a key to store a value which later can be referenced and looked up through the same key
Creating Dictionary
1 | var UniRankings = Dictionary<String, Int>() |
Assign key and values in Dictionary
1 | UniRankings = ["HKU":1, "PolyU":99] |
Set
A Set is an unordered collection of unique elements
1 | //Creating a set |
Common Set Accessing Methods
.count
.isEmpty
.insert()
.contains()
.remove()
.union()
.intersection()
.subtracting()
.symmetricDifference()
.isSubset(of: )
.isSuperset(of: )
.isDisjoint(with: )
Function
A function is a block of code with a given name. It can be executed by calling its name.
Function Declaration
1 | func functionName(parameter(s)) -> returnParameter(s) { |
All parameters to all functions have an internal name and an external name
- The internal name is the name of the local variable you use inside the method
- The external name is what callers use when they call the method
Example:
1 | func foo(external_a internal_a: Int, external_b internal_b: Double) -> (Double){ |
You can put _ if you don’t want callers to use an external name for a given parameter.
1 | func foo(_ internal_a: Int, _ internal_b: Double) -> (Double){ |
Class
A class is a group of variables with functions that can manipulate the variables
The name of the class become a type
1 | class Point { |
init
function is the constructor
Class Inheritance
A class may inherits from another class
- The new class (derived class) have the same properties (data and functions) of the parent class
1 | //Use : and followed by a class to inherit from that class |
Function Overriding
- Derived class can have its own version of function inherited from the parent class
1 | override func printX(){ |
- Keyword
super
is to use the parent class’s function and provide additional functionality within the overriding function
Enum
enum in general is a discrete set of values
- enums are like class and can have their own methods, but cannot have inheritance, and enum is “pass by value”
1 | enum Operation { |
An Optional is actually just an enum.
1 | enum Optional<T>{ //the <T> is a generic like as in Array<T> |
Closure
There is a Swift feature called Closure. Closures are self-contained blocks of functionality that can be passed around and used in your code. Closures in Swift are similar to blocks in C and Objective-C and to lambdas in other programming languages.
Closures can capture and store references to any constants and variables from the context in which they are defined. This is known as closing over those constants and variables. Swift handles all of the memory management of capturing for you. In other words, functions can be embedded in line in Swift.
A closure, like a function, contains a sequence of instructions and can take parameters and return values.
- Closures don’t have names
- The sequence of instructions in a closure is surrounded by curly braces
{ }
- Use
$0
,$1
,$2
, etc. to represent the parameters
Closure with Type Inference
Example:
1 | enum Operation { |
Closure with Arrays
filter(includeElement: (T) -> Bool) -> [T]
- This one creates a new array with any “undesirables” filtered out
- The function passed as the argument returns false if an element is undesirable
1 | let bigNumbers = [2,47,118,5,9].filter({ $0 > 20 }) //bigNumbers = [47, 118] |
Image example from https://useyourloaf.com/blog/swift-guide-to-map-filter-reduce/
map(transform: (T)->U) -> [U]
- Create a new array by transforming each element to something different
- The thing it is transformed to can be of a different type than what is in the Array
1 | let multiplied: [Int] = [1,2,3].map { $0*3 } // [3,6,9] |
Image example from https://useyourloaf.com/blog/swift-guide-to-map-filter-reduce/
reduce(initial: U, combine: (U, T) -> U ->) U
- Reduce an entire array to a single value
1 | let sum: Int = [1,2,3].reduce(0) { $0 + $1 } // adds up the numbers in the Array = 6 |
Image example from https://useyourloaf.com/blog/swift-guide-to-map-filter-reduce/
Lazy Initialization
Lazy initialization (also sometimes called lazy instantiation, or lazy loading) is a technique for delaying the creation of an object or some other expensive process until it’s needed. When programming for iOS, this is helpful to make sure you utilize only the memory you need when you need it.
- Swift requires that “you must initialize all of your properties”
- A lazy property does not get initialized until someone accesses it
- You can allocate an object, execute a closure, or call a method if you want
- Things initialized this way can’t be constants (i.e.,
var
ok,let
not ok) - This can be used to get around some initialization dependency issues
Example:
1 | lazy var brain = CalculatorBrain() |
Property Observers
You can observe changes to any property with willSet
and didSet
.
- Very common thing to do with
didSet
/willSet
in a Controller to update the UI - Will also be invoked if you mutate/change a struct (or value type)
- (e.g., add something to a dictionary)
Example
1 | var myData: Int = 0{ |
Computed Properties of a Variable
Automatic detection of getters and setters
- Using keyword
get
andset
Example:
1 | var displayValue: Double{ |
Struct
- they are like class and similar to enum
- But It is pass by value instead of pass by reference (class)
- Pass by value means that when you pass it, it makes a copy of it
- For pass by reference, it is done through pointer
Example:
1 | struct PendingBinaryOperationInfo{ |
Fun Facts
You can code with emoji.
Data Structures in Swift
These are the 3 fundamental building blocks of data structures in Swift:
- Classes
- Structs
- Enums
Similarities
Classes, Structs and Enums :
- have the similar Declaration syntax
- can have Properties and Functions
Differences
- Initializers (not for enum)
- Inheritance (class only)
- Value type (struct, enum) vs Reference type (class)
Value vs Reference
Pass by Value (struct and enum)
- Copied when passed as an argument to a function
- Copied when assigned to a different variable
- Immutable if assigned to a variable with
let
- function parameters are constants
You must note any
func
that can mutate a struct/enum with the keyword mutating (e.g.,mutating func
…)
Pass by Reference (class)
- Stored in the heap and reference counted (automatically)
- Constant pointers to a class (
let
) still can mutate by calling methods and changing properties (what the pointer pointed to could be changed) - When a pointer is passed as an argument, it does not make a copy (just passing a pointer to same instance)
Choosing which to use?
Usually you will choose class over struct. struct tends to be more for fundamental types (e.g., String, Double, Int, Array, Dictionary)
Use of enum is situational (any time you have a type of data with discrete values)