Practice English Speaking&Listening with: Developing iOS 10 Apps with Swift - 3 More Swift and the Foundation Framework

Normal
(0)
Difficulty: 0

[MUSIC]

Stanford University. Welcome to Stanford CS193P,

this is Developing Applications for iOS,

winter of 2017. This is the only lecture in this quarter

where I'm not going to do a demo, so this is all slides,

and that's because I'm pretty much going to try and

get you fully up to speed on Swift. Everything that I'm

going to talk about today is covered either in your reading

assignment one, which was due today, so hopefully you're

done with that, or it's in reading assignment two,

which is going out today and is due next Wednesday. So,

why am I even covering this? Because I know that reading

through that reading assignment can be a big slog

through a lot of information, and I want you to understand

the things in there that are really important. As I go

through the slides today, if you see something and

I explain it and you're like, my gosh I didn't get that,

just make a note about whatever the topic is that I'm

talking about and then you can go back and

read about it again in your reading assignment to try and

understand it. If you still don't understand it,

you can of course ask on the class forums.

You can think of this as kind of the highlights of the fist

two reading assignments. Some of these are also highlights

of the first two lectures I did in the demos,

so there's a little bit of that in there to.

But, this is really kind of the important stuff in Swift,

that I can teach you at this point.

There's more important stuff in Swift to come, okay,

but I'll teaching it kinda as we go in the next two weeks.

Okay, so lot of Swift topics,

let's start with the first one, probably everybody's

favorite topic when they first learn Swift,

which is optional. Optional is interesting in Swift,

because not a lot of other languages have optional, so

I'm sure, in fact I've heard, that some of you are like,

"Hmm, I'm not sure I really understand that optional

thing". And that's probably okay, but by the end of next

week you should feel very confident with Optionals,

because you're gonna see that they are absolutely everywhere

in iOS. Now, I mentioned this in the lecture but

I wanted to show it to you from a code,

kind of a code point of view, which is that optional

is nothing more than an enum, it is fact just an enum,

this is the enum that is an optional. It's a generic type,

kind of like array, how with array when you say the type,

you say the type of the thing you're putting in the array.

You should all be familiar to that, with that from Java for

example, same thing in Swift.

So, with optional it is the same way,

you put this type and the type that's associated there, or

not that's associated, but

the type of the generic type that we're talking about,

that "T" in an optional,

is just the type that's going to be the associated value.

When you look at this enum Optional,

it only has two cases: "none" which is "not set," and

"some" which is "set". When it's in the some case, look:

"(T)", you know what that is from the calculator demo,

that's an associated value, just like when we had

operation in calculator it had associated values, like unary

operation had an associative value of a function, and

constant had an associated value of the constant's value.

Same thing here, with optional, in the "some" case,

the "set" case, it just has an associated value, and

it's whatever type the option was, so

if this is an optional string, then it would be a string.

Now what makes optional like, " I don't really get optional,

what is it?", it's because of all those question marks and

exclamation points. But, all those question marks and

exclamation points, are just sugar,

syntactic sugar, to make your code look a little simpler and

straight forward, because it's so common to use them. So,

I'm going to map this enum to that sugar.

Let's take a look, here's the first one: If I say let x:

String?=nil, that's exactly the same as

saying let x = Optional.none,

just like by saying array, I'd say

Array that would mean I want an array of String,

here when I say Optional , that means I want

an Optional String. And I'm picking the none case, and

in just the same way, if I say let x = Optional=

hello, I'm just saying x = Optional.some

with associated value hello. Everyone got that? That's all

that's happening there with the question mark thing.

And then here is the unwrap. When we do that exclamation

point all we're doing is doing the switch to get things out

of an optional, so we're switching on the optional,

and it's in the "Some" case, then we're going to grab that

associated value just like we did in the calculator, and

we say "let function" or "let value" to grab the associated

value, we're saying "let value" here and

it's grabbing that value that's associated with it.

If it's in case none, where it's not set,

then it raises an exception and crashes your program,

we haven't talked about how to do that, it's quite easy, but

that's what happens here,

that's all exclamation point is, it's basically a switch.

And then finally, If we do the "if let",

"if let" is also just a switch, but

in the none case of an if let, we don't raise an exception,

we just break, break out of the switch, do nothing. Okay,

does that help you a little bit understand what optional

is? Optional is a type, it's an enum, it's just like any

other type, it just has this interesting behavior, and

it's got all the question marks and

exclamation points to make all the code look a little

simpler. Now, there's even other stuff about optionals

that are interesting. Optionals can be chained.

Now what does this mean? Well, this is best shown by example.

So, let's say I have a Optional UILabel like my

display in the calculator and it's got the text, that's also

an optional, Optional String, we all know that. And

let's say we want to get the hashValue which is just a var

on string, which hashes the string, gives you some integer

for it, I want to get that hashValue of what's in

the display. So then I would probably do some code that

looks like this, this is probably similar code to what

we have in our calculator where I've got my display,

that's my IBOutlet probably that display UILabel?, and

I'm going go do "if let" here, because I don't want to crash

so I don't want to do exclamation points,

I'm going to do "if let", so I'm going to say "if let

some temporary value equals to the display" (now temp1 is

the UILabel), and then I say, "if let temp2 = temp1.text",

I'm sending text to the UILabel and

now I'm getting back a String, not an Optional String, but

a String, because I did "if let", then I can finally say,

then "let x = temp2", which is the String,

the hashValue. Okay, this is a lot of code to have to type to

just get that dang hashValue, out of that UILabel's text.

With optional chaining, this same code looks like this,

the first line of those two lines.

"If let x = display?.text?.hashValue,

then do something with x". In that case of course, x will

be a non-optional, because I'm doing if let on it.

If I take the "if" off, and just do "let x =" all that,

then x will be an optional Int. Now, how is this working?

What's happening is that every time that you have one of

those question marks after an Optional, it's saying,

if this is in the set case, then grab it and keep on

going, send the next thing. If it's in the nil case, then

just return nil for this whole expression, this entire line,

boom, it's just gonna return nil. If I'm if letting it,

then obviously the code won't get executed.

You can do as many of these as you want in a row, and

we do this all the time, this optional chaining is going to

be all over your code, and it makes perfect sense because

again, we're using this question mark and exclamation

point. Here we happen to use the question mark when we're

accessing it versus when we're declaring it. That's what it

means to use a question mark when you're accessing it,

it means go get it, and if it's not set,

then just return nil from this whole expression,

it will just bail out of the whole thing,

It will never even execute hash value because we'll never

get down to that end of it, if any of these things are nil.

Another cool optional things we can do is optional

defaulting. So what if we had wanted to put a string in our

UI label like in our display, but we know that if that

string is nil, we don't want to put nil in there because

what'll happen to our label if we put nil in as the text?

It'll collapse down, right, probably most of you saw that.

You have to put something in there,

at least a space. So let's say that I want to do that,

I want to put space in there if it's nil. This is the code

that it would look like here: I'd have my string, I would

say if the string is not nil, then put it in the display,

otherwise, if it is nil, put space in there. This looks

a lot cleaner with optional defaulting, which looks like

this, display.text = s That means if s is nil, use

this other thing. It's like the default in case s is nil.

We will use this all the time as well. Everybody got that?

Just optional defaulting. Alright, so I bring those out

of the optional world just to highlight them,

because there's a lot in the reading that you're doing

about optional, but these are kind of the highlights.

There are a couple more things actually I'll show you later,

but basically that's it for optionals. Alright, tuples.

So I had you skip tuples in reading assignment one, but

you'll be reading about them in reading assignment two.

What is a tuple?

A tuple is super simple, it's just a grouping of values,

and you can use it anywhere you're using a type. What does

a tuple look like? It looks like this. This var here,

this constant, actually x, I'm setting its type to be a tuple

with a string and int and a w, that's its type. A tuple

can have any number of things in there, but realistically,

we probably only have three or four, sometime only two, but

it can have any number. I can set x equal to parentheses,

those three, any value of those three types. So here,

I've set it to hello, 5, and 0.85.

Now I can get the values out into individual variables by

