Swift is ready for your next iOS and OSX project – or for addition into your current app – because Swift code works side-by-side with Objective-C.

Printing text:

print(” I am cool”)

print(“the value is \(myVariable)”)

print(myVariable)

; semicolon optional and required in one line

Comments:

// it’s a comment

/*another comment

in multiple lines*/

Variables:

declaring variable:

var a = 42

changing variable

var a = 88

var a = 44; var b =66

np:

var test = “Hi”; test = “I love Swift!”

Constants:

let one = 1

let x = 0.0, y = 0.0, z = 0.0

The value of a constant can never be changed. Trying to assign a new value to a constant results in an error.

However, constant and variable names must have no blank spaces, mathematical symbols, arrows, private-use (or invalid) Unicode code points, or line and box-drawing characters. Numbers can appear anywhere within a name, except for at the beginning.

Type annotations ensure that your code is clear about the value stored within your constant or variable. Swift’s basic types include:
Int: Integers
Double and Float: Floating-Point Values
Bool: Boolean Values
String: Textual Data.

Add a type annotation by placing a colon (:) after the constant or variable name, then add a space, and then add the type name, as follows:

var welcome MSG: String

welcomeMSG = “Hi”

var red, green, blue: Double

In practice, you will rarely need to add type annotations. Providing an initial value for a constant or a variable at the point at which it is defined, will almost always be sufficient for Swift to infer which type should be used:

Swift always chooses Double (as opposed to Float) when inferring the type for floating-point numbers.
Swift is a type safe language, meaning that it supports clarity when specifying value types for code. When part of your code expects a String, you can’t pass it an Int by mistake.

An operator is a special symbol or phrase used to check, change, or combine values.

Operators are unary, binary, or ternary:
Unary Operator: Has a single target (-a). A unary prefix operator is placed before the target (!b).
Binary Operator: Has two targets (4 + 5) and is infixed, appearing between the two targets.
Ternary Operator: Has three targets. Like C, Swift has one ternary operator, the ternary conditional operator (a ? b : c).

The values targeted by operators are called operands. In the expression 1 + 2, the + symbol is a binary operator; its two operands are the values 1 and 2.

Assignment Operator

The assignment operator (a = b) initializes or updates the value of a with the value of b

let b = 7

let a = 42

a=b \\ now a is 7

Arithmetic Operators

+ – * /

The addition operator is also supported for String concatenation:

“hello, ” + “world” \\returns “hello, world”

The remainder operator (a % b) calculates the number of multiples of b that fit within a, and returns the value that is left over, or the remainder

5 % 2 \\return 1

In other languages, the remainder operator (%) is called a modulo operator. In Swift, however, its behavior for negative numbers means that it is, strictly speaking, a remainder, rather than a modulo operation.

Compound Operators:

The expression a += 2 is shorthand for a = a + 2. The addition and the assignment are combined into one operator that performs both tasks at the same time.
Similarly, there are shorthand operators for other arithmetic operations.

Comparison Operators

Swift supports all of the standard comparison operators in C:
Equal to (a == b)
Not equal to (a != b)
Greater than (a > b)
Less than (a < b)
Greater than or equal to (a >= b)
Less than or equal to (a <= b)

Each of the comparison operators returns a Bool value indicating whether or not the statement is true:

Swift also provides two identity operators, === and !==, which test whether two object references both refer to the same object instance.

The ternary conditional operator is a special operator with three parts, taking the form (question ? answer1 : answer2).

This operator acts as a shortcut in evaluating one of two expressions, based on whether the question is true or false. For a true question, it evaluates answer1 and returns its value; otherwise, it evaluates answer2 and returns its value.

gender == 0 ? print (“male”) : print (“female”)

Range Operators

Swift offers two range operators, which are shortcuts for expressing a range of values.

The closed rangeoperator (a…b) defines a range running from a to b, and includes the values a and b. The value of a must not be greater than that of b

The half-open rangeoperator (a..<b) defines a range that runs from a to b, but does not include b. It is said to be half-open because it contains its first value, but not its final value. As with the closed range operator, the value of a must not be greater than that of b

Logical operators modify or combine the Boolean logic values true and false. Swift supports the three standard logical operators found in C-based languages:

Logical NOT operator (!a): Inverts a Boolean value so that true becomes false and false becomes true.

Logical AND operator (a && b): Creates logical expressions in which both values must be true for the overall expression to be true.

Logical OR operator (a || b): An infixed operator made from two adjacent pipe characters. It creates logical expressions in which only one of the two values has to be true for the overall expression to be true.Multiple logical operators can be combined to create longer compound expressions.
The logical operators && and || are left-associative, meaning that compound expressions with multiple logical operators evaluate the leftmost subexpression before the right.

Optionals are used in situations in which a value may be absent.
An optional says:
-There is a value, and it equals x
or
-There isn’t a value at all

An optional Int is written as Int?, not Int. The question mark indicates that the value contained within is optional, meaning that it might contain some Int value, or it might contain no value at all.It can’t contain anything else, such as a Bool value or a String value. It’s either an Int, or it’s nothing at all.

var test = String?

You set an optional variable to a valueless state by assigning it the special value nil:

var mycCode: Int? = 44

myCode = nil

\\ my code is NIL

var someMsg: String?

\\automatically nil

nil cannot be used with non-optional constants and variables. If your code contains a constant or variable that needs to work with the absence of a value under certain conditions, always declare it as an optional value of the appropriate type.

A conditional statement executes certain code under certain conditions. For example, you can run a particular code when an error occurs, or display a message when a value exceeds a certain baseline. To set conditions, use if or switch statements.

var temp = 25

if temp <=30 {print (“its cold”)}

if a >b {print(a)} else {print(b)}

Use the switch statement as an alternative to the if statement for multiple potential states. The switch statement compares a value with several possible matching patterns, executing a block of code using the first matching pattern.

Each case begins with the keyword case

switch distance {

case 0: print (“not a valid distance”)

case 1,2,3,4,5: print (“near”)

default: print (“too far”)}

A single case can contain multiple values, as in our example above. It can also contain ranges, using the range operators.

Every switch statement must be exhaustive, i.e. take every possible value into consideration. In cases in which it is not appropriate to provide a switch case for every possible value, you can define a default catch-all case to cover any values that are not explicitly addressed. Indicate the catch-all case by using the keyword default. This always appears last.Swift doesn’t require break statements, but will still accept one to match and ignore a particular case, or to break out of a matched case before that case has completed its execution.

The where clause checks for additional conditions.

The three switch cases declare placeholder constants x and y, which temporarily take on the two values from myPoint, creating a dynamic filter as part of a where clause. The switch case matches the current value of point only if the where clause’s condition evaluates to true for that value.The final case matches all possible remaining values; a default case is not necessary to have an exhaustive switch statement.

let myPoint = (1, -1)switch myPoint {   case let (x, y) where x == y:      print(“(\(x), \(y)) is on the line x == y”)   case let (x, y) where x == -y:     print(“(\(x), \(y)) is on the line x == -y”)   case let (x, y):     print(“(\(x), \(y)) is just some arbitrary point”)}

while loop performs a set of statements until a condition becomes false. These kinds of loops are best used when the number of iterations is not known before the first iteration begins.
while evaluates its condition at the start of each pass through the loop.
The while loop is demonstrated in the example below:

var a = 1var b = 5while a < b {   print(a)   a+=1}

The code will execute until the a+=1 statement renders a < b as false.

The repeat-while loop is the alternate while loop. It first makes a single pass through the loop block, then considers the loop’s condition, and repeats the loop until the condition shows as false. Swift’s repeat-while loop is similar to a do-while loop in other languages.

var x = 10 repeat {   print(x)   x -= 1} while x > 0

Use the for-in loop to iterate over a sequence, such as ranges of numbers, items in an array, or characters in a string.
The following example prints the first few entries in the five-times-table:

