Transcript for:
L3: Understanding MVVM and Swift Types

it's probably the most slides you're going to see me do in a row the whole quarter long but we do need to cover some basic architecture before we dive into the next part of the demo which will be the second half of today any questions before I start okay good all right so lecture number three here we got two huge topics to talk about one is mvvm which is the architecture the design Paradigm that you're going to use to build an app and then the Swift type system the different types that are in there like struct and protocols and all that so those are two major topics and then I'm going to dive back in the demo and we're going to start building the game logic for our memorize app right we'll read all the things about what happens when you click on cards and all that we need to build all that all right so this mvvm thing what's that all about well in Swift to say that it's important to separate the logic and data part of your app from the UI would be a tragic understatement it's really really important Swift UI in a way is all built around this idea that you're going to have your data and logic what your app does over here and then you're going to have the UI that shows that to the user and interacts the user is a separate uh thing so that's just really important the logic and data side of it so in our memorize app it's the what happens when you click on a car then are the cards face up or face down all that stuff uh we call that part of our app the model you're going to hear me use that word model hundreds of times all that stuff lives in the model we call the stuff we've been doing so far in the class the UI or sometimes we'll call it the view because it's our view our portal onto the model now the model it could be a single struct it could be a whole SQL database full of stuff maybe it's some machine learning code maybe it's like a rest API over the Internet it could be almost anything it's conceptual our model is conceptual it's not just a single struct although with our memorize apps it is going to be a single structure this is super simple little first starter app but I don't want you to think that your model couldn't be way way more powerful uh and complicated now the UI part of our app really is just like a parameterizable shell that the model feeds one of the best phrases I've heard for the UI is it's a visual manifestation of the model because the model is what your app is it's a memorized game that's what it is so all that logic is in the model the UI it's just how you show that to the users it's a visual manifestation of it all right so you really want to think of it that way for what we've done so far is face up card count these things that we've been putting in assign State they belong in the model those are all things about the game we're playing right so we don't want those things so I will be getting rid of them putting them into our model now one of the things that Swift does super important one of its responsibilities is to take to make sure that anything that changes in the model appears in the UI so it's got an enormous amount of infrastructure to do that for you all right that's one thing you have to understand you're not really going to be responsible that much for making whatever's in your model appear in the UI Swift is going to mostly do that for you you just got to give Swift some hints about what in the model affects your UI but once you do that it's going to do it so don't worry too much about that part of it mostly you're going to worry about separating these things out if we separate these things out the UI and the model how do they connect to each other because obviously they need to talk to each other well I boiled it down to three different ways of connecting it here there's probably some other ways but I think most things would fit in one of these three categories so rarely one way we could connect the model to the UI is to have the model be atyne state in a view right I mean if you put the entire model all the logic your app into an atyne state in your view then obviously review uh could access it well this is extremely minimal separation it probably wouldn't do that I'll talk about when we would do that soon number two is that the model is only accessible to the UI via a gatekeeper okay so we're going to have a gatekeeper and that guy's job is to keep the UI in the model communicating with each other safely coordinating communication this is the main way we're going to do it this is this mvbm thing I'm talking about number two here is 99 of the time you build an application and then I throw out number three here which is kind of a hybrid of the first two which is there is this gatekeeper which we call the view model there uh but sometimes it'll allow direct access to the model it'll have a VAR that's public that the UI could look at that bar and actually talk directly to the model directly to the memorized game that's a hybrid of the first two essentially so how do we know which of these things to do well the easy answer is always do number two okay that's what I'm going to advise just always do number two especially when that previous live when I said the model could be SQL databases and all these things you definitely need number two in that case because the the this thing in the middle this intermediary it's the thing that knows how to do SQL and all that you don't want your UI to have to be making SQL calls your UI is just presenting information on screen it should all be simplified for your UI so that's why you would always do number two but it's very very very simple model even simpler than our memorize it might want to do this at sign State solution especially if the view maybe just comes on screen really briefly it has a little bit of data that maybe it's like image data that it's showing or something like that and then it goes away and it's gone forever then maybe you don't need this extra gatekeeper guy and then the third one is maybe you're in between like our memorized game could be that hybrid you're going to see when we build our memorized game yeah we have this intermediary the gatekeeper but a lot of time the gatekeeper is just forwarding on requests from the UI directly to the model so you could make the argument ah just let the UI see the model directly and still have the gatekeeper to do some other bookkeeping I don't like number three because as your app grows you start building a tangled mess where your UI is now talking directly to your model through this gatekeeper guy and it just doesn't grow very well it doesn't it's not a flexible growth system so even though you might have to do a little bit of work to protect your model from your UI with this gatekeeper that seems a little bit like why are we wasting our time doing that it still can be worth it especially as your app grows and becomes more powerful and you'll see that in the demo because I'm going to show you both number two and number three in our demo we're going to talk about number two this mvvm the reason it's called mvvm that stands for model view view model that's what the MV and VM are the model you know what that is I told you your view is another word for the UI and view model is this gatekeeper in the middle that I was telling you about it's kind of interesting name view model because its job is to connect the view to the model and be the gatekeeper between the two so I kind of like the name view model it's a weird word but that's what we're going to see so here's a picture of mvvm there's my model over there here's my view and we'll get to the thing in the middle in a second so let's talk about the model in this whole architecture the model is UI independent we are not even going to import Swift UI in our model it is truly UI independent in our memorized game it's going to play a game of memorized with anything on the cards jpeg images we're going to use emoji but it can do anything it's a generic ui-less memorized game playing thing UI independent important to understand that part in the model as I said before it's the data of your app like whether the cards are down and the logic like what to do when you choose a card which cards to flip over and stuff it's both of those things combined it's very important to understand that the model is the truth for all of these things so if you want to know the data or you want to perform some logic you have to talk to the model there's no copying this data somewhere else like into this view model thing I'm going to show you or certainly not into that sign state in your UI you would never do that you if you want the information you go back to the model it's the truth there's always anything the model knows you should always be asking the model for it at all times now let's talk about the view what is the view well the view as I said it's a visualization of the model The View should always look like what the model looks like whatever's happening the model you should see that on screen The View because of that is stateless you see it doesn't hold any state it's just always showing you what's in the model so it doesn't need any state that's why any state we have in the view we Market at sign state so we realize oh we have stayed in our view that's not good this is supposed to be stateless it's okay to have Aston state in very rare circumstances but it's unusual and it's specially marked like that so that we are aware that we're doing this thing that really is rare the views are mostly stateless they're just showing you constantly what's in the model at all times you've probably already noticed this but our view is declared okay we don't write the code for our view in an imperative fashion you guys know what the word imperative means that's like when you're writing code you're calling a function then you call another function to make something happen and then you call another function you're writing imperatively in our view you noticed we just had our body and we just listed the views that went our UI we modified them with new modifiers but we basically just listed them they're just sitting there of each Act of you know cards and the buttons we're saying what it is we're declaring this is our UI and then the model data drives it any part of our UI that can vary is is changing because our model is changing and causing it to change so we declare so it's declarative and that results in this word we see a lot which is reactive that's because the UI is reacting to changes in the model model changes UI updates because it has to because it's always showing what's in the model so now we can talk about this mbvm thing and it works like this we're going to introduce another actor into this thing the view model and the view model is going to bind the view to the model its job is to connect these things to each other so this line that comes across right here says data flows this way read only right because this is stateless and it's being fed by this this guy up here is going to intervene in this line and he's not only binding them he's also interpreting them like this might be SQL and this doesn't make SQL calls so it's the thing that has to make SQL calls turn them into normal variables or something so the view can see them right so it's doing interpretation of the model it also is a gatekeeper between these two guys it's protecting the model so that the UI can never do anything bad to the model and I'm going to show you how it does that the main way it does that in a minute here so it's a gatekeeper an interpreter it's the thing that controls the flow here between these two things so basically that line goes up and through there okay the data flows through the view model to The View how does this all work well things happen in the model and is this view model's job to notice those changes so again SQL database it's got you know it's signed up with a single database to get notified when things changes if it's a swift struct it's fantastic Swift really good at telling you when something in a struct changes and you'll see why that is when we talk about the type system whatever it is the view model has to notice the changes now when it notices the changes it then publishes to the whole world something changed in the model so once the view model says something changed that's when Swift UI kicks in and it looks at its view it says oh something changed did anything change that means I have to redraw and it's super smart about this it's only going to redraw the views that actually were affected by this change and it does that for you so you don't have to worry about it you don't have to do anything to make that happen right so this is the process notice change publish it changes happen system Swift automatically figures out which views have to be redrawn and it draws them how does it know this by the way how does it figure this out again it's all about dysfunctional programming about the fact that structs in Swift are value types we can see when they change very easily it's built in to know when they've changed that's all because of Swift swift enables this to happen and we're not going to talk about the mechanism for that right off the bat here but it's pretty cool I'm just putting these things here like this view modifiers and these little assign things with like assign States but they're different outside but I'm just putting them up here for future reference I'm not going to talk about any of them right now but later in the quarter when you see me talk about one of these things you can think back and say oh I'm gonna go look at that mvvm slide and see oh yeah that's right it was an mvvm thing so we'll we'll be talking about like observed object and observable object and published in the next lecture or so but some of the other ones a little later in the quarter so that's the basics of mvv I'm going this way but there's a big question here what about the other way because the view you can tap on things right you can swipe and do things the user can interact here they could affect the model so how do we go that way because I told you this Arrow only goes this way and it does only go this way while that is done by processing user intent and that's another thing the view model does when someone Taps on something in the view they call a function in the view model saying the user has the following intent for example in our memorized game the user wants to choose this card you're not going to have a method in view model called tap that would make no sense that's a UI thing you would have a method to view model called choose this card you see it's a user intent the user intends something semantically meaningful to the model but then once again the view model's job is to turn that into a bunch of SQL calls or something like that whatever it makes sense to express that intent in the model all right so it's very important this idea of intent now sometimes intent like choose a card r model our memory iPhone it's going to have a choose card method that's just fundamental to it so it's going to seem kind of weird like our view model is hardly doing anything it's just forwarding the message on but it's still being a gatekeeper it's still you know binding them together it's just that our first app is really simple but the second app we build you're going to see that there aren't intents that can't be mapped directly to a single call in the in the model but anyway that's what happens here is intent now what happens when that intent gets called in the view model well of course the view model modifies the model whatever the user in to express whatever the user's intention is then what happened before happens again the model changed a view model notices the changes it does all this publishing something changed the view does its thing and it updates same exact thing has happened before so when it comes to going this way the only thing is the intent once you call the intent view model updates the model and then the normal update happens right our stateless UI is reflecting the new state of the model after the intent that we expressed that is it that is the entirety of nvvm so let's go to the next step in architecture here which is the type system every language it's just so important to understand the fundamental types that are involved right because everything that that language can do really flows out of those fundamental types so let's talk about the types here now I don't have time because I want to do some demo today to talk about all the types so I'm going to talk about structs and classes and then these don't care types which are kind of fun and then protocols I'm going to talk a half about protocols that's why I say protocol part one I'll talk about more protocols in lecture five or so I'm going to skip enums not because enums aren't important they are genomes are important type but I just want time to do everything and I do need to talk about this last type which is functions and yes I'm talking about types here functions are types so let's talk about these types struct in class very similar so I'll kind of compare them in these first two slides they have almost exactly the same syntax and you've already seen it right you say struct content view colon view class very similar but inside there they both have vars they can be stored like is face up right there's a stored variable normal variable they also both have computed vars like bar body right we compute the value of the VAR they also both can have constant lets remember let's versus VAR lesser content bars are variable both have functions and I just want to remind you here that in functions are uh parameters here can have names like operand and buy right there and that they can also have two names an external name and an internal name the blue is the actual name and the purple internal name well we use this on the inside callers use the blue name we saw that in the last demo they both have that construction classes I'll have all these things they also both have something we haven't talked about which is initializers now we saw a rounded rectangle when we created it we created it with a corner radius of 12 or whatever but when we were typing corner it also was offering us this other one corner size where we could kind of do both the X and Y of the corner not just a radius and that's because the ground rectangle has two initializers and you can have any number of initializers you want and they can all have different arguments you can take whatever arguments you want as long as you initialize your struct or your class that's fine now we haven't needed any initializer so far because and I'll talk about this in the next slide we've used the free init you get a free init with structs and classes they're different but you get a free one and we have been using the free one like when we created our card view we use card view open parentheses content remember that we got a free init there that allowed us to call that and I'll talk about that in the next one in the download we're also going to write our own init because it is flexible and nice to be able to specify your own arguments to create your thing they're really simple it's in it looks just like a funk but you don't say funk in it you just say init and you can have as many of them as you want when we create our memory game over there memorize game we're going to initialize it our game with the number of pairs of cards we want even though a number of pairs of cards is not going to be a VAR we're going to have an array of cards instead so what's the difference then constructing class got all these things all exactly the same what's the difference well this is really important to understand and what's good about this is understanding not only from the Swift language perspective but because most of you are coming from object-oriented programming so you're used to classes and Swift task classes and so when I'm comparing structure classes it's kind of like comparing what you know to what you're going to be doing because you're going to be doing 99.9 obstructs in this class okay we're only the only thing we're going to use a class for believe it or not is that view model that gatekeeper thing that will be a class but everything else will be a struct all right so the biggest difference between structs and classes is it structs or value types in classes are reference types does anyone don't think raise your hand if you think you know what that means okay a few of you so a reference type means that when you have a variable that is a class you don't actually have the class stored in that variable you have a pointer to it it lives in the Heap somewhere you have a pointer to it you have a reference to it right it's a reference type and that's what you're used to okay almost all languages object or any languages they have reference to their classes now what's good about that well I guess what's good is you could have 20 different pieces of code all sharing the same class right they all have a pointer to it they can all modify it and everything what's bad about that you could have 10 different things all going to the same class and they're all modifying and how do you know one of them's not screwing it up for everybody else so that's the good and the bad of reference types it turns out Swift believes the bad outweighs the good so they don't use reference types for most things in Swift so what's the alternative value types what does that mean well a value type means that the storage for the variable is actually right there there's no pointers it's actually stored right there and it also has some things that fall out from that for example when you pass it a value type to a function you get a copy of it in fact even when you assign one variable to another you just made a copy of the other one every time the thing gets passed around or signed it's getting copied copy copy copied not pointer and why is that good because if you give a copy like you pass it to a function and then that guy mucks it up he only mixed it up for himself he didn't muck it up for you because you gave him a copy and he worked on it now the flip side of this is it requires a lot of different thinking okay when you're writing your code for example if you have a struct and you want to give it to a function to modify then you would give it to the function they would modify it and they would probably return you the new one right so the return value of the function like here's that new thing you wanted and you saw this actually probably when you looked for array Shuffle right there's array Shuffle which shuffles the array in place that only works if you have a bar and then they were shuffled with a d on the end which gives you back a new Ray shuffled you see and that shuffled that's more the kind of Swift way to do it now we'll talk about in a couple of bullets here How We Do The Shuffle in place when we have this going on let's explain that in a second but that's important to understand and then to get the class again you're passing around pointer so everybody's pointing to the same thing they're all sharing it now another interesting thing is if you have a class and you're handing out all kinds of pointers to it when do you know how to clean up the memory right when do you know I'm done with this object this class well in a lot of languages you do garbage collection right you go look in the Heap you do a mark and sweep and they'll be pointing to this I'm going to clean this up whatever your strategy is turns out Swift strategy is a great one it's called automatic reference counting where it keeps track in real time how many pointers there are there to this and when that count goes to zero it immediately cleans out the memory so it's really nice uh even though we don't use classes it's still really nice that they have this feature in there so what happens on the struck side on the struck side it uses copy on right because when I say that you're passing these things around by copying them I mean all struct if you had array of a million items in there when you pass it to a function it would copy it now that would be impossible if it was really a million items in terms of performance right you can't copy a million item array but arrays are struck so what happens is when you pass it behind the scenes it's not actually going to copy it until someone writes on it and once someone modifies that array now they get their own copy and they so the whole thing is based on copy on write now when you have copy on right guess what you know when things change you have to know when that array changed or how do you know when to copy it well I told you before in the mvvm Swiss really good about knowing when struck's change it's built into Swift to know this struct was actually changed all right that is just fundamental because it can't do the copy on right otherwise without the copy on right constantly passing around a raise of a million items would just not work it just wouldn't work and it's this works incredibly well so it is incredibly efficient if you build your code even if you're processing large data sets it's really really efficient because it does this copy on right built in to the very language now as you're probably getting the message here structs are the foundation of functional programming they're right at the base of what we're doing classes are the basis for object-oriented programming why do we choose one of these Styles over another well object-oriented programming came out of this idea I talked about it before data encapsulation right when encapsulate the data of a real world concept or thing and then associate all the functionality with that data by encapsulating it all into one structure with functions about that data right that's what object only program is I think we can all agree and it adds this idea of inheritance because some things are very like other things but with you know some minor modifications and so we can inherit from them and then tweak them to be a specific instance of that or whatever that's great but functional programming has a different take on it which is that it's not the data that we wanted to encapsulate it's the functionality so all we're going to really do is describe how things behave I've already said this before right like how a view behaves or whatever we're going to describe that formally in our language and then we're going to be able to know which things can do what and we can ask them to do it and when it comes to the data that's behind the scenes like how an array stores its things who cares okay what we know is that an array has a whole bunch of functions and bars on it that we can call that'll do certain things and we don't really care about today and we never care about it and if it totally changed its mind about that we wouldn't care too so functional programming it's fundamental to functional programming that we have these value types because in functional programming one of the real things we want is provability we all heard about this concept of provability in computer science you want to be able to take a piece of code and prove that it will do what it will do no matter what no matter what environment it's in or whatever you can't do that not becoming a programming because you don't know who's going to have a pointer to your class who might mess the whole thing up increment some counter or do something like that whereas here with functional program you can because your ball was passing a copy of the thing in there and it does what it does and it Returns the modified thing back so it's just that's always going to happen nobody can interfere with that from outside that function will always do what it says it's going to do and you can prove it with test cases or whatever you can prove what it's doing so it's just a different way of thinking about programming much more about provability and functionality based design and this is much more about data encapsulation and kind of modeling the real world although we can model the world just as well in functional program because in the real world things behave like certain things so we can do it there too just as much all right so there's no inheritance at all instructs because inheritance is limiting it you know if I had two things that are kind of similar but one's not really a subset to the other it's like ah they want to share some functionality but they can't you see they can't inherit inheritance is limiting unnecessarily so there's no inheritance there is inheritance of course in this side because Swift is trying to be an object or any language and also it has to have backwards compatibility with the old way of programming in iOS which is all class based so it has single inheritance regular normal inheritance that you're used to this init thing I told her we got a free init they both get free and it's totally different obstruct the free init you get is an init that initializes all of the variables is face up and content all of them right and of course if any of them are defaulted then you don't have to put them on there but you get that's what you get if you don't do in your own init you get a free one that has all with the class if you don't do your own init you get one that does none of them but it's still required that all of them be initialized so the only way you can use the free init in a class is essentially is if you put is equal to something for every single variable you have they have to all have default values because you only get this free one so in classes we almost always have inits because this is such a weak free init in structs we often don't have inits it's free one it's so powerful the objects are always mutable you have a pointer to them you can always go through that pointer and change the object dangerous that's why anybody can change your object it's dangerous here instructs mutability is explicit if something is in a let you can't mutate it if it's in a VAR you can so if I had an array and it's in a VAR I can call Shuffle on it because Shuffle shuffles it in place or I could call append to add something to it or I could subscript it and assign one of the things to something else because it's a VAR it's in a VAR stored in a VAR if it's in a let things like Shuffle don't even exist now if you call shuffled with a d that would work right because that doesn't modify the array it just shuffles it and returns a new one to you so this is explicitly managed which is really awesome as a programmer to know that you have some piece of state that can be modified or not it's just it's wonderful it would so the question is can I use a let for a class you can but all you're talking about there is the pointer the thing it points to is always mutable okay the Pointer's not mutable who cares right I mean you have the point lats are allowed but they don't really mean much over here foreign so yeah so structs are your go-to data structure 99 of everything you're going to do in this class is a struct we're doing functional programming here uh sometimes you'll hear me also say because whenever I say functional Prime I always throw in there or protocol oriented programming you could call it that I'm going to talk about protocols in a second you'll see why I keep throwing that in there pure functional programming doesn't have some of the things that Swift does with its protocols so it's a combination a functional programming and um a protocol running programming and here we either use this for backwards compatibility to the old iOS which none of you are going to be doing that's six years old by now old news or we would use it for our view models now why do we use a class for our view model here's why our view model is shared very much shared between maybe lots of different views lots of views want to get at the model right I might have a score view in my memorize game that wants to show the score of the game so it wants to get at it so you want to have a pointer to the shared view model the shared view model that's looking at the model but the key here the reason it works here is that the view model is a gatekeeper it has walls up against that are protecting the model right that's its whole existence is as a gatekeeper so having a shared pointer to it it's not going to get damaged its whole job is to not allow damage it's this whole interface the whole programming interface to it is a protected gatekeeping kind of interface so it's a time where we can take advantage of the shared nature of having a pointer to it that we can hand out to point at all these views but we're safe because its whole job is to be a gatekeeper all right generic so I talked about this earlier array writing an array of ins array is kind of a generic because you can put anything in there let's talk about how this really works this stuff sometimes you want to build a struct and it has some data associated with it and you don't care what type it is right the classic example there we call that being type agnostic about that type I like to use the phrase It's a don't care because I don't care what it is twist though is strongly typed remember I said that that's a problem because you got to know what that type is Swift doesn't Swift does have a thing that is not typed but it's just for backwards compatibility with that old iOS stuff okay we never use it when we're actually using Swift so Swift is strongly typed every single thing every variable has to have an actual strong type and then we do that nice type inference to make it so we don't have to type it so much but they all still have a strong type so if we're doing array and we want to have ins in there we have to have a type for INT so how do we specify this type we don't care about well we use generics and here's what the syntax looks like for grx we're going to imagine array and let's pretend that we're uh going to write the array struct okay we're the authors of it we're going to need to have variables and functions that are of this don't care type like if I say append to the array and int well that that append method its argument has to be a type int so I need that type when I'm building my programming interface for array so let's look what it would look like approximately if we were to build our own struct array so here it is struct array and it's got its functions and bars in there but it's got angle bracket element that drangle bracket element means I'm array I have a don't care called elements this element can be any type any type in the entire Swift type system here most ever maybe a function I guess but it could be a certainly a struct or a class or an enum and this type is something that array doesn't care what it is but it's going to use it in its a its programming interface right Punk append there's the element it's a type element so when does this thing become a real type well of course when we create it when I say VAR a equals an array of int now element is int for me whenever I'm using a element is an ant so a pen takes an INT a subscripting returns an ends or it says it's as simple as that so you notice that this angle bracket thing it kind of matches what the guy who wrote struck did angle bracks right after brackets right after the name angle brackets right after the name when you're creating one I think the thing that makes this hard to understand is people are like wow I can't really think of an example of when I would use this right it's like a ray yeah I get it of course but so in our demo we're going to do that we're going to create our own generics it'll make a lot more sense when I do that here I just want to emphasize that you could have multiple of these generics so array could have multiple you can declare as many of these don't cares as you need right to Define your classes totally allowed there all right so this is actually called type parameters because we're kind of parameterizing the array type with that little element thing but I'll call them don't cares I just think don't care is much more visceral it makes much more sense I don't care I don't care uh what that type is uh now one thing about Swift's don't cares or it's generics it really uses them a lot it's really fundamental this with and we're going to combine it with protocols and it's really going to be powerful once you throw protocols into the mix of these don't cares I'll give you a preview imagine that you have a don't care that you force to behave like something okay now you've made your don't care be oh I care a little bit about this and that allows you a lot of flexibility to build programming interfaces we'll see that in our demo we're going to do that in our demo as well and so I won't talk about too much about it but before we can talk about that we need to understand protocols more and again I don't have time to talk all about protocols but let's get a little bit of an understanding what's going on with protocols you already have seen the view protocol so you're probably already getting an idea let me talk a little more formally about it protocol looks like when you see it in code kind of like a class or a struct that has no implementation right so here's a protocol called movable and it's got a function move by some int it's got a VAR called has moved and another of our distance from start but notice no implementation here the move by has no curly braces after it and the two vars just say get or get set so the curly braces after a VAR in a protocol just say whether this is a read-only VAR or a VAR you can get and set that's that's all it appears in the curly brace no implementation so protocol is just a description I'm sure you can all make the leap quickly too why do we do this because we're just describing Behavior here just functionality we're not actually providing a functionality we're just saying we want to have things that behave like a movable and if you want to behave like a movable you need to implement movable which means you need to implement move by and has moved and distance from start so remember that when we said we behaved like a view we had to implement VAR body if we want to implement movable and behave like a movable we have to implement all three of these things when you claim to implement a protocol or you claim to behave like a protocol you have to implement all the things in that protocol really no way around that I use this thing behaves like it's the same way as well like I call it don't care I don't care it's just more visceral here but conforms to is really the right words well when I have a struct that uh does this colon movable we're saying that portable thing conforms to the movable protocol okay I I like that it behaves like a movable but that's the the real words the real thing would say so everyone understand that that's what a protocol is just a functions and bars no implementation just so we can say that other things behave that way so we can make contracts between objects basically it's also legal to have protocols protocol vehicle that behave like other protocols it's kind of like we call this protocol inheritance because vehicle has its own VAR but it's inherited these ones so if I want to have a car which is a vehicle I have to implement all four things because I've inherited both of them so it's protocol inheritance that's totally allowed you can also of course have uh your car or whatever Implement multiple protocols that just means they have to implement all those things in other words I'm just saying here you can have comma another one comma another one and it's actually quite common to do this we'll be doing this in our demo we're going to implement multiple uh we're going to behave like multiple things uh so what do we use a protocol for well we do this have this thing what do we use it for well a protocol is a type I'm talking about the type system it's a type and so you can use it as a type a type of a VAR or as an art type that's passed to a function uh VAR body actually it's return type or is it Savar but it's type that bar byte it's a view something to behaves like a view of course we've got the sum in there which makes it so automatically calculated for us from our you know computed property but it is a type view and view is a protocol so you can do that I am actually not going to talk about that right now even though that seems like wow that's really important uh it's really it is important but there's other things that are more important so I'm not going to talk about that that'll be in part two of protocols how do we use a protocol at just a type a type of a VAR or a parameter so what am I going to talk about me well I'm going to talk about the way you've seen it already which is super important which is to specify the behavior of a structure class or an enum right we say extract content view behave like a view by doing this and we know that when we did this we had some things we were required to do like Implement our body and that we got a ton of things a whole bunch of funk you know view modifier functions like foreground color and all these things that apply to All Views I call This constrains And gains so this is using protocols for constraints and gains you're going to constrain some structs and classes or enums or whatever like constrain them such that they have to implement VAR body if they want to behave like a view but you're going to get gains like a whole bunch of functions or whatever and this constrains and gains idea is true for all uses of protocols Protocols are always constraining because they're making you implement certain things but they provide a kind of a framework for you then to get a bunch of gains and I'm not going to talk a lot about the games it goes back to this extension thing how we make this happen but constraints and gains is a big part of what protocols are all about right huge gains so we're going to see quite a variety of protocols even in the next couple of lecture like identifiable National equatable custom Trend convertible animatable tons and tons of protocols pretty much in everything we do we start doing these protocols and we do it so that we can both constrain things and gain things another use of protocols I hinted at before which is to turn our don't cares into care a little bits so if struct had been declared as a ray of element where element behaves like an equatable then you could only put things into a race that you could do equals equals on because that's what the equatable protocol is equals equals right when you say that x equals equals y that equals equals is actually part of a protocol in Swift called equatable so if luckily they didn't Define it this way because we can put things into array that aren't equatable or had they done it using this where Clause see that magic word where we could constrain that don't care to be a care a little bit and we're going to do that in our demo as well all right does that make sense what how we could use protocols here it's just a way to make our Dome cares a little more like we care all right so more about protocols uh in part two once we had extensions uh they're going to be the gains part of constraints is going to go off the charts uh over there and we're also going to talk more about some in any you know like some View and there's another one called any that are really good for using protocols as types like when you want to put things in Array and you want any you want the array to be any kind of a certain thing that behave like something then you have this nice any keyword that helps you put that in there so we'll learn all about that in protocols part two in a couple weeks there's an overview of protocols just understanding why do we do this protocol stuff it's just a way for structs and classes and enums and stuff to say what they're capable of and to demand certain Behavior out of other struct classes and enums right that's that's what's fundamentally about but the great thing is that neither side has to reveal anything about what they are variance to say whether they're a structure or class or an enum they just have to say yes I Implement that protocol so it's it hides the implementation behind this protocol and hidden implementation is good because you can then change it on you know you can change it without breaking anything because you've hidden the actual structure class that's implementing something it's also a way to add a ton of functionality via this extension thing which I haven't talked about yet it's really when we say that Swift is all a pro protocol oriented programming language this is why we're saying this because it's all about the functionality and we describe what the functionality is via these protocols right that's why we say it's a functional programming language protocol or programming language they go together this is why they go together so much it's how we describe the functionality all right functions this is the last type in the types this I'm going to talk about the only thing to get from these slides functions are types okay they're first class types and here's how it works you can declare any variable or parameter to a function or the return type of a function to be of type function right this Syntax for the type function includes the arguments and the return type of that function you can do it pretty much anywhere another type is allowed there are some restrictions actually but certainly parameters functions return values variables they can all be of type function so here's some examples this one here in yellow that is a type called a function that takes two ins and returns a Bool that's what that pipe is there's another type this type is a function that takes a Boolean and returns nothing that's what Arrow void means right there this is a function that takes no arguments and returns an array of strings and here's one that takes no arguments and returns nothing so the common type we see we can have variables that are of these types we could have parameters that are of these types that are pass two functions they're just types here for example is a variable Foo its type is a function that takes a double and returns nothing or here's a function do something it has an argument what which is a type function that takes no arguments or returns a bull it's kind of exactly what you expect the only thing maybe you wouldn't expect is notice none of these include parameter names so when you're specifying the type there's a function you don't include the parameter names just the actual types of their term values and arguments so how do we use something like this here's a VAR operation that's of type function that takes a double and returns a double and here I have a function that I wrote called Square and square happens to take a double and it returns a double okay it Returns the operand times the operands do we all agree that that's a function that takes a double and returns a double right well then I can say operation equals Square because operation is of type function that takes a double and returns a double and square is a function that takes a double returns a double so I can say operation equals square and I can now call operation just as if it were Square I can say let result equal operation of four and that's going to work because operation is a function that takes a double this is a double and returns one so result one's going to get it and it's going to be 16. because operation is currently Square but I could reassign operation and say operation equals square root so square root is a built-in function in Swift that takes a double and returns a double square root of it now if I say let result equal operation of four I get two you see because operation is a different function now I'm not going to take the slide time here to show this doing the same thing for a function argument because we're going to do that in our demo closures you've heard me talk about closures we often call them inline functions we call them closures for a reason hopefully if you're doing your reading I believe we're covering that in the reading this week closures capture the environment of the variables that exist when the closure is in line right a closure just an inline function we've seen closures all over the place so far in the code we've done in this class there's a lot of built-in support for it I think these view Builders were closures when we did the on tap gesture it had closure when we did buttons action that was a closure these were all closures um I'm not going to talk a lot about closures and how they capture the environment I'm going to leave that to your reading and then you're going to see me doing it in class it'll make sense then it actually turns out I've been on the UI side the capturing nature of closures we don't use it that much mostly you can if you want to think of closures as just inline functions you can do that but hopefully closures now make more sense how they are arguments to functions like remember z-stack content colon open curly brace and then we put the view builder stuff in there well content in z-stack is just a parameter to its creation and its type is a function that takes no arguments and returns a view that's all it is nothing special there that's all it is the only thing that's a little special is that it's a view Builder so it has that magic that turns the list of views into one Tuple view combined view so it's got that magic but when it's declared it's just up type a function that takes no arguments return to view we're doing functional programming here in Swift these are really really important right closures functions as types just we're just going to be doing this all the time in this class well I take some time on this because I know that for some of you it's like whoa functions as types I can't imagine this uh but it'll become very natural once we start having some variables and functions that take these as arguments you'll be like oh yeah yeah it's really really cool and it is really cool all right so that is it for the slides today like I say that's the longest run of slides I'll do uh all quarter but those are two important things to understand that mbvm thing and all these types and so let's get back to the demo what we're going to do in our demo is we're going to start building the model for our memorize game and then the next lecture we'll build our view model and hook it up to our UI here we go this is where we left off last time now I'm going to take a little time here to clean out a little bit of the code that we put in there you were allowed to do this in your assignment as well I'm just going to go through here and remove these buttons at the bottom I have these buttons down here just to clean up the code because you understand how that works it's not really helping to be in our face so you can remove this the spacer and the card count adjusters there we don't actually need this to be in a v stack I guess we could just have it be scroll View that right and we don't need the card count adjusters or here by the way one thing I would have done probably you see how I created a one-liner card Adder here once I added this I probably would have put this up there in line not and it probably wasn't worth it to have just a one-liner there thing it wouldn't be wrong but it probably wasn't worth it either and let's see we don't need card count anymore because we're not adding or moving so let's have this go back to being the Emojis indices instead that's everything yeah we're back to working over here we got our UI I'm actually not going to touch this UI in this lecture instead we're going to totally do model only and they're totally separated right so I shouldn't have to touch my UI which I'm not going to and I'm going to create my model in totally different file so I'm going to in xcode here I'm going to go file new file that's how I add a file to my project my model is going to live in a totally separate file you notice down that the Bible says user interface Swift UI view that's one you might choose if you're creating a view or not so we're going to choose Swift file you'll almost never choose these other things unless maybe you're doing unit tests or something like that most of those other things you're not doing C plus plus you're not doing metal probably maybe for your final project you might be but we're going to choose Swift file here I'm going to call my model memorize game memorize game and remember that it is the gain it is the actual logic and date of the game one thing important to do see what that group right there is and speak this is the group that is going to put the file in this is something students really forget to do so I'm going to take some time to make sure I make it clear what's happening here is you don't really want to put your files up at the top level where your xcode project is right you know if you look in your directory you've got the xcode project and then you've got something there called memorize that's this folder that's where you want to put your files so the one way to kind of make sure you're doing the right thing so if you click through this is the folder you want to put it in this one here if you don't do it it's not the end of the world but it's just going to start looking a little ugly because you're going to have random files Swift files up at the top level instead of putting them down in this nice memorize so we create it here it is here is our model and our model starts out saying import foundation not import Swift UI that's because we said create a swift file and set up a swift UI View and that's exactly what we want here Foundation that module is just arrays and ants and Bulls dictionaries non-ui things nothing in Foundation has anything to do with UI and if you yourself having to do import Swift UI here in your model you're doing it wrong because models are UI independent they should not have import Swift UI now our memory game is just going to be a struct so I'm going to extract memory game and it's not going to behave like anything for now so I'm just going to put the curly braces after there and when I build my model one thing I almost always do is try to stub out when I'm starting what does this thing do and what it's what data does it have associated with it just to get me started I might change my mind and use a different data structure or whatever but I want to kind of make that clear in my mind at least as some straw man before I start going so our memory game what the guy I should have left those cards up although they probably wouldn't appreciated that in other classes but and I'm not taking them up and down because they take a lot of hooking up there uh what what does it do well it definitely has a bunch of cards all right can we all agree but we probably need some kind of VAR cards and it's a ray of something I'm not sure what I'll call it the ray of card how about that so I definitely want that do we all agree with that and what is a how do we play our game right we basically choose cards right choose cards choose guard and matches or not or whatever so I probably need some function choose a card and it's also of this little type card and that's it that is my entire model because that is all our memory game does it has a bunch of cards you choose them and it plays now in your assignment two you're going to be asked to do some additional things like scoring so you're going to probably add something here The Score probably an inch or something of our end or or double if you want double Precision scoring uh you're going to add that but for our basic game that we had so far this is really all there is but what about this card thing it's saying cannot find type card in scope so we're gonna have to think about what a card looks like in our model so let's have a little nested struct called card you see how I put this card inside this struct that's not only allowed it's really good for name spacing because the name of this struct is actually memory game Dot card because I put it on the inside of it and that's what I want because I don't want some generically named struck card floating around in my app maybe I'm building you know an app that has 20 card games in it I don't want this card to be called card I want to be memory games card right so this nesting is really nice but it's almost entirely just a namespacing thing but it's nice feature there so what do we know about a card what kind of information it has well there's whether it's face up that's a big one we know that it's going to have what else might want to know about a card anybody think of anything if it's been matched absolutely still having is matched that's a bull what else do we want to know about a card yeah like what's on the card you know I didn't bring a car today but remember my cards had Halloween themed things on there witches and spiders and things so we got to know what's on there so that's interesting we'll call it content it's the contents of the card what type should this be string a string if it's we're doing Emoji right then string because emojis are strings I guess it could be character also there's a pipe in Swift called character and that'd be maybe okay but I actually have a better idea let's make this a don't care because we're making a card game we don't care what's on the cards put anything one on there jpeg images emojis whatever so let's make this a don't care so how do we put adult care here so first of all let's just make up a name for it I'll call it card content this type I'm just making up and I could put it here card content as I don't care right it comes in don't care but actually that's really not going to work very well because that would mean here I would have to say what the type was because remember whenever I have a don't care whenever I use this thing like here I have to then say what it actually is so that's a little bit of a conundrum but easily fixed because I'm just going to take this and make the don't care be on the entire memory game now memory game including its little substructs here all have this don't care that can be used anywhere inside memory game that's one thing to understand about I don't care is the wider the scope you put it the more it'll apply right to sub substructs so we have it look no errors okay we have no errors up here and we got this card content it could be any type could be a string for our emojis it could be image JPEG image it could even be some UI thing and I said this was you are independent it can't have anything yeah but whoever creates this memory game is going to be in the UI probably in a view model right the view model is part of the UI by the way the view and if you model both considered parts of the UI they're going to create the memory game they could specify a UI I think because their UI that's part of it so here inside here though we are not doing any UI so that's a cool feature too you don't care can make it so that you can use things in the UI kind of through your model but your model is actually still completely UI independent because it doesn't care it does not care what you put on these cards so that truly is just about all there is to do with our model here I have five minutes left let me think about this yeah let's do it I'm going to create my view model and we're going to come back to this we obviously haven't implemented our memory games logic but that's all there is to our memory game it just has the cards we choose them they're face up matched content so let's create our view model this is the gatekeeper between this our model and that UI that we've built that looks like this view view file right here new file begins to Swift file it's not a view new model is not a view and I'm going to call this Emoji memory game because this view model is going to be specific to Emoji memory game if I had one that was jpeg image or something maybe I would have a JPEG image memory game now it is possible I could also build my view model to be generic and it could have a don't care as well but I don't I'm not going to propagate that up but I could it's totally legal to have don't cares on your view model I'm not too for most super Simplicity of this demo I'm not gonna kind of go that far with or don't care so this particular view model is going to be specific to Emoji memory games this will only work for memory games where it's your emoji so here we go create the app and this one is going to import Swift UI because your view model is part of your UI it has to be because remember it's packaging up the model for the UI so it has to know what the UI looks like it has to be part of your your UI but I say that but the viewmodel is not going to be creating views or any of that stuff okay the view is going to be doing that but this will know about the UI and it will know about UI dependent things like colors and things like that images it knows about that so this is a class because it's going to be shared amongst everything and I'm going to call it Emoji memory game and a class if it had inheritance would be right here my superclass or whatever we're not going to do inheritance we don't need to inherit for any from anything to be a view model so we'll leave that off but it could also behave like something so you know something we behave like right some protocol could be here and you could have one without the other like maybe I don't inherit anything but I do behave like something that's legal too the only thing is that if you do have a superclass you want to list it first in that list before you list the things you behave like that's the only restriction there now my view model is the conduit between my model and my UI so it needs connectivity to the model because it needs to talk to the model right for example if the UI if you had an intent like choose a card The View model has to be able to talk to the model and express that intent so we almost always need variables here for our model now I'm going to call mine model this is a bad name this is a name that you would only use for instructive reasons okay you would call this something like game because that's what it is you always want to pick names variables what they are I'm going to call the model just so you constantly are going to be reminded what's model and what's view model and when we go back to our UI on Monday I'm going to call that Variable View model so that you'll be able to see them but which ones which so I have a model and what's its type anyone want to guess what the type of this model my model is here no guesses it's a memory game of string right because I said this was an emoji memory game and so it's going to create a memory game that model is a type string everybody cool with that I just took that generic type and specified the don't care I don't care as a string right there well now let's let's not go over time uh I'll stop so we have two errors two things to do right off the bat we'll do on Monday one thing emoji memory game has no initializers you see it has no init and remember I told you that classes only get a free init which initializes nothing and this bar has not been initialized so that's why it's making this complaint right here so we'll have to fix that obviously and the other thing I'm going to do right off the bat on Monday is talk a little bit what I was telling you about the partial separation versus the full separation uh mechanism we're doing full separation here because we're creating a view model in between but I'm going to show you how this model can be protected right now the UI could see this model because it's just a VAR in my class it can see the view model if you see it but I'm going to protect it so they can't see it so the UI cannot see it and then I'm gonna be a gatekeeper so we'll start that off on Monday and we'll implement the rest of this and then we'll go make our UI use all this all right that is it