saying let parentheses three different variable names equal

x. And now it will pull out the three different values

into the three separate variables, word, number, and

value. So it's kind of mirror image there,

you can kinda go either, either direction,

putting things in or out. We actually, believe it or not,

don't do it that way most of the time,

because it is also possible to name the elements of a tuple.

So here, I define x, same thing, string int double, but

look, I've named each of them,

I called the string part w, I called the int part i, and

I called the double part v for some reason. Now, I still set

it equal in exactly the same way, no difference there. But

now I don't need to pull it out into separate variables.

I can just say x.w and get the w, the first component of it.

You see that? This is how we do tuples, with names.

I strongly recommend you almost always use

names with tuples. It's just a little easier to read,

clearer to say what your intent is as a programmer.

Because those names

of the parts of the tuple can have good variable names.

You're gonna see in your programming assignment number

2, I'm gonna have you write a function that returns a tuple,

and it's going to specify the names of the parts. Now even

if you name them, like we have x with the named ones,

you can still do that thing where you just say, let (word,

num, val) equal x, and it'll still pull it out into

individual ones, so naming them doesn't stop you from

pulling them out by individual variable, if you want.

Also, in tuples, you can always put underbar for

any of the names, like here I could say let word_ val or

let word,_, val equal x, and then I would get word and

val into individual variables, and I would just ignore that

middle one. Underbar in Swift always kinda means ignore

that, I'm not interested in that particular thing.

We've already seen this with function parameters when we

want to ignore the external name of a function parameter.

Alright, so using tuples that return values,

like I said, you're gonna see this in the homework.

Nothing special here. It's a type like any other type, so

it can be the return type of a function. So, this is how you

can have a function that returns multiple values.

In some languages, it's very difficult to do this.

You have to create a structure or something to return.

However, it's very, very, very easy in Swift.

You literally just do this. And

when you get the value that comes back from that function,

you just access the elements by name. Notice that when I

returned it in my code there in getSize, I didn't have to

give the names; I could if I wanted to,

I could have said return weight:150, height:, but

I decided, eh, I'm just gonna return the values. Okay,

another thing: range, range is an important little

struct in Swift: all that it represents is two end points.

So a range is useful for, for example, a selection of text,

where the selection starts and where the selection ends.

It's also good for a sub-slice of an array. If you've got

array of 100 elements, you might want the 15th to

the 40th one, so you could specify that range, 15 to 40.

So range is this really simple little struct, which kind of

looks like this. I say kind of, because it's a little more

complicated than this, but it basically looks like this.

It's a generic type like array because of course, you can

have a range of ints. You could have a range of floats.

You could have a range of strings even. Okay, so

that T right there could be float, float, int,

string. T is restricted a little bit, and I haven't

really talked about how you restrict a generic type.

But that T is restricted,

and it has to be what's called comparable. That's because

range needs to make sure that the start index is less than

the end index. That's part of what a range is defined to be.

So that T has to be something that can be compared

to see if the start index is less than the end index,

minor thing there. So, for example, a range of int

would be great for specifying a range in an array,

cuz an array is indexed by integers, right, starting at 0

and going up to the number of things in the array.

Now there are other more powerful, more capable ranges,

like CountableRange. A CountableRange is

just like a range, except for that you can count through

intermediate values between the start and the end.

Okay, it's like a range of ints. A CountableRange means

the begin point and end point and one point each.

Now as you stride through that range, it depends on what

the type is. Striding through a range of ints is different

then striding through a range of floats, or striding through

a range of strings. There's a little difference there, and

we'll talk about that in a minute.

There's a special syntax for

doing range, which is "dot dot less-than" or "dot dot dot".

Dot Dot Less-than means that you put the start index and

the end index on either side of the dot dot less than.

And that means go from the start index to the end index,

but don't include the end index, not inclusive of it,

and the dot dot dot includes both ends. So for

example, in an array, let's have an array of four strings,

a, b, c, d, and let's say that I want to get the c and

the d out of there, I can say array sub, ( just

like how I can say array sub 5 or array sub 3 is the fourth

index of the array), I can also specify a range and

get a sub array, a slice of the array, it's called. So

I can say 2...3, which means index 2 in the array,

which is c because a is index 0, b is index 1, c is index 2,

dot dot dot index 3, which is the d inclusive, cuz it's dot

dot dot. And then the less than 1 would be exclusive,

so that's why the d wouldn't be included in that one. So

see how I'm using a range to get a sub slice of an array,

that's kind of cool. By the way,

if you say give me the array from 6...8,

that's going to crash at run time with an array index out

of bounds because this array only has four elements. So

just because I'm accessing this subscripting with a range

instead of with a number, it still has to be in bounds.

And then if I say array[4...1],

that also will crash at run time, because the range

is going to look at that and say I can't create a range

where the start value is greater than the end value,

can't be a backwards range, that's why that type like

int has to be comparable, of course you can compare ints.

One thing very important to understand: a string,

a subrange of a string is not a range of ints.

You might think it is, right, I've got this string,

100 characters, you might think strings sub 15 to 40

would be the 15th character to the 40th. And

it's not: a string subrange is a range of string.index,

which is a different little data type, and

I'm going to talk all about that in a few slides.

But I just want to make it really clear,

that it is possible to say string subrange start..<end,

but start and end are not ints, they're string.indexes,

and we'll see how that works. If the type

of the range that you create with dot dot less than or

dot dot dot, if that type is an int, (actually,

if it's strideable by int, they can be strided by int so

it's not gonna be float, but I'm not really prepared to

talk to you about strideable), but if the range has

ints on either end, so it's a range from 2 to 7, for

example, then it automatically creates that countable range,

that more capable range.

That range then becomes what's called a sequence, And

sequences can be iterated through or enumerated, and

the way you do that is with "for in", so Swift's for

statement, this is the only one there is. It's called

"for in" and all it ever means is, I want to go and enumerate

all the values of a sequence. I'm going to talk about what

things that can be sequenced. Countable range is 1,

because if an int goes from 0 to 7, and

it's a countable range, then it can go 0, 1, 2, 3, 4, 5, 6,

7. Arrays are sequences, sequences of their elements.

So you can "for in" through an array. Dictionaries are also,

and we'll see that a little later. So here's how you do

a normal C-like for loop, for (i = 0; i < 20; i++).

You cannot do that in Swift, that syntax simply doesn't

exist. Instead you would say for i in the range 0..<20,

because notice I said it's less than 20, not less than or

equal to 20, so 0..<20 means go through that. And so

that little block of code is going to be executed once for

0, 1, 2, 3, 4, all the way up to number 19, so

that's same thing as what you see there.

Now what about floats? Floats are a little weird.

What if I wanted to do for{i = 0.5; i <= 15.25; i += 0.}.

Whoa, how am I gonna do that? I can't, for

example, say for i in 0.5...15.25.

How does it know to go by 0.3? And the answer is, it doesn't.

In fact, a range like that, 0.5...15.25 is not a countable

range, it's just range. It only knows the start and end,

it knows nothing about what's in between, so

it cannot be a sequence, it can't be for in over. But

luckily, there's this great global function called stride.

Stride takes a from and a to, or a through,

(depending whether you wanna go through to the end,

or just to to and not including it), and

a by, which is, what it's going to step by.

So here, I say stride from 0.5 through 15.25,

because I want less than or equal to, by 0.3, and

that's gonna create a new object, it's a CountableRange.

Now it's a special CountableRange, it knows

how to count from 0.25 to 15.25 by that 0.3 step. You

don't need to worry about how it implements it, Stride just

creates you a CountableRange. Actually this will be called

a ClosedCountableRange because it counts through to the end,

so it's a dot dot dot kind of range of a dot dot

less than kind of range. So I have a CountableRange, and

it's a sequence, so I can for in it, so I say for i in.

Stride, I'd probably say for f in, or even better than f or

i. A lot of times, by the way, on my slides, I'm gonna use

variables like i or x or d because I want it to fit on my

slide, I don't want it to be wrapping. It's hard for you to

read the slide if the code's always wrapping around, so

just because you see me using i and d and f doesn't mean