for index in 1…5 {   print(“\(index) times 5 is \(index * 5)”)}

\\1 times 5 is 5 2 times 5 is 10 3 times 5 is 15 4 times 5 is 20 5 times 5 is 25

Control transfer statements alter the code execution by transferring control from one piece of code to another. Swift’s four control transfer statements are continuebreakfallthrough, and return 

The continue statement stops the loop, then restarts it at the beginning of its next cycle.
The example below shows how to use the continue statement to skip over even numbers.

for num in 1…10 {   if num%2 == 0 {      continue   }   print(num)}

A for loop with a condition and an incrementer still evaluates the incrementer after the continue statement is initiated. The loop itself continues to work as usual; only the code within the loop’s body is skipped.

Break

Use the break statement to immediately end the execution of an entire control flow statement. Also, the break statement is used within a switch statement or a loop statement to terminate its execution sooner than would otherwise be the case.

Break in a Loop Statement

When a break statement is used within a loop statement, the loop’s execution immediately stops. Control transfers to the first line of code following the loop’s closing brace (}). The current iteration’s remaining code is skipped, and no further iterations of the loop are initiated.
For example, you can have a loop that breaks out when the value of a becomes less than that of b:

var b = 7 var a = 10 while a > 0 {   if(a < b) {     break   }   print(a)   a-=1}

Break in a Switch Statement

break causes a switch statement to end its execution immediately, and transfers control to the first line of code that follows the switch statement’s closing brace (}).

var a = 5 var letter = “X” switch a {   case 1:     letter = “A”   case 2:      letter = “B”   default:      break} print(letter)

This example breaks out of the switch statement as soon as the default case is matched. Always use a break statement to ignore a switch case.

In Swift, switch statements do not fall through the bottom of each case into the next. Instead, the entire switch statement completes its execution when the first matching case is completed.
By contrast, C requires insertion of an explicit break statement at the end of every switch case to prevent fallthrough. By eliminating default fallthrough, Swift allows for more concise and predictable switch statements in comparison with C, and thus avoids inadvertently executing multiple switch cases.

In cases that require C-style fallthrough behavior, use the fallthrough keyword on a case-by-case basis. The example below uses fallthrough to create a number’s textual description.

let myInt = 5var desc = “The number \(myInt) is”switch myInt {   case 2, 3, 5, 7, 11, 13, 17, 19:      desc += ” a prime number, and also”      fallthrough   default:     desc += ” an integer.”}print(desc)

This prints “The number 5 is a prime number, and also an integer.”

If myInt‘s value is one of the prime numbers in the list, text noting that the number is prime is appended to the end of the description. The fallthrough keyword then causes it to “fall into” the default case.The fallthrough keyword does not check case conditions in the switch case into which execution falls. As with C’s standard switch statement behavior, the fallthrough keyword moves code execution directly to the statements inside the next (or default) case block.

string is an ordered collection of characters, such as “Hello, World” or “SoloLearn”. Swift strings are represented by the String type, which in turn represents a collection of Character type values.

Predefined String values can be included within code as string literals, or fixed sequences of textual characters within double quotation marks (“”). Use a string literal as an initial value for a constant or variable.

let someString = “Some string literal value” print(someString)

Because it is initialized with a string literal value, Swift infers a type of String for the someString constant.

An empty String value can be created as the starting point for a longer string. To do this, either assign an empty string literal to a variable or initialize a new String instance using initializer syntax:

var emptyString = “” // empty string literalvar anotherEmptyString = String() // initializer syntaxprint(“Value of emptyString is \(emptyString)”)

Both strings are empty and equivalent to each other.Determine whether a String value is empty by checking its Boolean isEmpty property:

var emptyString = “”if emptyString.isEmpty {   print(“String is empty”)}

Concatenation

String values can be added together (or concatenated) with the addition operator (+) to create a new String value:

let string1 = “Hello”

let string2 = ” World”

var welcome = string1 + string2print(welcome)

The addition assignment operator (+=) appends a String value to an existing String variable.

var msg = “Hi”

msg += ” David”

print(msg)

String interpolation includes the values of a mix of constants, variables, literals, and expressions inside a string literal to form a new String value. Prefix each item with a backslash, place the item in parentheses, and insert it into the string literal.

let mult = 4

let message = “\(mult) times 1.5 is \(Double(mult) * 1.5)”

print(message)

In the above example, the multiplier value is inserted into the string literal as \(mult). When the string interpolation is evaluated prior to creating the actual string, this placeholder is replaced with the actual value of mult.

Later in the string, the value of mult appears within a larger expression within the string literal: \(Double(mult) * 1.5). The expression calculates the value of Double(mult) * 1.5 and then inserts the result (6) into the string. The expressions appearing inside of parentheses within an interpolated string cannot contain an unescaped double quote (“), backslash (\), carriage return, or line feed.

To retrieve a count of the Character values in a string, use the count property of the string:

let someString = “I am learning with SoloLearn”

print(“someString has \(someString.count) characters”)

When using the characters property, the character count does not always match the length property of an NSString containing the same characters. The length of an NSString is based on the number of 16-bit code units within the string’s UTF-16 representation, as opposed to the number of Unicode extended grapheme clusters within the string.

Swift offers three options for comparing textual values: string and character equality, prefix equality, and suffix equality.
Use the “equal to” operator (==) and the “not equal to” operator (!=) to determine string and character equality.

let s1 = “We are alike”

let s2 = “We are alike”

if s1 == s2 {   print(“These two strings are equal”)}

Use the string’s hasPrefix and hasSuffix methods to determine whether a string has a particular string prefix or suffix. Both methods take a single argument of type String and return a Boolean value.

An array is an ordered list of values of the same type, in which the same value can appear multiple times at different positions. In Swift, the array type can be written in full as Array<T>, in which T represents which value type the array is allowed to store. The array type can also be expressed in shorthand form, as [T].
Although the two forms are identical in function, the shorthand will appear throughout this tutorial in reference to an array type.

var someInts = [Int]()

print(“Empty array equals \(someInts)”)

Array with a Default Value

Swift’s Array type also provides an initializer for creating an array of a certain size with all of its values set to the same default value. You pass this initializer the number of items to be added to the new array (called count) and a default value of the appropriate type (called repeating):

var fourDoubles = [Double](repeating: 0.0, count: 4)

Array Literal

Using an array literal is another way to initialize an array. The array literal is shorthand for one or more values written as an array collection, and is written as a list of values, separated by commas, with square brackets at beginning and end.

[value 1, value 2, value 3]

The example below creates an array called shoppingList, for storing String values:

var shoppingList:[String] = [“Bread”, “Milk”]

This particular array can store only String values, as it has String specified as its value type.

Because of Swift’s type inference, you don’t have to write out the array type. Be sure to initialize with an array literal containing values of that same type. The initialization of shoppingList could have been written in a shorter form:

var shoppingList = [“Bread”, “Milk”]

All values in the array literal are of the same type, enabling Swift to infer that [String] is the correct type for the shoppingList variable.

Combining two existing arrays with compatible types using the addition operator (+) allows you to create a new array. Swift infers the new array’s type based on the type of the two combined arrays.

Access and modify an array through its methods and properties or by using subscript syntax.

An array’s read-only count property provides the number of items in an array.

print(“The shopping list contains \(shoppingList.count) items.”)
// prints “The shopping list contains 2 items.”

Use the Boolean isEmpty property as a shortcut when you want to know whether the count property is equal to 0.

if shoppingList.isEmpty {
print(“The shopping list is empty.”)
} else {
print(“The shopping list is not empty.”)
}
// prints “The shopping list is not empty.”

An array’s append method allows you to add a new item at the array’s end.

shoppingList.append(“Flour”)

Alternatively, add an array of one or more compatible items using the addition assignment operator (+=):

shoppingList += [“Juice”]
shoppingList += [“Chocolate”, “Cheese”]

