# Lecture Handout

## Welcome

Hello! Welcome to AppDev’s iOS Training Course. Throughout this course, you will learn all the fundamentals of iOS programming and learn how to build your own full-fledged iOS applications! Each lecture will be accompanied by a handout (like this) summarizing the main concepts from that lecture. This is the first handout and we will be covering Swift and Xcode.

## Xcode

### What is Xcode?

Xcode is the main integrated development environment (IDE) that iOS developers use to develop their applications. In simpler terms, Xcode is just the application that we use to write iOS code (similar to how you might use Atom, Sublime, vim, etc.). The reason all iOS developers use Xcode (instead of other IDE’s) is that other than being a place for us to write iOS code, Xcode allows us to run our code and build our application on a simulator. This is important because otherwise we would have no way to testing if our code actually does what it wants!

### Creating a new Xcode project&#x20;

{% content-ref url="../../cheat-sheets/setting-up-a-new-xcode-project" %}
[setting-up-a-new-xcode-project](https://ios-course.cornellappdev.com/resources/archived-past-semesters/sp23/cheat-sheets/setting-up-a-new-xcode-project)
{% endcontent-ref %}

## Swift

### What is Swift?

Swift is Apple’s newest programming language for developing iOS applications. One other popular programming language that you can use is Objective-C. However, in this course we will be using Swift. Thus, you will be writing Swift code inside your Xcode project and then running that on the simulator to see your application come to life.

### Swift Basics

We will now cover some fundamentals of the Swift programming language. One thing to note is that while we will not be able to cover every single aspect of Swift in this handout, any aspect not covered can be found through a simple Google search.

#### Variables and Constants

```swift
var x = 5
var y: Int = 5
y = 6
```

Like other programming languages, we can declare a **variable** in Swift using the syntax `var [variable name] = [value]`.&#x20;

Unlike languages like Java, where value types have to be explicitly typed, Swift has **type-inferencing** so Swift is able to infer the type of your variable based on the value that you assign to it. For example, by assigning **5** to `x`, Xcode knows that `x` is of type **Int** because **5** is of type **Int**. Therefore, when declaring a new variable and assign a value to it, it is not required to also declare the type of the variable.&#x20;

If you wanted to, however, you could do so using the syntax `var [variable name]: [type] = [value]` There are also some cases where the type is ambiguous and Swift cannot automatically infer the type so you'd have to explicitly declare the type for the compiler.

```swift
let z = 7
let y: Int = 5
z = 8 // Error!
```

In addition to variables, we can also declare a **constant**. One important distinction to make between variables and constants is that after you assign a value to a constant, you **cannot** change the constant’s value again in the future (you can change a variable’s value). The syntax to declare a constant is `let [variable name] = [value]`. Similar to variables, it is not required to declare the type of the constant, although you can.

#### Classes and Structs

```swift
// class name
class Song {

    // field declarations
    var name: String
    var author: String
    
    // methods
    init(name: String, author: String) {
        self.name = name
        self.author = author
    }

}
```

In Swift, we can also declare **classes** and **structs**. Every class contains several different parts: a **class name**, **fields**, and **methods**. Fields are just **variables/constants** that belong to that class. In our sample class above, for example, our **Song** class contains a `name` field of type `String`and an `author` field of type `String`. Similarly, **methods** are just functions that belong to that class. In our example above, we have an **init** method which is called when you create an instance of that class.

A **struct** has the same exact syntax as a class (except you replace **class** with **struct**). However, a core difference between structs and classes is that structs are **value types** whereas classes are **reference types**. What does this mean? A **value type** “is a type whose value is *copied* when it’s assigned to a variable or constant, or when it’s passed to a function.” On the other hand, **reference types** “are *not copied* when they are assigned to a variable or constant, or when they are passed to a function. Rather than a copy, a reference to the same existing instance is used.” To see what this means, let us look at the following example.

```swift
var songA = Song(name: "Lucky You", author: "Eminem")
var songB = songA
songB.name = "Walk on Water"
print(songA.name) // prints "Walk on Water"
print(songB.name) // prints "Walk on Water"
```

Using the **Song** class that we declared before, we create an object of type **Song** and assign variable `songA` to that **Song** object. Next, we create another variable `songB` and assign its value to be `songA`. Then, we set the `name` field of `songB` to be “Walk on Water” (previously was “Lucky You”). Lastly, we **print** the value of `songA`’s `name` field and the value of `songB`’s `name` field. In both cases, “Walk on Water” gets printed.

Why does this happen? Well, because Song is a **class** and we know that classes are **reference types**, when we created our new Song object and assigned that to `songA`, what really happened is that `songA`’s value was a **pointer** to that Song object. Then, when we assigned `songA` to `songB`, what we were doing was assigning `songB` that exact **same pointer**. Thus, when I changed the value of `songB`’s name field, we actually altered the object that both `songA` and `songB` were pointing to, and thus the value of `songA`’s name field changed as well.

If instead Song was a **struct**, we would see something else happen:

```swift
struct Song { ... }
var songA = Song(name: "Lucky You", author: "Eminem")
var songB = songA
songB.name = "Walk on Water"
print(songA.name) // prints “Lucky You”
print(songB.name) // prints "Walk on Water"
```

Looking at the example above, we see that printing out `songA`’s `name` prints out “Lucky You” and printing out `songB`’s `name` prints out “Walk on Water” (unlike the previous case where they both printed out “Walk on Water”). Why did this happen? Well, remember that structs are **value types**. Thus, when `songA` was assigned to `songB`, a copy of the Song object that `songA` was pointing to was passed to `songB` (unlike the previous case where the pointer to the exact same Song object was passed to `songB`). Thus, when we changed `songB`’s name field, `songA`’s name field was not changed because `songA` and `songB` are pointing to two different Song objects.

#### Optionals

In Swift, we also have a type that you may not often see in other programming languages, **optionals**. Optional types just mean that a variable may hold some value or it may not (i.e. it is `nil`). For example, let's consider a situation where we want to look at assignment grades for a student.&#x20;

```swift
var grade1: Int
var grade2: Int
var grade3: Int
```

What if the TA hasn't graded assignment 3 for the student yet? How do we represent that `grade3` might not actually have an integer value? Well, this is where optionals come in.&#x20;

```swift
var grade1: Int?
var grade2: Int?
var grade3: Int?

grade1 = 10
grade3 = 9
// grade2 = nil
```

By making this change, we have redeclared `grade1`, `grade2`, and `grade3` to be variables of an optional **Int** type so that it is possible for any of these variables to actually be nil, for the case when the TA has not yet provided a grade. In the example above, after the TA provides grades to assignment 1 and assignment 3, `grade1` and `grade2` will now have integer values. However, `grade3` will still hold a `nil` value.&#x20;

Now suppose we want to print out the grades for the student.&#x20;

```swift
print(grade1) // 10
print(grade2) // Error: value of optional type ‘Int?
print(grade3) // 9
```

Trying to print `grade2` will cause an error because `grade2` could potentially be `nil`. In order to actually use this variable, we have to first **unwrap** the value inside the variable and check if it actualyl has a value. There are two main ways to unwrap a variable: using an `if-let` statement and using an `guard-let` statement. First, let's take a look at unwrapping using an if-let statement:

```swift
if let unwrappedGrade2 = grade2 {
    // this block gets run if variable a holds a value
    print(grade2)
} else {
    print("grade2 contains no value!")
}
```

The syntax for an `if-let` statement is `if let [unwrapped constant name] = [optional variable] { … } else { … }`. In our example above, we take optional variable `grade2` and then we try to unwrap it. If `grade2` actually does hold some value, then that value gets assigned to the constant `unwrappedGrade2` and then we enter the first block of code. If, however, `grade2` was `nil`, the second block would get run.

Another way that you can unwrap a value is using guard-let.&#x20;

```swift
guard let unwrappedGrade2 = grade2 else {
    // this block gets run if variable a was nil
    // in here, you should return or throw an error
    print("grade2 contains no value!")
    return
}
// this gets run if variable a holds some value
print(unwrappedGrade2)
```

The syntax for a `guard-let` statement is `guard let [unwrapped constant name] = [optional variable] else {…}`. In our example above, we take optional variable `grade2` and then we try to unwrap it. If `grade2` actually does hold some value, then the rest of our code runs under the assumption that the new `unwrappedGrade2` holds that value and `grade2` is still an optional. If, however, `grade2` was nil, the else block will get run. One thing to take note when using `guard-let` statements is that in the else-block, you **must** either return or throw some error at the end of it. This aspect is what distinguishes it from an `if-let`.&#x20;

We often use `guard-let` statements more for cases where you want to assume an optional variable is non-nil for that portion of the code, and if not, then we want to exit or throw the proper error. `if-let` statements are better for cases where either `nil` or a real value is fine, we just need separate cases to handle each one.