that's license to have those kind of terrible names for

your variables. You need to have meaningful names. So

that's how for in works here,

because stride is gonna return a CountableRange,

ClosedCountableRange in this case. So

that's how you do your standard for loops from C.

Alright, let's talk about the data structures in Swift.

You've already learned about three of the four of them,

which are classes, structures, and enums. In our lecture,

we already did all three of those things.

We had a class, which is our view controller subclass.

We had a struct, which is our calculator brain.

And we had enum, which was our operation.

The fourth one is protocols, and

I'm not gonna talk about that until next week or

even the week after. Protocols are super, duper important,

I don't want to make it sound like they're not important,

But they're new to a lot of you, and so I'm gonna try and

ease you in with these ones that are more familiar,

although different in Swift probably than what you're used

to, they're still more familiar to you.

Let's just review quickly these three structs and what's

the same and different about them. So what's the same?

They're declared very,

very similar: they have different key word, but

they're almost exactly the same.

The only difference really is a class can specify a super

class, otherwise they're declared exactly the same.

They can all have properties and functions, So,

they're all very similar in that way. The only thing here

is that there cannot be any stored properties in an enum.

Enum keeps any data it has in associated values, so it can't

have any stored properties, but it can have computed

properties and they certainly all can have functions.

Another thing that's very similar is they can all

have initializers except enums. Enums don't need

an initializer cuz you just say the case you want, but

structs and classes have initializers. Okay, so

that's the same. Now what are the differences?

Well of course, inheritance is a big difference for classes.

Classes have inheritance. Structs and enums do not. But

the most important difference, which I mentioned last time,

is that structs and enums are value types, and

classes are reference types. So let's go into that and talk

about it just a little more. It's so important, I'm gonna

talk about it again. A value type, what does that mean?

It means that it's copied when you pass it as an argument

It's copied, even if you just assign it to another variable,

to a function.

it gets copied. If you assign it to a let, it's immutable,

that's very important to understand. If you assigned

a value type to a let, using let x equal that thing,

you just made it immutable, No matter how complicated it is.

If it's an array or dictionary,

you can't add any elements. If it's a calculatorBrain,

it means you can't call any of its mutable functions, So

you can't do perform operation on it. Now in assignment two,

I'm gonna have you add a method to the calculator brain

that is gonna let you use the calculator brain when it's

immutable, which is kinda cool. You still wouldn't be

able to perform operation but you can be able to something

very important, immutably. Now because of this, this kind of

copyright-on-write behavior of value types, you must,

of course, mark all the functions that are going to

modify it as mutating. And that's how the Swift knows,

"Oops, I've gotta make a copy of this, an actual real copy,

if someone writes to it". Now a reference class is pretty

different in that it gets stored in the heap somewhere

with a pointer to it, and when you pass it around to

a function or to assign it to another variable or something

like that, you're just passing a pointer around to it.

Now, by the way, when you say, let x equal a reference type,

you can still send it messages that will mutate it.

All you're saying is the pointer can't change, but

what it points to can always be changed.

Now reference types are what you're used to.

Most languages that have object-oriented reference

types. Reference types are a little bit Wild West- I

don't have time to teach you this, I hope you'll get to see

this sometime in your career at Stanford, but

there is a different way of thinking about programming

than you're used to: it's called functional programming.

How many people have heard the phrase,

functional programming? So about half of you. The idea

of functional programming is: you don't want this Wild West

where you've got these objects with multiple people pointing

at them, any of whom could modify it at any time.

That leaves you open to a lot of difficulty in verifying

the correctness of your program.

Whereas if you have a lot of objects that are immutable,

you know they can't change, and their APIs are basically

like mathematical functions where data goes in and

predictable data comes out, because there's

not all this side-effecting, data-effecting other objects

that someone else is pointing to in all this.

It's this really well-contained little thing.

Now iOS was not developed with functional programming in mind

at all. But the people who invented Swift,

they were thinking about functional programming, So

you can kind of mix a lot of the elements of

functional programming into your application,

if you're building an iOS application. Now that's a new

frontier in iOS, because for however long, 20 years,

really, or 30 years, really, if you consider all the way

back to the invention of the technology that led to iOS,

people have been programming with basically

reference types only, for their object-orienting.

But when you do this programming with structs and

enums, and especially when you throw in protocols, (which I

told you I was gonna tell you that are very important, but

I cannot explain to you yet, and generics),

when you start throwing those things all in there, you can

really do a good job of doing real functional programming.

All of the Swift foundation is really designed with a lot

of functional programming in mind. If you ever really wanna

kind of see a good example of how to apply this immutability

and generics, and protocols and all that stuff to build

an architecture, chase down all the things that

are going on in the foundation library: string and range and

all these things. Remember, that I said things like

the range is a sequence, or this thing is comparable,

remember how I said things like that? Okay, well,

how do you express that? You use protocols,

with these immutable types, that can be immutable and

use generics. So I can't explain all that,

I've already spent too much time on it than I have to even

talk about it in the lecture today, but just so

you know, there is a huge advantage of programming in

a different way; it requires a real mindset change.

So hopefully, you'll take a class where maybe the whole

class is functional programming,

and really you'll get a feel for it.

Swift does a good job of supporting for

the fundamentals you need to do that. That's kind

of the long-winded answer to which do you choose. If you're

doing more of a functional approach, even if you're doing

a reference-based approach like what you're used to, try

to lean towards immutability, try to ask yourself,

can this thing work and be immutable? Is there some

functionality in my program that I could share by creating

a generic, for example. At least those leanings

might help you build the apps that are more testable,

because it's a lot easier to write a test for

something that's like a mathematical function where

you know the data out is supposed to be the same for

the data in, than it is for something where there's

a lot of data that you have to set everything up. Set this,

set this and this and this, and now call the method,

that's a lot more difficult to write test cases for, etc.

So that's value and reference. Let's talk a little bit about

the syntax of methods. I'm gonna go fast on this.

Hopefully, you all understand this.

All parameter names have external names and internal

names. The internal name is used inside the definition, or

the inside the implementation of the function.

So here I have these two functions, foo and bar. Bar

calls foo. So you can see that inside foo's implementation,

it is using the first and the second, whereas bar,

when bar calls foo, it uses external first and

external second, as the names of the items. And you know

that you can put an under bar to make it so there's no

external name. We only do that 99.99% of the time with

the first item. Why do we do it? Because sometimes the name

of the method, and/or the type of that first argument, is

enough to make it clear what that thing is supposed to be,

so we don't need to put an external name.

It's kinda clear. All the other parameters,

we don't have the advantage of having the name of the method

there. So that's why we almost never put underbar for

the later ones. By the way, if you only put one

parameter name, then that's both the external name and

the internal name, and that's not that uncommon,

you'll do that occasionally. All right, so you know all

that. When it comes to doing overriding, subclassing, in

reference types and classes, when you override, you have to

explicitly let Swift know that you know you're doing that.

And you do that by putting the override keyword.

So if you override a method from your superclass you have

to say override func whatever. You can mark a method or

even a whole class final, and that means that it cannot be

overridden, subclasses will not be allowed to override it.

Most languages have that. Now on the topic of methods.

You've seen, actually you've seen both, but mostly seen and

understood instance methods. These are methods,

or vars, that are being sent to an instance of the class

struct or enum. In other words, one of them.

Like I create one of them: I create a double of 15.5,

I have one, and I can send it messages.

But types, like the type double, the type strength,

the type calculator brain, they can also have methods and

vars. Computed vars, no storage, but computed vars.

All you do to add a method or a var to a type is

you put static in front of the declaration.

So "static func whatever" means this is a function on

the type, not on instances of the type, on the type itself.

For example, let's think about double here.

Double actually has quite a few static or type methods and

vars. You access them by sending the message to

Double to the actual word, capital D-O-U-B-L-E. You

don't send it to an instance, you send it to that word. And

you've already seen at least one of these, which was pi.

Remember we said Double.pi and we got the value of pi?

Pi is a var, a computed var, on the class or

struct actually, double, but it also has other methods,

like abs. Abs takes a double value and