Using subscript syntax, you can retrieve a value from the array, inserting the index of the value you want to retrieve within square brackets immediately after the name of the array:

var firstItem = shoppingList[0]

Arrays in Swift are always zero-indexed, meaning that the first item’s index is 0, rather than 1, as you might expect.
Accessing or modifying a value for an index that is outside of an array’s existing bounds triggers a runtime error. Check the validity of an index prior to using it by comparing it with the array’s count property.

Use subscript syntax to change an existing value at a given index:

shoppingList[0] = “Two apples”

Subscript syntax also changes a range of values all at once. This will even work with a replacement set of values with a length that is different from the original range.
In the following example, the elements with index 1, 2, 3 are replaced with two new values.

shoppingList[1…3] = [“Bananas”, “Oranges”]

Don’t use subscript syntax to append a new item to an array.

An array’s insert method will insert an item into the array at a specified index.

shoppingList.insert(“Syrup”, at: 0)

“Syrup” is now the first item in the list.

Similarly, the remove method allows you to remove an item from the array. This method removes the item at the specified index, and also returns the removed item. Note that the returned value can be ignored if it is not needed.

let syrup = shoppingList.remove(at:0)

When an item is removed from an array, Swift closes any gaps that have been created. If you want to remove the final item from an array, use the removeLast() method rather than the removeAtIndex method to avoid the need to query the array’s count property:

let apples = shoppingList.removeLast()
// the last item has just been removed

The for-in loop allows you to iterate over the entire set of values in an array.

for item in shoppingList {
print(item)}

Alternatively, use the enumerated() method to iterate over an array when you need the integer index for each item in addition to its value. This returns a tuple for each item in the array that indicates that item’s index and value. You can decompose the tuple into temporary constants or variables as part of the iteration:

for (index, value)in shoppingList.enumerated() {
print(“Item \(index + 1): \(value)”)}

This will print the index and the value of the elements in the array.

set stores distinct values of the same type in a collection with no defined ordering. Sets are used as an alternative to arrays when item order is not a concern or when you need to ensure that an item appears only once.
For a Swift set, write the type as Set<T> where T is the type that the set is allowed to store. Unlike arrays, there is no equivalent shorthand for sets.
You can create an empty set of a certain type using initializer syntax:

var letters = SetCharacter>()

Based on the initializer type, Swift infers the type of the letters to be Set<Character>.An array literal will also work as shorthand when initializing a set with one or more values as a set collection.

var names: Set<String> = [“David”, “Susan”, “Robert”]

When initializing the type of set with an array literal that contains values of the same type, it is not necessary to write the type of set. The initialization could have been written in a shorter form

:var names: Set = [“David”, “Susan”, “Robert”]

Because all values in the array literal are of the same type, Swift infers that Set<String> is the correct type to use for the names variable.

The count and isEmpty properties work the same way with a set as they do with an array.
Calling the set’s insert method adds a new item to a set.

names.insert(“Paul”)

You can remove an item from a set by calling the set’s remove method. The item is removed if it’s a member of the set, and the removed value is returned. It returns nil if the item is not contained in the set. Alternatively, use the set’s removeAll() method to remove all of the items in a set.

The contains method tells you whether or not a particular item is present in the set.

if names.contains(“James”) {
print(“James is here.”)
} else {
print(“James is not with us.”)
}

You can iterate over the values in a set with a for-in loop.

for name in names {
print(“\(name)”)
}

Since Swift’s Set type does not provide defined ordering, use the sorted() method to iterate over the values of a set in a specific order.

for name in names.sorted() {
print(“\(name)”)
}

Swift allows you to efficiently perform fundamental set operations, such as combining sets, determining which values two sets have in common, or determining whether two sets contain all, some, or none of the same values.

Fundamental Set Operations

The illustration below depicts sets a and b, and shows the results of various set operations, as represented by the shaded regions:

contentImage

The intersection method creates a new set, with only the values common to both sets.
The symmetricDifference method creates a new set with values in either set, but not both.The union method creates a new set with all of the values in both sets.
The subtracting method creates a new set with values not in the specified set.

For example, to combine the two sets:

let oddDigits: Set = [1, 3, 5, 7, 9]
let evenDigits: Set = [0, 2, 4, 6, 8]

oddDigits.union(evenDigits).sorted()
// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Set Membership and Equality

The illustration below depicts three sets: a, b, and c. The overlapping regions represent the elements that are shared among sets.
Set a is a superset of set b, because a contains all elements in b.
Conversely, set b is a subset of set a, because all elements in b are also contained by a.
Sets b and c are disjointed with one another, because they share no elements in common.

contentImage

“is equal” operator (==): Determines whether two sets contain all of the same values.
isSubset(of: ) method: Determines whether all of the values of a set are contained in the specified set.
isSuperset(of: ) method: Determines whether a set contains all of the values in a specified set.
isStrictSubset(of: ) or sStrictSuperset(of: ) method: Determines whether a set is a subset or superset of, but not equal to, a specified set.
isDisjoint(with: ) method: determines whether two sets have any values in common.

35 Comments

Drag and drop from the options below to create a new set “c”, with only the values common to both “a” and “b”, if not all of the values of set “a” are contained in set “b”.

let a: Set = [1, 2, 3]

let b: Set = [3, 5, 2]

if ! a.isSubset(of:

b) {

let c: Set

= a.intersection

(b)

}

dictionary stores associations between keys of the same type and values of the same type, in a collection with no defined ordering. Each value is associated with a unique key, which acts as an identifier for that value within the dictionary. A dictionary is used to look up values based on their identifiers, in much the same way that a real-world dictionary is used to look up the definition of a particular word.

Written in its entirety, a Swift dictionary’s type is Dictionary<Key, Value>. Key indicates which type of value can be used as a dictionary key, and Value indicates which type of value the dictionary stores for those keys. The shorthand form for the type of a dictionary is [Key: Value].

As with arrays, initializer syntax is used to create an empty Dictionary of a specified type:

var airports = [Int: String]()

the dictionary airports, the keys are of type Int, and the values are of type String.

A dictionary literal provides a way to write in shorthand one or more key-value pairs as a Dictionary collection.
The key and value in each key-value pair are separated by a colon. The key-value pairs are written as a list, separated by commas, surrounded by a pair of square brackets.
The example below creates a dictionary in which the keys are three-letter codes, and the values are airport names:

var airports: [String: String] = [“TOR”: “Toronto”, “NY”: “New York”]

As with arrays, it isn’t necessary to write the type of the dictionary when initializing it with a dictionary literal whose keys and values have consistent types. The initialization of airports could have been written in a shorter form instead.

var airports = [“TOR”: “Toronto”, “NY”: “New York”]

Because all keys and values in the literal share the same type, Swift can infer that [String: String] is the correct type to use for the airports dictionary.

The count and isEmpty properties also work for the dictionary.
Add a new item to a dictionary using subscript syntax:

airports[“LHR”] = “London”

Subscript syntax can be used to change the value associated with a particular key

airports[“LHR”] = “London Heathrow”
// the value for “LHR” has been changed

Use a dictionary’s updateValue method as an alternative to subscripting when setting or updating a key’s value. The updateValue method returns the old value after performing an update:

let oldValue = airports.updateValue(“New York”, forKey: “NY”)

Subscript syntax is also used to retrieve a value for a particular key from the dictionary.

let airportName = airports[“NY”]

If the value for the requested key does not exist, Swift returns a value of nil. Use subscript syntax to assign a value of nil to a key in order to remove a key-value pair from a dictionary.

airports[“APL”] = “Apple”
airports[“APL”] = nil

Alternatively, the removeValue(forKey: ) method removes a key-value pair from a dictionary, if the pair exists, and returns the removed value. nil is returned if no value exists.

if let removedValue = airports.removeValue(forKey: “NY”) {
print(“The removed airport’s name is \(removedValue).”)
} else {
print(“The airports dictionary does not contain a value for NY.”)
}

Use a for-in loop to iterate over the key-value pairs in a dictionary. Each item in the dictionary is returned as a (key, value) tuple, which you can decompose into temporary constants or variables as part of the iteration:

for (airportCode, airportName) in airports {
print(“\(airportCode): \(airportName)”)
}

In addition, accessing a dictionary’s keys and values properties will retrieve an iterable collection of the dictionary’s keys or values.

for airportCode in airports.keys {
print(“Airport code: \(airportCode)”)
}

for airportName in airports.values {
print(“Airport name: \(airportName)”)
}

Since Swift’s Dictionary type does not have a defined ordering, use the sort() method on the dictionary’s keys or values property to iterate over the keys or values in a specific order.

for x in 1…7 {
print(“in a loop”)
}

Functions are self-contained chunks of code that perform a specific task. Name a function in a way that identifies what it does, and then use the name to call the function to perform its task when needed.

In Swift, every function has a type that contains the function’s parameter types and return type. This type can be used like any other type in Swift, and this makes passing functions as parameters to other functions and returning functions from functions easier.

Functions can also be written within other functions to encapsulate useful functionality within a nested function scope.

When you define a function, you have the option of defining one or more named and typed values that the function takes as input (parameters), and/or a type of value that the function passes back as output (return type).

To use a function, call it using its name and pass to it input values (arguments) that match the types of the function’s parameters. Arguments must always be provided in the same order as in the function’s parameter list. Also, the argument label is mandatory.

The example below defines a function sayHello, which takes a String (personName) as a parameter and then returns another String:func sayHello(personName:

String) -> String {
let greeting = “Hello, ” + personName + “!”
return greeting
}

The function definition begins with the func keyword. The keyword is followed with a return arrow -> that indicates the function’s return type, and the name of the type to return ends the definition.
The return statement indicates the value to be returned by the function.
Once the function has been defined, it can be called in other parts of your code.

print(sayHello(personName: “David”))

You can call the defined function multiple times, and with different input values.

Multiple Input Parameters

Multiple input parameters can be written within the function’s parentheses. Use commas to separate the parameters.
This function takes a start and an end index for a half-open range, and works out how many elements are contained in the range.

func rangeLength(start: Int, end: Int) -> Int {
return end – start
}
print(rangeLength(start: 2, end: 7))
// prints “5”

When calling a function parameters, all arguments should be labelled according to its corresponding parameter name.
If you don’t want an argument label for a parameter, write an underscore (_) instead of an explicit argument label for that parameter.

Functions Without Parameters

Defining input parameters within a function is not a requirement. It is possible to have a function with no input parameters. That function will return the same String message every time it’s called:

func sayHelloWorld() -> String {
return “Hello, world”
}

The function definition still needs parentheses after the function’s name, even though there may be no parameters. The parentheses following the function name are simply empty when the function is called.

Functions Without Return Values

When defining a function it’s not mandatory to define a return type. In the example below, the function sayHi() prints its own String value, rather than returning it.

func sayHi(name: String) {
print(“Hi, \(name)!”)
}
sayHi(name: “Dave”)
// prints “Hi, Dave!”

Because it does not need to return a value, the function’s definition does not include the return arrow (->) or a return type.

The sayHi() function does still return a value, even though it has no defined return value. Functions without a defined return type return a special value of type Void.
Return values can be ignored, but a function that says it will return a value must always do so.

Multiple Return Values

You can use a tuple type as the return type for a function to return multiple values as part of one compound return value.

The example below defines a function that returns the smallest and largest numbers in an array of Int values:

func minMax(array:

[Int]) -> (min: Int, max: Int) {
var currMin = array[0]
var currMax = array[0]
for value in array[1..<array.count] {
if value < currMin {
currMin = value
} else if value > currMax {
currMax = value
}
}
return (currMin, currMax)
}

The minMax function returns a tuple containing two Int values. The values are labeled min and max, to facilitate easy access when querying the function’s return value.

Because the tuple’s member values are named as part of the function’s return type, they can be accessed using dot syntax to retrieve the minimum and maximum found values:

let bounds = minMax(array: [4, -4, 1, 88, 7, 42])
print(“min is \(bounds.min) and max is \(bounds.max)”)
// prints “min is -4 and max is 88”

It’s not necessary to name the tuple’s members when the tuple is returned from the function, because their names have already been specified as part of the function’s return type.

What is the output of the following code?

func test(n1: Int, n2:Int) -> (a: Int, b: Int) { return ((n1-n2), (n1+n2)) } let tmp = test(n1: 8, n2: 3) print(tmp.b)

its 11

Function parameters have both an external parameter name and a local parameter name.
The external parameter name is used to label arguments that are passed to a function call, while a local parameter name is used as the function is implemented.
By default, the first parameter omits its external name, and the second and subsequent parameters use their local name as their external name. Each parameter must be given its own, unique local name. External parameters may be shared. An external parameter name appears just before the local para meter name that it supports. The two parameter names are separated by a space:

func someFunc(externalName localName: Int) {
// function can use localName
}

Here’s a version of the sayHello() function that takes the names of two people and returns a greeting for both of them:

func sayHello(to p1: String, and p2: String) -> String {
return “Hello \(p1) and \(p2)!”
}
print(sayHello(to: “Tom”, and: “Jerry”))
// prints “Hello Tom and Jerry!”

The words to and and are the external parameter names, which are used when the function is called. The use of external parameter names can allow a function to be called in an expressive, sentence-like manner, and still produce a readable and clear function body.

If you provide an external parameter name for a given parameter, that external name must be used every time the function is called.

Fill in the blanks to define a function that multiplies two Integers and returns the product. Call the function using external parameter names.

func myFunc(a n1: Int, b n2: Int) -> Int {
return n1*;n2
}
print(myFunc(a: 11, b : 27))

Default Parameter Values

Adding a value after a function parameter’s type defines a default value for the parameter. If a default value is defined, that parameter can be omitted when calling the function.func someFunction(p1: Int = 12) {
// the default value of p1 is 12
}
someFunction(p1: 6) // p1 is 6
someFunction() // p1 is 12SWIFTTry it YourselfPlace parameters with default values at the end of a function’s parameter list.

Variadic Parameters

Variadic parameters indicate that the number of input values of a specified type passed to the parameter can vary. The variadic parameter can accept zero and/or more parameters of a certain type, and is indicated by adding three period characters (…) immediately following the parameter’s type name.

The values passed to a variadic parameter appear as an array of the specified type in the function’s body.

In the example below, the function calculates the arithmetic mean, or average, for a list of numbers of any length:

func arithmeticMean(numbers: Double…) -> Double {
var total: Double = 0
for number in numbers {
total += number
}
return (total / Double(numbers.count))
}

One variadic parameter is allowed per function. The variadic parameter must always be the last parameter in the list, to ensure clarity when calling the function with multiple parameters.

For a function with one or more parameters containing default values, as well as a variadic parameter, the variadic parameter is added at the very end of the list, following all defaulted parameters.

In-Out Parameters

Function parameters are constants by default. Trying to change the value of a function parameter from within the body of that function results in a compile-time error. This means that you can’t change the value of a parameter by mistake. If you want a function to modify a parameter’s value, and you want those changes to persist after the function call has ended, define that parameter as an in-out parameter instead.

The inout keyword is placed at the beginning of the parameter’s type. Its value is passed in to the function, where it is modified. It’s then passed back out of the function, where it replaces the original value.

This example swaps out two Integer values.

func swapInts(a: inout Int, b: inout Int) {
let tempA = a
a = b
b = tempA
}

An in-out parameter cannot be assigned a default value. A variadic parameter cannot be marked as inout.

An ampersand (&) that is inserted directly before a variable’s name when it’s passed as an argument to an inout parameter, indicates that the variable can be modified by the function:

var someInt = 3
var anotherInt = 107
swapInts(a: &someInt, b: &anotherInt)

The in-out parameter presents an alternative method when a function is desired to have an effect outside of the scope of its function body.