returns the absolute value of it. That is on the type.

You say Double.abs, Double.pi. As opposed to, for example,

if I have a double like x is equal 23.85.

So x is now a double. I can't say x Double.pi cause

x is an instance of a double. You see the difference?

We see saying x.pi, trying to send pi

to an instance versus sending pi to a type double.

So what do we use these type methods for?

Well, we can't access any instance variables because

we're not sending them to an instance.

We mostly use them for utility methods, things like that.

Constants like pi is a good example. Things that

kind of are functions that are associated with this type but

don't belong to a particular instance or

wouldn't really operate on an instance. Now for example,

you might have an instance method or

even an instance var called abs, A-B-S, with no arguments,

That you would send to an instance, and it would take

the absolute value of the thing you sent it to. But

of course the type one has to have an argument because

you're sending it to the type double,

so there's no double involved.

There's no instance of a double involved. Everybody got

that? Alright: properties. You know all about properties.

We saw computed properties like display value in

our calculator. There's actually some really cool

features on properties. One of the most interesting ones is

property observers. What is a property observer?

A property observer is a little piece of code that

will get executed when your property changes.

Anytime your property changes just a little piece of code

can get executed. Now you can actually find out

just before your property changes. Or

you can find out just after your property changes.

Or both. And the way you do this, and this works for

your stored properties, like userIs InTheMiddleOfTyping:

we could put a property observer on there, and

execute some code every time we change that. It also works

for inherited properties, so if you inherit something

from your superclass, you can put these properties in and

notice that it changed. By the way, if you have a property

which is a value type, (a struct or

something, like an array or an dictionary), this property

observer stuff will happen if that thing gets changed,

if it gets mutated. So if you add something to the array,

boom, the Property Observer will kick in and say,

"that changed". How do these Property Observers

work? They look a lot like a computed property. Remember

that the computed property displayValue had get and

then we had some code, And then we had set and

we had some code? This is similar except for

get and set it's will set, or did set.

By the way, you probably would never (I don't even know if

you can) use this in a computed property because

you've got the set clause there so

you can just put it right in set.

You don't need to find out when it's set because you set

it. But for stored properties and inherited properties,

that make sense, so you have willSet.

Now, willSet, first of all, you put it all in a curly

brace after the property just like if you were doing

a computed property but, this is not a computed property,

just adding a curly brace doesn't make it a computed

property, you have to put get or set in there, but,

if I put willSet, then, inside that code,

there's a special variable just like there in the set

case of computer property, called newValue, and

that is the value that that thing is going to be set to.

It's not set yet. Some property,

see some stored property up there? It has not yet

been set to newValue but it's going to be. And then didSet,

that code occurs after some property has been set and

the special variable in there is oldValue.

That's the value it used to have before it got set. So

you can compare if they've changed, for

example. So where do we use these things?

Probably the number one place that we use them is in our

Controller in view. Let's say I'm a button and

my background color changes. I inherit my background color

from my super class, UI view. Up the chain of super classes.

Every time the background color changes,

the button wants to redraw itself so

it will have var background color is a UI color,

open curly brace, didSet open curly brace

draw myself closed curly brace. Question? Okay,

so the question is, if someone changes some stored property

there, am I responsible for doing something about that

in willSet or didSet? Do I have to actually set it? And

the answer is no. Okay, that's being set somewhere else.

You're just getting a chance to run some other code that

you wanna run just before and just after it happens.

But you're not responsible for setting the actual value.

That's done for you. That's why you get to

see the old value and the new value in the two of them.

So we'll see this next week when we start drawing on

screen, where we're gonna be watching properties change so

we can cause ourselves to redraw. Next, lazy properties.

Lazy initialization is a really powerful tool.

It's gonna get you out of a lot of binds in this class.

What does it mean? A lazy var, a var

that you say lazy in front of, whatever it's set equal to,

that equals doesn't actually happen until someone accesses

that var. Until someone asks for the value of that var,

it doesn't actually do the initialization there.

It doesn't do that equal something.

So it's lazy. It's waiting.

Now why do you wanna be lazy? Well, one obvious reason

is like here, lazy var brain equals calculator

brain, what if calculator brain was really expensive to

create. What if it opened a network connection because

we're going to share the calculation with the internet

or something, you know what I mean,

do something that is expensive.

Well, you wouldn't want to do it,

unless someone actually tried to access the brain,

called set up operand on it or something. Then you would

want to actually do the work to create it.

Okay so one reason to be lazy,

it's not that important of a reason it turns out, but

one is to delay expensive operations. But

what's another reason to do it? Well, in Swift,

all vars have to be initialized. Remember that?

Remember we added userIsInTheMiddleOfTyping.

And we didn't say, equals false. And we got an error.

It said we had no init, because we hadn't initialized

that. Not only did they all have to be initialized, but

they all had to be initialized before you could even send

a message to that class, even internally. So

you can't invoke any of your own methods until you fully

initialize yourself. What if one of the things you want to

initialize needs to call a method on yourself? It's

impossible. Because if you need to initialize something

to be allowed to send messages to yourself and you need

to send a message to yourself to initialize something,

it's a deadlock. You can't do it. Okay, well lazy let's you

do it. Because you can say for example, the last one there;

lazy my property equals some method on myself. This is not

going to be executed until someone says my property and

no one's allowed to access my property until I'm fully

initialized. So by definition there's no way

that that is gonna try to get initialized until I'm already

fully initialized. And yet this lazy thing counts as this

thing having been initialized. So this is the big loophole.

Lazy var myProperty counts as having been initialized

even though it really hasn't yet. Because it's waiting for

something to actually access myProperty. But it counts for

the purposes of that rule, so now someone comes along later

and accesses it, now we can call this method. So

do you see how deferring the calling of this method in

order to initialize this gets us around that requirement

that everything be initialized?

It's really tricky. And then the middle one there,

someProperty, that's super tricky. Because you can

actually have a closure, (remember what a closure is,

right from calculator brain, it's just a function,

in line function), you can actually have a closure

to initialize your thing lazily. All you do is you

put the closure, open curly brace, close curly brace.

It obviously has to return something of the type

of that bar. And then just put the little open parenthesis,

close parenthesis at the end. When we open parenthesis and

close parenthesis at the end of the closure,

that means execute this closure right now. But

it's not gonna execute right now, it's gonna act lazy so

it's gonna happen later. And that means that that closure

inside could reference self. Because self will be fully

initialized by the time this closure gets executed,

since it's lazily executed. So

lazy will get you out of some of these tricky wickets,

because when you see me talk about initialization,

you're gonna be like, "I don't want to do that, ever".

You're going to try and avoid it, and

this is a good way to avoid it. So yeah,

it still satisfies all those things. Alright, on to Array.

Everybody knows what an array is. Everyone knows what

a generic array is. You just, when you declare the array,

you have to say what type of things are gonna

be in the array. There's a different syntax though,

which I didn't introduce when I did dictionary in the demo.

But you can declare an array, those two yellow things

up there are exactly the same thing. So,

open square bracket,

string close square bracket is exactly the same as saying

array angle bracket string. It's just kind of a special

way to declare an array and it actually seems to be

the preferred way. I actually prefer the other way because

it's a little clearer to you that are learning that this is

an array, because it says the word array and string.

But open square bracket, close square bracket,

we know that's going to be index into an array so

it looks kind of array-ish but

just get used to it. [String] means an array of string.

It's the declaration of the S and the name of that

type array of string. So if I had a string right here like

this giraffe, cow, doggie, and bird. Four animals in here,

four strings and I said animals dot append ostrich,

well append appends something onto the array, now the thing

you are appending has to be the same type obviously

as the type of everything in the array, however the type

was declared. Notice that animals is in inferred.

By Swift, to be an array of string. Because Swift sees

that you sent it to an array of things and

it looked at all the things and they were all strings.

So it said, the animals must be an array of string. Now,

this line of code animals.append("Ostrich").

That's very bad.

Can anyone tell me why that's not gonna work?

Yeah? >> That's exactly right.

We define this animal's variable with let, so

it's immutable. So when we say append an ostrich onto