Every function has a specific function type that consists of the function’s parameter types and return type. Here’s an example:

func addInts(a: Int, b: Int) -> Int {
return a + b
}
func multiplyInts(a: Int, b: Int) -> Int {
return a * b
}

This example defines two simple mathematical functions called addInts and multiplyInts, which take two Int values, which return an Int value.
For both of these functions, the type is (Int, Int) -> Int. This can be interpreted as
“A function type that has two parameters, both of type Int; and that returns a value of type Int.”

Here’s another example. This one shows a function with no parameters or return value:

func printHelloWorld() {
print(“Hello, world”)
}

The type of this function is () -> Void, which translates into “a function that has no parameters, and returns Void.”

unction types are used in the same way as any other Swift types.
For example, define a constant or a variable to be of a function type. Then assign an appropriate function to that variable:

var mathFunction: (Int, Int) -> Int = addInts
You can now call the assigned function using its name, mathFunctionprint(“Result: \(mathFunction(2, 3))”)

A different function with the same type can be assigned to the same variable, in the same way as for non-function types.

var mathFunction: (Int, Int) -> Int = addInts
You can now call the assigned function using its name, mathFunctionprint(“Result: \(mathFunction(2, 3))”)

A different function with the same type can be assigned to the same variable, in the same way as for non-function types.

Drag and drop from the options below to assign the function myFunc to the variable t.

func myFunc(s1: String) -> Int {

return s1.characters.count

}

var t: (String

) -> Int = myFunc->IntDoublefunc

Function Types as Parameter Types

A function type, such as (Int, Int) -> Int, can act as a parameter type for a different function, allowing for leaving some aspects of a function’s implementation for the function’s caller to provide calling the function.
The following example defines a function called printResult, which takes another function as its parameter and calls it as it’s implemented:func printResult(mathFunc: (Int, Int) -> Int, a: Int, b: Int) {
print(“Result: \(mathFunc(a, b))”)
}
printResult(addInts, a: 3, b: 5) SWIFTTry it YourselfIt doesn’t matter what the called function’s implementation actually does – it matters only that the function is of the correct type.

Function Types as Return Types

A function type may be used as another function’s return type, by writing a complete function type immediately following the return arrow (->) in the returning function.func plus(input: Int) -> Int {
return input + 1
}
func minus(input: Int) -> Int {
return input – 1
}
func chooseFunc(flag: Bool) -> (Int) -> Int {
if(flag) {
return plus
}
else {
return minus
}
}

In the above example, the chooseFunc function returns another function of type (Int) -> Int, based on the value of its flag parameter.

Nested Functions

You also have the option of defining functions inside the bodies of other functions. These are called nested functions.

By default, a nested function is hidden from the outside world. It can still be called and used by its enclosing function. An enclosing function can also return one of its nested functions, thus allowing the nested function to be used in another scope.

From the previous lesson, the function chooseFunc can be rewritten to use and return nested functions:

func chooseFunc(flag: Bool) -> (Int) -> Int {
func plus(input: Int) -> Int { return input + 1 }
func minus(input: Int) -> Int { return input – 1 }

if(flag) {
return plus
}
else {
return minus
}
}

The term recursion is used to describe the situation in which a function calls itself:

func factorial(n: Int) -> Int {
return n == 0 ? 1 : n * factorial(n: n-1)
}
print(factorial(n: 5)) //prints 120

The function calls itself recursively, until n is equal to 0, at which point the recursion ends.Be sure to always add a condition that ends the recursion. Otherwise, your recursion will continue infinitely.

Closure is a self-contained block of functionality that can be passed around and used in your code.

Global and nested functions are actually special kinds of closures.

Nested functions offer a convenient way to name and define self-contained blocks of code within a larger function.

However, it is sometimes useful to have the option of writing shorter versions of function-like constructs that do not require full declarations and names. This is particularly true when working with functions that take other functions as one or more of their arguments.

Closure expressions present a way to write inline closures using brief, focused syntax. Closure expressions offer a number of syntax optimizations for use in writing closures in a shortened form, without losing clarity or intent.

Closure expression syntax takes the following general form:

{ (parameters) -> return type in
statements
}

Closure expression syntax can use constant parameters, variable parameters, and inout parameters, but default values cannot be used. Variadic parameters can be used if you name them and make sure that it’s placed last in the parameter list.

o understand how Closures are used, let’s take a look at a function called sorted, which is available in Swift’s standard library. The sorted function orders an array of values of a known type.

The sorted method takes two arguments:
– An array of values of a known type.
– A closure that takes two arguments of the same type as the array’s contents, and returns a Bool value to say whether the first value should appear before or after the second value once the sorting is complete.

The example below shows the sorting of an array of String values. The sorting closure needs to be a function of type (String, String) -> Bool.
One way to provide the sorting closure is to write a normal function of the correct type, and to pass it in as the sorted method’s parameter:

func backwards(s1: String, s2: String) -> Bool {
return s1 > s2
}
let names = [“Cc”, “Aa”, “Ee”, “Bb”, “Dd”]
var reversed = names.sorted(by: backwards)

The example compares the Strings in the array names, based on the backwards function.
However, this is a long-winded way to write what is really a function that contains a single-expression (a > b).
In this situation, it would be preferable to write the sorting closure inline, using closure expression syntax:

let names = [“Cc”, “Aa”, “Ee”, “Bb”, “Dd”]
var reversed = names.sorted(by: { (s1: String, s2: String) -> Bool in
return s1 > s2
}
)

For the inline closure expression, the parameters and return type are written within the curly braces, rather than outside of them. The in keyword is used to introduce the beginning of the closure’s body, and indicates that the definition of the closure’s parameters and return type has finished, and the body of the closure is about to begin.

Inferring Type from Context

The sorting closure is passed as an argument to a function, making it possible for Swift to infer the types of its parameters and the type of the return value from the type of the sorted method’s second parameter. This parameter expects a function of type (String, String) -> Bool. This means that writing the (String, String) and Bool types as part of the closure expression’s definition is not necessary. Because all of the types can be inferred, the return arrow (->) and the parentheses around the names of the parameters can also be omitted:

reversed = names.sorted(by: { s1, s2 in return s1 > s2 } )

The parameter types and return type can always be inferred when passing a closure to a function as an inline closure expression. As a result, it is unnecessary to write an inline closure in its fullest form when the closure is used as a function argument. You still have the option of writing out the types. In fact, doing so is encouraged when you need to avoid ambiguity for others who might read your code.

Closures17 Comments

Fill in the blanks to define a function that takes an array of Integers as a parameter and returns it, sorted in descending order.

func order(arr:[Int])-> [Int] { return
arr.sorted(by: {
n1, n2 in n1 > n2
})
}

Inferring Type from Context

Single-expression closures can implicitly return the result of their single expression, simply by omitting the return keyword from the declaration, as in this new version of the previous example:

reversed = names.sorted(by: { s1, s2 in s1 > s2 } )

Here, the function type of the sorted method’s second argument makes it clear that a Bool value must be returned by the closure.

Because the closure’s body contains a single expression (s1 > s2) that returns a Bool value, there is no ambiguity, and the return keyword can be omitted.

a = b.sorted(by: {s1, s2 in s1 > }s2 )

Swift automatically provides shorthand argument names for inline closures. These argument names can be used to refer to the values of the closure’s arguments, with the names $0$1$2, and so on.

If you use these shorthand argument names within your closure expression, you can omit the closure’s argument list from its definition, and the number and type of the shorthand argument names will be inferred from the expected function type. The in keyword can also be omitted, since the closure expression is entirely made up of its body:reversed = names.sorted(by: { $0 > $1 } )SWIFTTry it YourselfHere, $0 and $1 refer to the closure’s first and second String arguments.

Operator Functions

There’s actually an even shorter way to write the closure expression above. Swift’s String type defines its string-specific implementation of the greater-than operator (>) as a function that has two parameters of type String, and returns a value of type Bool. This exactly matches the function type needed for the sort method’s second parameter. Just pass in the greater-than operator, and Swift will then infer that you want to use its string-specific implementation:

reversed = names.sorted(by: >)

Tuples group multiple values into a single, compound value. The values within a tuple can be of any type and do not have to share a common type.let error = (404, “Not Found”)SWIFTTry it YourselfThe tuple above is of type (Int, String).

You can create tuples from any permutation of types, and they can contain as many different types as you like. There’s nothing stopping you from having a tuple of type (Int, Int, Int), or (String, Bool), or any other permutation you require.

A tuple’s contents can be broken down into separate constants or variables, which you then access as you would any constant or variable.

let (statusCode, statusMessage) = error
print(“The status code is \(statusCode)”)
// prints “The status code is 404”
print(“The status message is \(statusMessage)”)
// prints “The status message is Not Found”

An alternative method of accessing individual element values in a tuple is to use index numbers, starting with zero.

print(“The status code is \(error.0)”)
print(“The status message is \(error.1)”)

When you define a tuple, you have the opportunity to name its individual elements. You can then use the element names to access the values of those elements:

let http200Status = (statusCode: 200, description: “OK”)
print(“The status code is \(http200Status.statusCode)”)
print(“The status message is \(http200Status.description)”)

An enumeration defines a common type for a group of related values. It enables you to work with those values in a type-safe way within your code.
Use the enum keyword to introduce an enumeration, and place their entire definition within a pair of braces:

enum Compass {
case North
case South
case East
case West
}

Multiple member values can appear on a single line, separated by commas:

enum Planet {
case Mercury, Venus, Earth, Mars, Jupiter
}

Each enumeration definition specifies a brand new type. As with other types in Swift, their names (such as Compass and Planet) should be capitalized.

The values in an enumeration can be accessed using the dot syntax.

var direction = Compass.West

Give enumeration types singular rather than plural names, so that they read as self-evident.


Fill in the blanks to declare an enumeration called “Planet”, and use it in a switch statement:

enum Planet {
case Mercury, Venus, Earth, Mars
}
let somePlanet = Planet.Earth
switch somePlanet {
case.Earth:
print(“Mostly harmless”)
default:
print(“Not a safe place for humans”)
}

Classes and structures are general-purpose, flexible constructs that become the building blocks of your program’s code. You define properties and methods to add functionality to your classes and structures by using exactly the same syntax as for constants, variables, and functions.

Swift does not require that you create separate interface and implementation files for custom classes and structures. Rather, they are defined in a single file. The external interface to that class or structure is automatically made available for other code to use. In other languages, an instance of a class is traditionally known as an object. However, because classes and structures in Swift are much closer in functionality than in other languages, the more general term instance is used.

Classes and structures have a similar definition syntax.
You introduce classes with the class keyword and structures with the struct keyword. Each places its entire definition within a pair of braces.

struct Resolution {
var width = 0
var height = 0
}

class VideoMode {
var resolution = Resolution()
var interlaced = false
var frameRate = 0.0
}

The example above defines a new structure called Resolution, with two stored properties called width and height.
It also defines a new class called VideoMode, which has three variable stored properties. The first, resolution, is initialized with a new Resolution structure instance, which infers a property type of Resolution.

When a new class or structure is defined, a brand new Swift type is defined.

The Resolution structure definition and the VideoMode class definition only describe what each one will look like. The definitions in themselves do not describe a specific resolution or video mode. To do that, you need to create an instance of the structure or class.

The syntax for creating instances is very similar for both structures and classes:

let someResolution = Resolution()
let someVideoMode = VideoMode()

When creating new instances, structures and classes both use initializer syntax. The simplest form of initializer syntax uses the type name of the class or structure, followed by empty parentheses.

This creates a new instance of the class or structure. Properties are initialized to their default values.

define a structure called Size. Also, create two instances of your newly created structure.

struct

Size {var width = 0 var height = 0 }

let s1 = Size()

let s2 = Size()

Access an instance’s properties with dot syntax. Write the property name immediately after the instance name, separated with a period (.), with no spaces:

print(“The width is \(someResolution.width)”)

In this example, someResolution.width refers to the width property of someResolution, and returns its value.

You can drill down into a sub-property, such as the width property, which is in the resolution property of a VideoMode

print(someVideoMode.resolution.width)

Dot syntax is also used when assigning a new value to a variable property.

someVideoMode.resolution.width = 1280

In the last example, the width property of the resolution property of someVideoMode is set directly, with no need to set the entire resolution property to a new value.All structures have an automatically-generated memberwise initializer, which you can use to initialize the member properties of new structure instances. Initial values for the properties of the new instance can be passed to the memberwise initializer by name:

let vga = Resolution(width: 640, height: 480)

Unlike structures, class instances do not receive a memberwise initializer by default.

Structures are Value Types

value type is a type whose value is copied when it is assigned to a variable or constant, or when it is passed to a function.
In fact, all of the basic types in Swift – integers, floating-point numbers, Booleans, strings, arrays, and dictionaries – are value types, and are implemented as structures behind the scenes.

All Swift structures are value types. This means that any structure instances you create – and any value types they have as properties – are always copied when they are passed around in your code.

Consider this example, which uses the Resolution structure from the previous example:

let hd = Resolution(width: 1920, height: 1080)
var cinema = hd

The example declares a constant called hd and sets it to a Resolution instance.
It then declares a variable called cinema, and sets it to the current value of hd. Because Resolution is a structure, a copy of the existing instance is made, and this new copy is assigned to cinema. Even though hd and cinema now have the same width and height, behind the scenes they are two completely different instances.

Next, the width property of cinema is amended:

cinema.width = 2048

However, the width property of the original hd instance still has the old value of 1920.

print(“hd is still \(hd.width) pixels wide”)
// prints “hd is still 1920 pixels wide”

The same behavior is true of enumerations.

Classes are Reference Types

Unlike value types, reference types are not copied when assigned to a variable or constant, or when they are passed to a function. Rather than a copy, a reference to the existing instance is used instead.
Here’s an example, using the VideoMode class:

let tenEighty = VideoMode()
tenEighty.resolution = hd
tenEighty.interlaced = true

let alsoTenEighty = tenEighty
alsoTenEighty.interlaced = false

The video mode is assigned a copy of the hd resolution of 1920 by 1080 from before.
Next, tenEighty is assigned to a new constant, named alsoTenEighty, and the interlaced property of alsoTenEighty is modified.
Because classes are reference types, tenEighty and alsoTenEighty actually both refer to the same VideoMode instance, so the interlaced value is changed for both. Effectively, they are just two different names for the same single instance.Rather than being declared as variables, tenEighty and alsoTenEighty are declared as constants. However, it’s still possible to change their properties, because the values of the tenEighty and alsoTenEighty constants themselves do not actually change.

Identity Operators

You may need to determine whether two constants or variables refer to the same instance of a class. To accomplish this, Swift provides the following identity operators:
Identical to (===)
Not identical to (!==)

Use these operators to check your constants or variables to see if they refer to the same single instance:

if tenEighty === alsoTenEighty {
print(“Same”)
}

Note that “identical to” (represented by three equals signs, or ===) does not mean the same thing as “equal to” (represented by two equals signs, or ==).

Classes vs. Structures

Structure instances are always passed by value, and class instances are always passed by reference. This means that they are suited to different kinds of tasks.
As a general guideline, consider creating a structure instead of a class when one or more of these conditions apply:

1. The structure’s primary purpose is to encapsulate a few relatively simple data values.
2. It is reasonable to expect that the encapsulated values will be copied rather than referenced when you assign or pass around an instance of that structure.
3. Any properties stored by the structure are themselves value types, which you would also expect to be copied, as opposed to being referenced.
4. It is not necessary for the structure to inherit properties or behavior from another existing type.