an immutable thing, it's going to crash my program.

But actually, it won't even crash my program.

It won't even compile.

Like, Swift compiler's just gonna say, no way,

you can't do append of something or other.

So that's a good one over there, you got that.

How about this one? I'll give you a second chance for

everyone. Why is this one no good? Okay,

I'm trying to get animal[4] over there, why? Nobody?

This one's easier. Array index, yes! Array index is

out of bounds because arrays are indexed starting at zero.

Okay, so giraffe, cow, doggie, bird that's zero, one, two and

three. So if I say, give me array number four, bam,

crashed my program array index out of bounds.

Let's talk about the fact that array is a sequence.

Array is actually a collection and collections are sequences.

And a sequence means I can do for in on it. So if I say for

animal in animals, my little for loop will get executed

four times, once with animal being giraffe, next one with

animal being cow, next one with animal being doggie,

next one animal being bird. Okay, so that's a really cool

feature. Remember this is the only four there is in swift.

For in, that's the only for there is, nothing else.

So array in a lot of classes instructs

in iOS have some interesting methods

that have arguments that are closures. So I teach closures

to you right at the beginning of the of the quarter.

And why do I do that? Because closures are an important

thing to understand if you want to really use iOS API

well. So let's take at this (just so we can learn a little

bit about how closures can make our API great,

especially again if you're doing functional programming,

closures can be really good), but why are closures so great?

So let's look at this so, this first function right here

called filter is an array method.

Nothing special about it, it's just funk and array.

It has one argument, which is called includeElement.

And that argument is a function. It's a function that

takes one argument which is of the same type of the things in

the arrays, cuz it's a t. So I have an array angle bracket t.

It's a generic type so this function is declared in that

generic type so the t means the same t, the same type. So

if I have an array of strings this filter expects this

to be a function that takes a string. As its only argument.

And it returns a Bool, so that's the argument.

The argument is a function that takes a string and

returns a Bool or takes a T, whatever that is, and

returns a Bool. And then what's the return

value of this filter thing? It's an array of T, so another

array with the same kind of elements. So what does filter

do? Filter takes every single element In the array that

you're sending it to and it runs that little function. And

if that function returns true, it includes it in the array it

returns. If it returns false it doesn't.

It throws it out. So

it's a filter: it's filtering your array and creating a new

array with all the things you don't want as defined by this

function that you're providing as an argument.

With all the things you don't want thrown out. So for

example here, I have this var that I'm creating,

bigNumbers, and I'm creating an array on the fly 2,

47,118,5,9, (see? I created an array), and look,

I'm sending it a message right away. Yeah, I didn't have to

put it into another var, by the way, I could have but,

I just want all be on one line here. I created this array and

I'm sending it the message filter and

look what I'm providing for the argument there.

That include element it has an underbar, so, you don't have

to actually put the include element column in there. So,

what am I putting in there? That's a closure. So

that means, it's a function. Now, Swift knows that this is

a function that returns a bool. So

I don't have to put the word return in there. I can use

dollar zero to be the one and only argument to the function.

And I'm just going to check and

see if dollar zero is greater than 20, in other words,

is this a big number. So I get back an array which has only

47 and 118 in it, because I've filtered out all the things

where the value's not greater than 20. Imagine writing

this line of code without filter. You're gonna have

to a four loop. You're gonna have to create another array.

You're gonna have to run this little function,

call this function, create a new array and

add, append thing to do it. It's at least four or

five lines of code. And here you get it in one line of

code, okay? So you see how closure there has helped us.

This is also much more readable cuz you can read this

like this: Let the big numbers equal this array, but

filter for things there are greater than 20.

That reads nicely, so I'm just clear.

It's very easy to understand what's going on here.

So here's another one. It's called map. What does map do?

It takes a closure, or a function. And

it executes that function in order to transform each

of the elements in the array you're sending map to,

to a new array.

Now that transformation could be anything that a function

can do. And you can convert it to any new type you want.

Although it's one function, so it

coverts everything to the same type. So you could use it for

type conversions like I have here. I've taken 1,

2, 3 and mapped it to the string versions of 1, 2, 3, so

now I have the new array with strings in it. String of 1,

string of 2, string of 3. That's a trivial mapping.

But you can imagine much more powerful mappings where you

take each element of the array, and

call some complicated function on it, and get the result into

a new array. So by creating a really powerful argument there

instead of String($0), something more powerful, you

can really have one line of code that's really expressive.

It can do a lot of things. One thing about this one: notice

that after the word map, there's no parentheses,

no open parentheses. Did you notice that?

You see the difference between filter and map, okay?

When I called filter, I said open parentheses,

open curly brace, the function, curly brace, close

parentheses. Here I just say, { String$0}, no parentheses.

And this is what's called the trailing closure syntax. You

are allowed to have closures that are the last argument to

a function. The outside of the parentheses of that function,

if they're trailing, see they're trailing the call. And

in fact, if there's only one argument and

it's closure, you don't need the parentheses at all.

And that's what happened there with map.

I'm just saying map, parentheses get rid of them.

Just put the closure there, trailing. And

that also results in some pretty cool looking

code right here, you see that? So you can use that anywhere

that a closure is the last argument of function.

You can take it outside of the curly braces. Cuz you already

got the curly braces, and that's why they do it.

You don't really need the parentheses around it as well.

So put that at the end.

And put all the rest of the arguments, if you had them,

inside the parentheses right before. This last one, I won't

go into the details, but it's a similar kind of thing.

Reduce: what reduce does is it takes an entire array and

reduces it to a single value. So here I'm reducing it by

adding all the numbers in the array up. So my closure is $0

+ $1, because the argument it takes is a function that takes

two elements. One of them is an element from the array and

the other is the answer so far, and

then it returns the new answer so far. So it just executes

that function over and over and over on the arrays.

By the way, notice that I can say this as sum = [1,

2, 3].reduce(0, +) which is my starting so far value.

Which I haven't added a name on, so it starts at 0 and

then I can say plus. The reason I can say plus right

there at the bottom line, is because plus

in Swift is not some kinda weird built-in thing,

it's just a function. It's a function that happens to be

declared in a way that says, this is a function, but

it's two arguments it's going either side of it.

It's called an infix operator on a function. So

since plus is just a function, and

I'm taking a function as an argument,

as long as it's a function that takes two arguments and

returns one, which is exactly what plus does, it works

there. We could have done that in our calculator brain, too.

Remember all that closures we were doing ($0* $1),

that could've just been *), ($0+$1), that could've just

been +. Cuz + is a function that takes two doubles and

returns a double. Plus also know how to plus other types,

ints. And it even knows how to plus and into a float,

for example, etc. You can plus strings together.

So that was just a little aside just to give you

an introduction there. You're gonna start seeing a lot of

methods that take functions as arguments.

So I want you to start to get comfortable with that.

Okay, dictionary. So we learned a lot about dictionary

in our first lecture. Dictionary also has this

special declaration syntax, which is open square bracket

key type colon value type closed square bracket. So

those two things in yellow are equivalent.

And the one on the bottom seems to be the preferred

one these days. So you know you can create a dictionary.

By the way, I show you creating dictionaries from

kind of constant values here.

But you can create a dictionary just by saying,

let d equal dictionary. Open parenthesis,

close parenthesis. And if you say var d

equals dictionary, then now you can start appending items

onto it because you get an empty dictionary to start. But

here I'm starting my dictionary with stuff in it.

That probably should say var pac12teamRankings

because two lines later I say pac12teamRankings sub Cal

equals 12. Note also that

when I try to get the ranking of Ohio State, it returns nil.

And we know that when we use square brackets to get

something out of the dictionary, it returns

an optional of our value type. Our value type here is ints,

so it's gonna return an optional int.

Alright, enumeration. A dictionary is also

a collection and thus can be sequenced. So you can do for

in on it. Of course, a dictionary has keys and

values. So we need a tuple to do our enumeration for

the tuple key common value in the dictionary. And

then it'll go through and key in value will be set.

It's a perfectly straightforward way

to enumerate or iterate over a dictionary. Okay,

String. So string, you would think, is the simplest class