For example, the size of a geometric shape would be a good choice for a structure, with the structure perhaps encapsulating a width property and a height property, both of type Double.

In all other cases, define a class. You will find that most custom data constructs should be defined as classes rather than as structures.

Swift’s StringArray, and Dictionary types are implemented as structures.

Properties

Properties associate values with a particular class, structure, or enumeration. Stored properties store constant and variable values as part of an instance.
In its simplest form, a stored property is a constant or variable that is stored as part of an instance of a particular class or structure.

struct Size {
var width: Int
let height: Int
}
var size1 = Size(width: 10, height: 35)
size1.width = 6

In the example above, height is initialized when the new size is created. This is a constant property, and it cannot be changed once initialized.
When creating an instance of a structure, if you assign an instance of a structure to a constant, the instance’s properties cannot be modified, even if they were declared as variable properties.

Lazy Stored Properties

lazy stored property’s initial value is not calculated until the first time it is used.

class DataManager {
lazy var importer = DataImporter()
var data = [String]()
}

Lazy properties are useful when a property’s initial value is dependent on outside factors, the values of which are not known until after an instance’s initialization is complete; or when the initial value for a property requires complex or computationally expensive setup that should not be performed unless or until it is needed. You must always declare a lazy property as a variable, using the var keyword, because its initial value might not be retrieved until after the completion of instance initialization. Constant properties must always have a value before initialization completes, and therefore cannot be declared as lazy.

Computed Properties

Rather than storing a value, a computed property provides a getter and, optionally, a setter, which indirectly retrieve and set other properties and values, respectively.struct Point {
var x = 0.0, y = 0.0
}
struct Shape {
var origin = Point()
var center: Point {
get {
return Point(x: origin.x/2 , y: origin.y/2)
}
set(newCenter) {
origin.x = newCenter.x/2
origin.y = newCenter.y/2
}
}
}SWIFTTry it YourselfThe Shape structure defines a custom getter and setter for a computed variable called center. The center property is then accessed through dot syntax, which causes the getter for center to be called to retrieve the current property value. Rather than returning an existing value, the getter actually calculates and returns a new point that represents the center of the shape.

If a computed property’s setter does not define a name for the new value to be set, a default name of newValue is used.
Below is an alternative version of the Rect structure, which takes advantage of this shorthand notation:

struct Point {
var x = 0.0, y = 0.0
}
struct Shape {
var origin = Point()
var center: Point {
get {
return Point(x: origin.x/2, y: origin.y/2)
}
set {
origin.x = newValue.x/2
origin.y = newValue.y/2}}}

A computed property with a getter but no setter is known as a read-only computed property. It always returns a value, and can be accessed through dot syntax. However, that value cannot be altered.

Drag and drop from the options below to declare a read-only volume property. Then create a Cuboid variable and print its volume property.

struct Cuboid {

var w = 0.0, h = 0.0, d = 0.0

var volume: Double {get

{

return w * h * d}}}

var c =Cuboid

(w:2, h: 5, d: 3)

print(c.volume)

Property Observers

Property observers detect and respond to changes in a property’s value. Property observers are called every time a property’s value is set, even if the new value is the same as the property’s current value.
Property observers can be added to any defined stored properties, with the exception of lazy stored properties.
You have the option of defining either or both of the following observers of a property:
– willSet is called just before the value is stored.
– didSet is called immediately after the new value is stored.

The example below defines a new class called StepCounter, which tracks the total number of steps that a person takes while walking.

class StepCounter {
var totalSteps: Int = 0 {
willSetnewSteps) {
print(“About to set totalSteps to \(newSteps)”)
}
didSet {
if totalSteps > oldValue {
print(“Added \(totalSteps – oldValue) steps”)
}
}
}
}
let stepCounter = StepCounter()
stepCounter.totalSteps = 50
// About to set totalSteps to 50
// Added 50 steps
stepCounter.totalSteps = 150
// About to set totalSteps to 150
// Added 100 steps
stepCounter.totalSteps = 420
// About to set totalSteps to 420
// Added 270 steps

The StepCounter class declares a totalSteps property of type Int, with willSet and didSet observers.
The willSet and didSet observers for totalSteps are called whenever the property is assigned a new value.
The willSet observer uses a custom parameter name of newSteps for the upcoming new value.

The didSet observer is called after the value of totalSteps is updated. It compares the new value of totalSteps against the old value. The didSet observer does not provide a custom parameter name for the old value; the default name of oldValue is used, instead.
Similarly, newValue could be used for the willSet observer, if no parameter name was defined.If you assign a value to a property within its own didSet observer, the new assigned value will replace the one that was just set.

Type Properties

Type properties are useful when defining values that are universal to all instances of a particular type, such as a constant property used in all instances, or a variable property that stores a global value to all instances of that type. Stored type properties can be variables or constants. You define type properties with the static keyword:

class SomeClass {
static var storedProp = “Some value.”
static var computedProp: Int {
return 42
}
}

Type properties are queried and set with dot syntax, just like instance properties. However, type properties are queried and set on the type, not on an instance of that type:

print(SomeClass.storedProp)

Unlike stored instance properties, you must always give stored type properties a default value. This is because the type itself does not have an initializer that can assign a value to a stored type property at initialization time.

Methods

Methods are functions that are associated with a particular type. Classes, structures, and enumerations can all define instance methods.
Instance methods are functions that belong to instances of a particular class, structure, or enumeration. Instance methods have exactly the same syntax as functions:

class Counter {
var count = 0
func increment() {
count+=1
}
func incrementBy(amount: Int) {
count += amount
}
func reset() {
count = 0
}
}

You call instance methods with the same dot syntax used for properties:let counter = Counter()
// the initial counter value is 0
counter.increment()
// the counter’s value is now 1
counter.incrementBy(amount: 5)
// the counter’s value is now 6
counter.reset()
// the counter’s value is now 0

The self Property

The self property refers to the current instance within its own instance methods.
The increment() method in the previous example could have been written like this:

func increment() {
self.count+=1
}

n practice, you rarely need to write self in your code.
You can use the self property to distinguish between the parameter name and the property name.
Here, self disambiguates between a method parameter called x and an instance property that is also called x

struct Point {
var x = 0.0, y = 0.0
func isToTheRight(x: Double) -> Bool {
return self.x > x
}
}

Without the self prefix, Swift would assume that both uses of x referred to the method parameter called x.

Modifying Value Types

Structures and enumerations are value types. By default, the properties of a value type cannot be modified from within its instance methods.
The mutating keyword is added to the method’s definition so it can modify its properties.

struct Point {
var x = 0.0, y = 0.0
mutating func moveByX(dX: Double, dY: Double) {
x += dX
y += dY
}
}

You cannot call a mutating method on a constant of structure type, because its properties cannot be changed.Mutating methods can assign an entirely new instance to the implicit self property

Type Methods

Instance methods are called on an instance of a particular type. A type method is called on the type itself, and is indicated by writing the keyword static before the method’s func keyword:

class SomeClass {
static func someTypeMethod() {
// type method implementation goes here
}
}
SomeClass.someTypeMethod()

As with instance methods, type methods are called with dot syntax. However, type methods are called on the type, not on an instance of that type. Within the body of a type method, the implicit self property refers to the type itself, rather than an instance of that type.

Subscripts

Classes, structures, and enumerations can define subscripts, which are shortcuts for accessing the member elements of a collection, list, or sequence. Subscripts enable you to query instances of a type by writing one or more values in square brackets after the instance name.
Subscript definitions are written using the subscript keyword, and specify one or more input parameters and a return type, in the same way as instance methods.
Here’s an example of a read-only subscript implementation, which defines a TimesTable structure to represent an n-times-table of integers:

struct TimesTable {
let multiplier: Int
subscript(index: Int) -> Int {
return multiplier * index
}
}
let threeTimesTable = TimesTable(multiplier: 3)
print(threeTimesTable[5])
// prints “15”