in all of any language. It's just a string, right?

Well, that turns out not to be so true. When you think of

a string that represents every language in the entire world,

all of a sudden it got real complicated real fast.

Because some languages are ideographic. Some languages go

right to left instead of left to right. Some languages have

a lot of diacritic marks and accents in them. Some don't.

Most languages don't use the same alphabet as we use.

So string is super complicated,

this is a very complicated class. Now string tries

its best and does a pretty good job of simplifying it for

your use. But the complexity is still there. Now the most

important complexity about a string is that representing

a string is not always one character equals one

internal representation unit. Now the units, the kind of

thing that's used to represent strings on the inside,

are Unicodes. I had you skip that reading in assignment

one, I'm putting it in for assignment two.

It's really not that critical that you understand it.

I think it's very interesting, though, so

you probably want to read it. But the thing about Unicodes

is it's not one Unicode equals one character.

In fact, if you have like a little emoji of a dog barking,

that might be three Unicode characters. It's only one with

regards to what you perceive to be a character. Or

even more simply, the example I have here, the word cafe.

It's got e accent aigu on the end, right, it's a French

word, e accent aigu. That could be four Unicodes,

because there is a Unicode for e accent aigu.

Or it could be five. It could be the e with another Unicode

character that says put an accent on that previous

character. So, when you have this kind of unknown how many

characters it represents, you need a new abstraction

to represent what we perceive as humans to be a character.

Even that is difficult to truly define, when you think

of all the languages in the world. It's easy in English,

though. So that's really how we're gonna interact with

strings: to try to think of them in terms of characters.

But a string itself is not actually

a collection of characters.

A string is a more powerful internal structure,

it's got all the Unicodes in there and all that stuff,

it's not quite that. And that makes for a little bit of

complication as you're gonna see. Now, you can't string, is

indexable which means you can use the open square brackets

just like you can in array to get one of the characters.

The only rub is what I said on the other slide that index

is not an int. So if you have the word hello,

it's not like you can say, hello[1] equals e.

You can't do it that way because it might,

if it was cafe then cafe sub 3.

It's not clear that you want a character at that point, and

so you've got to make sure you get the right index in there

because that index behind the scenes can be quite

complicated. There's this other struct for it, which is

called a string.index. So let's say I had a string,

which I'm gonna call s and I'm gonna put hello into there.

Now, what if I wanted s[0] now, I can't do s[0],

because we don't index strings by integers but

let's say I want that. How do I get it? Well,

I start by calling this var, again using this var and

string called startIndex, okay? It gives us

a string.index. It's very important, we need to get

a hold of a string.index because the way we're gonna

move around in string is by taking index we know and

moving forward or backward by character, by human

understandable character. Not by Unicodes, because we

don't know how many Unicodes there are per character but

by character, we're gonna be moving back and forth.

So we start with this first one.

And so now I can create a variable firstChar which is of

this type Character,

that human understandable character.

That's gonna be equal s[firstIndex]. So see look,

I've used square brackets to index into a string, but

I had to use a String.Index not an Int. This first index

I got by asking the string "what's your first index"?

Well this is kinda useless because I have to ask

the string, what's the index of your first character and

then turn around say okay give me S of your first character.

So that's not the interesting thing,

what if I want the next character. If I

want the next character, I ask the string what's the index of

the character after your first character. And

it'll give me a new index, of its second character and

now I can get that one. Even that is a little bit like,

my God, you're kidding me,

this is really how I have to do this? What if I wanted

to go jump ahead though, and get the fourth, the fifth

character, let's say? Well I can jump ahead by saying s,

give me the index of, starting at your first index,

that's four ahead so jump four ahead,

four characters ahead. This is all a little

tedious and of course this is not the actual way that we're

interacting with strings. We're usually looking for

substrings, okay, or subranges of characters or

we're trying to find a character in a string.

By the way, you can use ranges, so I could say

give me the substring which is firstIndex...secondIndex and

it would give me he. A new string which is he, so

you can use ranges there but they have to be string.index

not ints. So we want basically something that

is a collection of characters. A string is not a collection

of characters so you can't do for in, for example, on it.

You can't even say index(of:).

Index(of:) is this great thing where you can,

if you have a collection of things, you can say give

me this index of this thing in there. You can't even do that

with a string because it's not a collection. Luckily,

string has a var which will give you a collection of its

characters. And not only is it gonna give

you a collection of its characters that you can for

in over and do index(of:), but the string indexes you get

from that collection will match what's in the string. So

you can use this collection of characters to find things in

there, get the index of a character, things like

that. And then use the indexes you find there to go back to

your string and say, okay now give me a substring. So

characters is the name of this var on string. So for example,

if I want to iterate over all the characters one by one,

do a for loop over them I can say, for c:,

which will be of type character,

by the way, in s.characters. I can't say for c: in s, for

c: in s.characters. And that's just gonna call my for

loop once with each character. Question? Yeah,

great question. So if I do this over cafe,

what am I gonna get? I'm gonna get four characters, okay,

because that E-accent-agu that they use is considered in our

human perception one character.

I'll get four characters. So there is a character.

Characters are struct, right and in the character

there is a character that represents e-accent-agu.

No matter how it's represented in the string,

in the string it might be two characters, it might be one,

it doesn't matter. You're gonna get the one character

for it, so that's a really good question. How would I

know how many characters there are in a string? Again,

from the user perspective. s.characters.count,

not s.length or something, s.characters.count,

the count of the characters in the collection of characters

for this string. Also, what if I want to find the first space

in a string? Got a string with a bunch of words, I wanna find

the first space. I would say s.characters.index(of: " ").

And that's giving me a string.index(of: " ') that

collection of characters. I can then use that string in

that index though to go back to my string and do something.

Maybe insert something there or

delete the word that's right after the space or insert

another space. I'll have the index into the string now.

String is a value type, so when you do let versus var,

if you do let you cannot do things like append on to

the string cuz it's immutable. Most strings in Swift

are immutable, that makes it super high performance.

But if you have a var you can do reading plus equals there

and so I can have hello there. It doesn't have any effect on

hello, the let one because that's immutable, right? Okay,

so I can't do that. And I can use the characters to

manipulate strings in really powerful ways. I can, I don't

have time to talk about all of it, this is where you really

do need to read your reading assignment carefully. But for

example if I want to insert the word you into hello there,

so it says hello you there, okay, I would just get the,

find the first base by doing characters.index(of: " "),

which I showed you on the previous slide. Then there's

a method in string called, insert the constant,

the content of this collection of characters

at this location, this string.index. So, when I want

a collection of characters that represents " you", I say,

" you".characters, because it's the .characters, and

it gives me a collection of characters for that string. So

it seems a little weird but It actually turns out to work out

pretty well. And there's a billion other functions,

in Swift, many, many, many,

I can't talk about them all.

Notice I say if let firstSpace, because that might

return nil if it couldn't find it. So I wouldn't do it there,

I wouldn't insert it there. Yeah a bunch of other things

checking where strings have prefixes or not.

You can replace subrange, of course you have to find

the range which usually you're gonna have to look at that

collection of characters to find the ranges you wanna

replace things etc. Even cool methods like components

separated by string will take a string that has like calm or

separated values and grab all of the values and

put them in an array which is kinda fun. Okay so

a lot: string has dozens and dozens of methods, you really

need to familiarize yourself. If you don't take the time to

familiarize yourself with those thing in strings.

Then I guarantee you're going to be writing a program and

you're going to want to do some string parsing or

something and you're going to write a whole bunch of

code to do it and then find out there was one method that

did exactly what you want in the string.

There are things in there take closures and

do all kinds of fun stuff so

make sure you pay attention to both to string and

to the character view which is a collection of characters.

All right, other classes. This is kind of quick summary here

of other important classes. One is NSObject, NSObject is

a class. It is the root of all Objective-C classes. An iOS

app written before a couple years ago when Swift came out,

all the classes in there would inherit eventually from

NSObject. So NSObject has a base functionality. You do not

need to subclass from NSObject to make a swift class.

However there are some really obscure features still left in

IOS where to expecting a class that inherit from NSObject.

If we even get to them, I'll show them to you. They're

pretty rare. But that's just so you know what NSObject is.

Doesn't really have meaning to you,

cuz you guys are gonna be Swift programmers.

NSNumber is another class, it's a generic number

holder. This is also inherited from Objective-C, you can tell

by the NS there. Until we can hold any kind of number,

floating point, decimal, you can even hold a bool,

since it considers that a number where zero is false and

one is true. Any nonzero is true. And you can also

do type conversions. Again, in swift, we're gonna be using

the actual concrete number classes like double an int and

we'll use their constructors. To do type conversion.

But just so that you know that NSNumber is around. Okay,

date. Super important class. Anytime you are representing

a date or time, you're gonna wanna use this date struct.

And it has a lot of ancillary classes that go with it,

like calendar, date formatter, date components like date

components will tell you the month of a date. And

of course, what the month of is of a date depends on

the calendar it's in, cuz not everyone uses a calendar like

we do. All right, there's a lot of calendars

all over the Earth that are different than ours.

So anytime you're even contemplating putting a date

anywhere in your UI you need to be using this class.

Because if you wanna have your app work in anything but

English, you're gonna have to format your date, using

the DateFormatter, in whatever locale your app is running in.

So date is super important. You would think date is really

easy, but no. Date actually has a lot of complexity to it,

because of all the different ways we represent dates in

the world. Same, similar to strings complexity. And

then there's data, D-A-T-A, that represents a bag o' bits.

Just a bits, bunch of bits in there. Usually this might be

something like an image, the bits of an image, or

something like that. Something you get over the the network.

So data is how we represent those.

Notice that there is a struct, it's a value type.

It gets passed around copy on right. And

you'll start seeing data in UI maybe week five or

six of this class. All right, initialization.

So initialization is very complicated. You're

gonna have to read the reading assignment on it eventually.

I'm gonna give you the really fast highlights of it. init

method, again, we can have them on classes or structs.

They are used to initialize any of the properties that we

didn't initialize with equals or using lazy or they were

optionals. All those are taken care of and if there's one

left, or more than one left, then we need an initializer.

To initialize it. And they're kind of a pain in the neck.

Because, especially for classes. For structs,

they're not a pain in the neck. They are perfectly fine.

Struct, you just have an init with whatever argue you want,

arguments you want. And initialize your variables.

It's all very simple. But for classes, it's a little more

complicated. Now, whether you're a struct or a class,

you can have multiple init. And they can have different

arguments. As long as you give them enough arguments to be

able to initialize all their variables, you're good to go.

So you can have as many inits as you want.

And a lot of classes have multiple inits. Meaning on

kinda how they are being used, how they are being created.

Think of something like string.

String has an init that takes a double.

It has a string that takes another sting if you want to

make a copy of the string it turns out. It takes an init.

It has all these things that you can compare to string.

Or not all the things you compare string but

a lot of things you can compare to a string.

It has an initialized that it will take that as an argument

for example. Callers execute your init by creating

one of the thing. They just put the name of the type and

parentheses and the arguments you want for that init. So

they pick which of your init that they want and

they call that one with those arguments.

We've seen many examples of this in our lecture, so far.

You get some inits for free. If you're a base class, okay,

you don't inherit from anything else.

You get a free init with no arguments. Congratulations.

So that means, at least, people can create you.

But, again, if you have any vars that aren't initialized,

you're gonna have to create your inits that initialize

them. Structs are even better. They get an init that has all

of their vars. Now if a struct implements even one of its own

initializers, it stops getting this one, this free one.

You only get the free one if you don't do any other ones.

So it's like the default one.

And we saw this in the lecture also.

We got the free one in the init function, first operand.

We never wrote that init function, we got it for free.

It just appeared and we were able to call it. , so

structure nice you get the basic free init for

all your vars. What can you do inside of a nit? I'm

gonna start going fast here, okay. So here we go. One,

you can set any properties value even if that property

already had its value set, you can reset something else.

You can set lets. So you're gonna have a let that's

got less x equal 5. You can still reset it in your init.

Your init is allowed to set lets. You can call other init

methods okay in your own class or your own struct. And you do

that by saying self.init with whatever the arguments to that

init method are so init methods can call each other.

In a class, you can call super.init.

An initializer from your super class.

Of course you need to get your super class initialized.

Now, when we start talking about class though,

and we start talking about calling inits in our super,

and we start thinking about inheritance,

it gets really complicated. So

let's start thinking about class and break this down.

Let's start with what are you required to do in an init for

a class? in a struct it's easy you're just required to

initialize all your vars that aren't initialized. But

in a class what are you required to do? By the time

it's done you have to have initialized all your vars.

We know that. There are two types of initializers.

A convenience initializer.

This is only for classes. A convenience initializer and

what's called a designated initializer.

Designated is the default. There's no keyword it's just

if it's not marked convenience then it's a designated.

Now here's where the rules come in.

A designated initializer non convenience must and

can only, call the designated initializer that it is in,

that is in it's immediate superclass,

it's very important. It has to call a superclass init

and it has to get designated initializer. It cannot call

it's convenience initializer in a superclass. Nor

can it call two classes up the inherent chain unless the one

right above inherited the init from the one up above, and

we'll talk about that in a second. You have to initialize

all of your properties before you call that super init.

You must have completely

done all the ones that you introduced in your class.

Get them initialized before you call super init. And,

you have to call the super one before you can reinitialize or

change the value of any of it's Properties, obviously,

you gotta let your super class have a chance to initialize

itself before you start mucking with its properties.

Otherwise, when units call super, it's probably gonna

blast whatever you did to its properties.

A convenience init can only, must and can only,

call an initializer in its own class, no super.

Only in your own class,

convenience initializer only in your own class. You can

call it another convenience or you can call it designator,

but it has to be in your own class,

not in your super class. And

a convenience init has to call whatever init it's gonna call

in itself before it can set any of the property

values. It's kind of different from an init that calls into

super because that one has to do its initialization,

the designated one, before it calls super.

This, in this case, you have to do convenience,

you have to call your other one first.

And the calling of all other inits, whatever you do, any

inits that you have to call has to be done in all cases,

before you start calling methods on yourself or

accessing properties.

Not setting the properties, but accessing them.

In other words, you have to be fully initialized before your

init can start using your class. All right,

whew is right: a lot of rules there, and a lot of them

are conflicting and all that stuff. Let's make it even more

complicated when we talk about inheriting inits. So,

you wanna get some inits from your super class,

whoa, not so fast. If you don't implement

any designated inits, you only implement convenience inits,

then you'll inherit all of your super classes designated,

but only if you don't implement any of them.

And if you implement even one designated init,

now you're not gonna inherit all your super classes. If you

override all of your super classes designated inits,

then you'll inherit all of its con, convenience inits.

Now why is that? That's because your superclass,

when it implements these convenience inits,

it depends on the designated inits being implemented,

so you have to implement them all.

Of course, you could inherit them all by implementing

none of them as well. So, any init that you inherit by these

rules can be used to satisfy any of these other,

other requirements that we're talking about on the previous

stage. You can make an init required. You just say

required init. Required is a key word, and that will

make it so the subclass has to implement that init, okay,

it's required. Failable inits, we talked about these with

double. If you put a question mark after your init,

init question mark, that means that this init can fail.

And that means that this init, or when you create this thing,

will return optional version of this class. So

we thought it was double.

If we said double parentheses string, it would return

an optional double. It was a failable init, and

that's because you could have said double of hello, and

you would be like " I can't turn it into double: fail".

And the way you fail out of a failable init is you just

return nil. Otherwise,

you don't return anything out of init, it just initializes,

but the one time you return anything is out

a failed init, you can return nil. So, an example here is

UIImage. UIImaged named looks up that image in

the xe assets. Remember that xe assets thing that I moved

off to supporting files at the beginning of the first demo?

This looks it up in there, of course, it might not find it.

So we do if let image = UIImage(named: "foo"),

then we do something, otherwise we fail,

that UI image initializer failed. Alright, Any and

AnyObject. There is no more init, we're done with init.