Multiple subscripts can be defined for a single type. The appropriate subscript overload to use is selected according to the type of index value you pass to the subscript. Subscripts are not limited to a single dimension, and can be defined using multiple input parameters that best suit your custom type’s needs.

Subscripts

Matrix is a good example how a subscript is used.
The following example defines a Matrix structure, which represents a two-dimensional matrix of Double values. The subscript takes two integer parameters:

struct Matrix {
let rows:

Int, columns: Int
var grid: [Double]
init(rows: Int, columns: Int) {
self.rows = rows
self.columns = columns
grid = Array(repeating: 0.0, count: rows * columns)
}
subscript(row: Int, column: Int) -> Double {
get {
return grid[(row * columns) + column]
}
set {
grid[(row * columns) + column] = newValue
}
}
}

Matrix provides an initializer that takes two parameters called rows and columns to create an array large enough to store values of type Double. Each position in the matrix is given an initial value of 0.0.Initialization is described in detail in the coming lessons.You can construct a new Matrix instance by passing an appropriate row and column count to its initializer:

var matrix = Matrix(rows: 2, columns: 2)

This results in the following grid:

contentImage

Values in the matrix can be set by passing comma-separated row and column values into the subscript.:matrix[0, 1] = 1.5
matrix[1, 0] = 3.2SWIFTTry it YourselfThis results in the following:

contentImage

Inheritance

A class can inherit methods, properties, and other characteristics from another class. The inheriting class is a subclass, and the class from which it inherits from is its superclass. Inheritance is a fundamental behavior that differentiates classes from other types in Swift.
Any class that does not inherit from another class is known as a base class.
Subclassing is the act of basing a new class on an existing class.
To understand inheritance in action, let’s create an example:

class Vehicle {
var currentSpeed = 0.0
var desc: String {
return “traveling at \(currentSpeed) mph”
}
func makeNoise() {
// do nothing
}
}

To indicate that a subclass has a superclass, write the subclass name before the superclass name, separated by a colon:

class Bicycle: Vehicle {
var hasBasket = false
}

The new Bicycle class automatically takes on all of the characteristics of Vehicle, including properties such as currentSpeed and desc, as well as methods like makeNoise(). In addition to its inherited characteristics, the Bicycle class defines a new stored property, hasBasket.
You can also modify the inherited currentSpeed property of a Bicycle instance, and query the instance’s inherited desc property:

let bicycle = Bicycle()
bicycle.hasBasket = true
bicycle.currentSpeed = 25.0
print(“Bicycle: \(bicycle.desc)”)

Subclasses can themselves be subclassed. The next example creates a subclass of Bicycle for a two-seater bicycle, or a tandem.class Tandem:

Bicycle {
var currNumOfPassengers = 0
}

If you create an instance of Tandem, you can work with any of its properties, both new and inherited. You can also query the read-only desc property it inherited from Vehicle

let tandem = Tandem()
tandem.hasBasket = true
tandem.currNumOfPassengers = 2
tandem.currentSpeed = 20.0
print(“Tandem: \(tandem.desc)”)

Overriding

A subclass can provide its own custom implementation of an instance method, type method, instance property, type property, or subscript that it would otherwise inherit from a superclass. This is known as overriding.
To override a characteristic that would otherwise be inherited, prefix the overriding definition with the override keyword.

The superclass version of a method, property, or subscript is accessed by using the super prefix.
For example:
– An overridden method named someMethod() can call the superclass version of someMethod() by calling super.someMethod() within the overriding method implementation.
– An overridden property called someProperty can access the superclass version of someProperty as super.someProperty within the overriding getter or setter implementation.
– An overridden subscript for someIndex can access the superclass version of the same subscript as super[someIndex] from within the overriding subscript implementation.

The following example defines a new subclass of Vehicle, called Train, which overrides the makeNoise() method that Train inherits from Vehicle:

class Train: Vehicle {
override func makeNoise() {
print(“Choo Choo”)
}
}

The following example defines a new class called Car, which is a subclass of Vehicle. The Car class introduces a new stored property called gear, which has a default integer value of 1. The Car class also overrides the description property inherited from Vehicle to provide a custom description that includes the current gear:class Car:

Vehicle {
var gear = 1
override var desc: String {
return super.desc + ” in gear \(gear)”
}
}

You can prevent a method, property, or subscript override by marking it as final (such as final varfinal funcfinal class func, and final subscript).
You can mark an entire class as final by placing the final modifier before the class keyword in its class definition (final class).

Initialization

The process of preparing an instance of a class, structure, or enumeration for use is called initialization. It involves setting an initial value for each property stored in that instance and performing any other setup or initialization that is required before the new instance is ready for use.
Classes and structures must set all of their stored properties to an appropriate initial value prior to creation of an instance.
Initializers are called to create a new instance of a particular type. In its simplest form, an initializer is like an instance method with no parameters, and is written using the init keyword:

struct Fahrenheit {
var temp: Double
init() {
temp = 32.0
}
}
var f = Fahrenheit()

As part of an initializer’s definition, initialization parameters define the types and names of values that customize the initialization process.

struct Celsius {
var tempInCelsius: Double
init(fromFahrenheit fahrenheit: Double) {
tempInCelsius = (fahrenheit – 32.0) / 1.8
}
init(fromKelvin kelvin: Double) {
tempInCelsius = kelvin – 273.15
}
}
let boilingPoint = Celsius(fromFahrenheit: 212.0)
let freezingPoint = Celsius(fromKelvin: 273.15)

The example above defines a structure called Celsius, which implements two custom initializers called init(fromFahrenheit:) and init(fromKelvin:). This initializes a new instance of the structure with a value from a different temperature scale. When you assign a default value to a stored property, or set its initial value within an initializer, the value of that property is set directly, without calling any property observers.

Initializers

In the case of structure types that have no defined custom initializers, Swift automatically provides a memberwise initializer, even if the structure types have stored properties that do not have default values.
The Size structure automatically receives an init(width:height:) memberwise initializer, which you can use to initialize a new Size instance:struct Size {
var width = 0.0, height = 0.0
}
let twoByTwo = Size(width: 2.0, height: 2.0)SWIFTTry it Yourself

Class Initialization

All stored properties of a class – including any properties inherited from its superclass – must be assigned an initial value during initialization. In other words, assign a default value or create an initializer for the properties of the class.
The structure from the above example would have the following form as a class with an initializer:

class Size {
var width:Double, height:Double
init(w:Double, h:Double) {
width = w
height = h
}
}
let twoByTwo = Size(w: 2.0, h: 2.0)

Required Initializers

Write the required modifier before the definition of a class initializer to indicate that every subclass of the class must implement that initializer:

class SomeClass {
required init() {
// initializer implementation goes here
}
}

You must also insert the required modifier before every subclass implementation of a required initializer. This indicates that the initializer requirement applies to further subclasses along the chain. Do not write the override modifier when overriding a required designated initializer:

class SomeSubclass: SomeClass {
required init() {
// subclass implementation goes here
}
}

It’s not necessary to provide an explicit implementation of a required initializer if you can satisfy the requirement with an inherited initializer.

Deinitialization

deinitializer is called immediately before a class instance is deallocated, and is useful when you work with your own resources.
For example, if you create a custom class to open a file and write some data to it, you might need to close the file before the class instance is deallocated.Class definitions can have at most one deinitializer per class.Rather than providing you with the ability to call a deinitializer, Swift automatically calls it, just prior to instance deallocation. Superclass deinitializers are inherited by their subclasses, and the superclass deinitializer is called automatically at the end of a subclass deinitializer implementation. Superclass deinitializers are always called, even in cases in which subclasses do not provide their own deinitializers.

The deinit keyword is used to write a deinitializer, which is similar to writing an initializer using the init keyword. The deinitializer does not take any parameters and is written with no parentheses

:deinit {
// perform the deinitialization
}

Deinitializers are only available on class types.

Leave a Comment