Any and AnyObject: these are types, special types.

These types really are almost exclusively used for backwards

compatibility with Objective C because Objective C had a type

in it called id, which was kind of like Any,

AnyObject actually. So Swift needed some compatibility, but

Swift doesn't really use Any very much, so

we wouldn't, Swift is strongly typed. So you wouldn't wanna

have a type which is like, it can be anything. Okay, because

that's what Any and AnyObject are, it's like anything,

any type. It's this weird kind of typeless type kinda thing.

The only difference between Any and

AnyObject is AnyObject can only be a class,

it has be a reference type. Any can be anything,

reference or a value type, that's the only difference.

So why do we have these AnyObject things?

Where are they gonna show up? Well,

there are some methods in iOS where one of the arguments

truly could be anything. One example here is when you have

multiple MVCs, which we're gonna learn about next week.

The way you go from one to the next, next is called segueing,

you segue from one MVC to the next.

And the thing that causes a segue to happen, okay,

is the argument in this method called prepare for

segue called sender, okay,

just like we had sender in the IB action. So

the sender is the one who's causing this segue to happen,

well, a button could be causing a segue to happen,

a line in a table view could be causing it. Some custom

piece of code of yours could be causing this MVC to segue.

So when you're preparing for it, you've gotta be

able to say which one it was, and that's just Any. So

if this were a Swift API, they wouldn't have done Any.

They'd have had a protocol where you could be a segue

sender. And you'd have to implement probably some

functionality that would make sense here. But in this case,

it's Any. It knows optional Any too because you can have

nil, the center could be nil. Where else will you see it?

You could have an array of AnyObject or an array of Any.

That could be an array that has doubles and strings and

things mixed in there. Now you might be tempted to use this

in your assignment number two when you see the assignment.

But you're not allowed to

because one of the required tasks says you can't use Any

or AnyObject. Also you wouldn't be very Swifty.

In Swift, if we wanted to put doubles and

strings in the same array, we use an enum.

That's what we did with our operations array, and that's

what we would do in Swift, so we wouldn't use AnyObject.

Another thing you could possibly use Any for is for

a cookie, right, some piece of data that you're giving

out that you don't want people to know what class it is.

And they're just gonna give it back to you at some point,

and you'll do something with it and

only you know what it is.

So you know, an opaque type, you could use it for

that. How do we use something of type Any, because we can't

send any messages to it cuz it's not of AnyType, so

we don't know any methods that it does or whatever. Instead,

we have convert it, and we convert type Any or, or

AnyObject into some class that we know about using as.

As is a key word, and we do as question mark because we don't

know for sure that we can convert something,

so it's an optional. And we use it with if let.

So if I had some variable unknown,

which is of type Any, so I don't really know what it is.

But I think it might be MyType, I'm not sure.

But I think that might be MyType in there. So I say,

if let foo = unknown as MyType,

if let. Then inside there, foo is now going to be unknown,

but as MyType. So I will be able to

send foo message whatever my tape, I'll be able to send foo

whatever MyType understands, methods and vars.

So that's how we use it. We use this "as?", it's called

casting. This casting, by the way, not just for AnyObject,

we can cast other things. For example, if I had a variable

which is, vc which is a type UIViewController,

I could assign it to UI, to CalculatorViewController.

Because CalculatorViewController is

a subclass of UIViewController. So

it is a UIViewController, so I could assign it to vc. But

if I assign it like this, with this typing,

I cannot say vc.displayValue cuz vc.displayValue,

displayValue is a var in CalculatorViewController,

and vc is of type UIViewController.

Even though it points to a CalculatorViewController,

from Swift's perspective, it's typed as vc, and

Swift is strongly typed. So if I wanted to send displayValue,

I would have to say, if I can let calcVC = vc

as a CalculatorViewController Now I can send displayValue to

calcVC. Cuz it's the type that you actually

type it as that matters, not what it's pointing to. So you

have to use as to get it to be something that you really

wanna use. Okay, I'm gonna go a little bit over here.

If you have to go, it's, it's fine, just keep it quiet.

The last thing I'm gonna talk about is user defaults.

User defaults is a very lightweight,

limited database. It's a tiny little database that persists

between launchings of your app. It's great for

things like settings and stuff like that.

Don't put anything big in there. The only thing you can

put in this database is what's called a property list.

A property list just means any combination of array,

dictionary, string, date, data, or

a number, like int, float, double, whatever.

That's what a property list is. It's just conceptual.

There's no actual type property list, unfortunately.

If this were a Swift API, it probably would be such a type.

It could be a protocol. But anyway, there's not.

This is from Objective-C. So since there's no type

that represents that codgepodge of classes,

this API that I'm gonna show user defaults uses Any. And

this is what it looks like. It has this core, set, and

get. Set Any? Now that Any can't really be Any,

it has to be one of those types, string, dictionary,

array, whatever, it has to be be a Property List,

forKey string. So you just put it, anything you want

in this database under a certain key.

And then you get it back out by saying, object for key, and

it returns you an Any. And it's an optional Any because

it might not be in the database,

in which it is returned nil. So it says any but

it's not really Any, it's Any as long as the property lists,

which means it's one of these ten classes or

whatever. The way you read and

write it, you don't create a user default by saying let

x equal user defaults with parentheses.

You say let defaults = UserDefaults.standard, so

that's a type var on the user default struct.

And you get this standard UserDefaults and

then you can send it things like set,

that thing I was telling you, set Any. And here,

I've got three different sets, one of them setting of double,

one setting an array of ints. An array of ints is okay

because array is part of property list. And so is int,

so that's okay. That's a property list. An array

of ints is a property list, a property list. So is a double,

cuz it's one of those types. And I just set them in there.

And then when I get them out, I use that object for key.

And actually for some common types,

like doubles, arrays and dictionaries, there's actually

a nice little method in there to give you that type back.

That's so you that don't get an Any back and

then have to do as. Because you know that objects for

key returns an Any until you give this Any and

you have to go if this thing has a double,

then I've got it. That would be annoying. So instead,

it just has a method called double that does that as for

you. And if the as fails then you, I think either,

I don't know if it returns a double or an optional double,

but you might get zero back, you might get a nil.

I don't remember exactly. But for array in dictionary,

a couple of interesting things to note. Obviously,

the Anys that are inside the array in dictionary,

those will have to be property lists as well, the things that

are returned to you. And also know that dictionary,

this convenience method dictionary,

it's the string is always the key in the dictionary.

If you had a dictionary where the keys were say, ints.

I think that's a valid key, yeah, in the dictionary, yeah,

it is. Then you would not use this convenience method.

You'd have to use object for key and then use as to turn it

back into a dictionary with int keys.

Saving the database is autosave, so you actually

don't have to save it. If you wanna force it to save because

you're worried that the autosave might not happen.

You're gonna exit your program or something, you can use this

method synchronize. It's called synchronize defaults.

It will synchronize it. That's almost it, assertions.

Sorry, one last quick thing. Assertions are just a little

Swift function that takes a closure as the first argument

and a message as the second argument.

All it does is it executes the closure. If that returns true,

it does not crash your program. If it returns false,

it crashes your program and prints that message out. So

you could put, you know, some validation call. This line of

code will not even execute in the version of your app that

you ship on the app store. When you build the app for

release, the asserts are completely ignored.

It doesn't even actually give the closure, let alone crash.

It just ignores them, so this is a debugging thing only,

okay? That's it! For Friday,

we do have Friday session, it's at the normal time. And

it's gonna be on source code management.

A really cool way to manage your code even if you're just

one programmer working on a project by yourself. And then

next week I'm going to talk about doing custom drawing

in your own view. Multi-touch, like pinches and swipes, and

things like that. And finally, multiple MVCs so

we can build a more powerful calculator.

Your assignment two has gone out. It's already posted.

It's essentially enhancing your calculator with a lot of

the things that I talked about today like tuples and

defaulting values and even value types.

All kinds of stuff. So we'll have a lot of fun with that.

>> For more,

please visit us at standford.edu

The Description of Developing iOS 10 Apps with Swift - 3 More Swift and the Foundation Framework