MVVM in Practice - RWDevCon Session - raywenderlich.com

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi everyone welcome to mvvm in practice I know all of you were at the party last night right you got to check out the cool show the breakpoints they had a good song about NBC last night and it kind of reinvigorated me on NBC and I'm kind of into it now so I'm really hoping that my own talk will kind of reconvince me to go back to looking at some better design pattern like mvvm for example and before I get started I did want to say that you know and there's no Bible for mvvm in iOS it's definitely a something that everyone kind of does differently and so this is this talk will be kind of about my experiences with mvvm and my opinions but hopefully by the end of that you will be able to take what you've learned here and apply that to your own apps and you know make your own decisions and maybe you can come back to this conference next year speak on it and prove me wrong and with that said let's start with where we currently are with NBC so in the world of iOS we all know that NBC is king from the minute that we started developing on iOS we were pretty much told that NBC was the only way to go it was more it wasn't an option it's just the only way to go so let's look at what we currently have you've all seen this before the standard NBC diagram except this one has the sexier a green color on it but uh let's see we have the model here on the right side and you know the model it just holds like it could just be a struct with some properties it's just a basic data layer for your views you have the view on the left side there which is what the user interacts with and it basically displays information from the from the model and the controller which is the intermediary between the two so in this scenario the controller owns both of those and it communicates with them for example with the model through kvo or delegation and the view through user interaction with buttons and actions and things like that but we all know that I mean this sounds great in theory but we all know that that's not usually the case what we normally have is something like this the view and the controller become much more tightly coupled they become pretty much the same thing we have the model which is the which stays the same and you know the reason for this is as we've kind of developed as Iowa's community and our frameworks have been changing and now that we have the use of storyboards a lot more the view and the controller basically the same thing our view controllers are just they're so tightly bound with our views that it's really hard to distinguish between them in most cases so that's what we normally have and we now all know that it leads to pretty terrible ugly code so what is mvvm mvvm takes very similar ideas as NBC you can see it still has the three different components and let's take a look at each one the model stays the exact same it's still just our basic data layer we have the view on the left side which I put in parentheses controller because we're just for all intensive purposes we're going to assume that you know the view and the control are the same thing for this talk so if you ever hear me say view or view controller controller I'm probably talking about the same thing just interchangeably the new object is the view model and that's kind of the new intermediary between the two other objects and this is the bread and butter for for mvvm and so if you look now its main job is to take the model's data and basically convert that to a human readable format or human consumable and it's very out specific so it's basically taking that raw data and putting it in a format you can think of it as a converter kind of or formatter for the view to consume and if you look at the arrows rather than the middle object owning both others there's kind of a nice line from yellow down and then updating back so it's a very straight line rather than everything be able to talk to each other and let's look at its responsibilities really quickly so the view obviously is presentation and user interaction so it allows the user to be able to see the data that's underlined and also be able to edit it through through interactions and the view model again is just presentation logics you can think of it I do really like to think of it as kind of a format or converter and that's all its really doing is doing the very out specific responsibilities you have the model object that's just business logic same thing as them NBC so nothing really changes there and what is the problems that it's solving well NBC or the massive viewcontroller The Strokes been done a lot so don't expect any laughs on that one but it's really true and NBC has terribly massive view controllers whenever you do it and it's pretty much the pretty much makes all of our code bases disgusting and it happens the testability is really improved so I'll show you a little example later on but when you're putting all this logic inside of your view models that whole file basically becomes testable now and it's really awesome so now you don't even have to think about testing your view controllers really the code organization so again being able to split things up whatever C is actually trying to accomplish that's a huge benefit and code reusability if you're doing things with few models now you can kind of interchange which if you model a view controller does and it should completely change the look and potentially feel of your app without actually having to change any lines of code they're kind of inter swappable which is really nice the limitation with cons are always is right there's no no perfect answer so it requires binding we're going to be talking about that a little bit later but and mvvm requires binding at the core and iOS doesn't really give us that so we have to have some clever workarounds to be able to implement it there's a potential for boilerplate code so it gets really frustrating when you actually have to you know start a new thing and then get to create all these other files and do all the connections our standard practice will just be like throwing it all into a controller making sure it works and then going from there so that kind of can be frustrating for some people and it's overkill for simple abuse so again if you have a very simple like cell or something it feels really weird to make a view model when really just want to out its data in do its thing and it doesn't cover every case NBC also doesn't cover every case so we're not losing anything there so that's fine and with that side we're going to get start with demo one so what we're going to be working on is a project that I got my hands on through some practices that I won't speak up I actually got from the NSA and so we're going to be working on kind of fixing it up because unfortunately my hacking skills aren't what they used to be and when I was getting at some of the files got corrupted so we're going to have to go through and fix some of those for while we're doing it we're going to be implementing mvvm patterns you know because obviously the government put everything in one view controller they're not very efficient so why would yeah so alright so if everyone wants to open up their starter project so it's in the 3:06 session demo one starter and then mvvm mvvm dioxo a project alright it looks good alright so let's just run it really quick before you even look at anything just so we can see what it currently does at what state it's in all right cool nice little government animation there looks like we have a login screen here with some corrupted data down at the bottom oh I should say I guess it has data from the slide but the username and password from now on is going to be my name Attorney and then the password Swift so I'll keep doing that but I'll keep saying it for you let's see that's what happens let me just type in my name and then like drop gibberish for the password alright cool so it still does validation and we'll type in Swift authenticate cool but interesting it doesn't show us potential threats in the area right now so there must be something wrong with it so let's just log out all right so let's just move from there let's open the project up and kind of explore what we're looking at so we have the login view controller in the controller's folder that's obviously this first page we're going to be it seems to work for the most part so we're going to actually just kind of refactor this and I think one of the most important steps of nvvm when starting off is just to be able to reflect your code you already have rather than just starting something new so I think that's really powerful so I think that would be a good place for us to start one thing before we get going is something got messed up and the when setting up these projects for you guys there's an empty folder called view models and the path for it is all messed up and rather than walking through fixing it I'm just going to say delete it so that you're not tempted to put something in there later it will break beside that let's let's get going so we have this big login view controller it has a lot of you know constant users it handles keyboard dismissing so user interaction has text field delegates for being able to change the data based on what the user enters in text field and some validation logic and API logic at the bottom all pretty standard stuff but you can notice the file still is like 176 lines it's pretty big for how simple it does or for a simple it is and so let's see what we can do so the first step for us is going to be creating a view model for this class so I'm just going to put it in the main folder create a new file Swift file I'm going to call it a user user view model cool now that we have this file I'm actually going to open up the login view controller in the assistant editor by holding an option and clicking login view controller so it should have them side by side on it close this all right looks good okay so for creating our view model I'm going to create a class called user view model just empty right now and in our login view controller let me go to the top you can see pretty much over we're going to enter code there's a to-do there I don't know somehow the corrupted data added to dues on where it got corrupted so that's cool so right here we're going to create a private of our view model is equal to user view bottle so now that our class has a view model and start moving things to it so if you look right below where we just defined the view model we have these constants here we have constants for validation and we also have the user data model so if we look at the data model really quick what it is it's just a username and a password that's it it's just a struct so very simple but we can actually just move all three of those to our view model so let's cut those out get rid of the to do and move those right into our view model that's a good place for it right because it was very app specific information if our product or our design comes back and says like oh now now we actually need to have a 7 character password length or something it's something that the new controller shouldn't have to deal with is something that the view model would alright so now now that we have the user in there the view controller doesn't have access to any of its information so we're going to expose information by making some properties so let's create a username property of type string and all it's going to do is return the user username and then we'll do the exact same for password it's also a string and we'll return user dot password alright great so now our view controller will have access to those when it needs that's cool there's one more thing that we'll need to expose so if you look back at the app when I type in my name eeeek rainy I press ENTER to go to the next line it actually stars out everything except for the last three letters so we'll actually want to expose that and do that logic in our view model so we'll create a property called pro tected user name which is also a string and rather than implementing that if we go to our view controller and scroll to the bottom you'll see that there is a method called protected username that takes a username and does all its magic to it let's actually just take all of the contents of that method take those out and recopy them remove that empty method and we're just going to put the contents of that into our protected username all right our protected username property cool no problems there so now that we've exposed all the data that we need for our view controller we're going to go back and add some methods to our view model for being able to edit that data because right now there's no use we would actually always just have empty data at this point so let's add some some methods that will create an extension I think it's good in view models to always have an extension for your setters and getters and things like that so I'll create a method called or for updating the username called all right called update username it will take in a user name string and inside of that we're just going to do user username is equal to username and again we have to expose this because if you look our user is private so they don't have access to that from the outside but this gives them away we're going to the exact same thing for the password update password and up take a passwords string and set the user's password to that password okay so now that we have all these setters and getters done for view model I mean that's pretty much it for there for the most part we can go back to our view controller and start fixing some of the errors so if we go to our UI text field delegate on the right here alright you'll see our first air where right now we're setting the text field equal to the models user name but since that doesn't exist anymore we need to replace that with our view model oops view model dot username right so it's just being able to access that and we'll move down to the next method for when the text field did begin editing so this will help us start out the username when that happens so rather than using this method that we got rid of we can actually just do our view model view model dot update username and loops and you're sorry that was a confusing way of doing that but what am i doing all right wait what text will do okay Onew so I did in the wrong spot you'd regret you ready right right text what text is equal to view model dot protected using it thank you get rid of the to do alright so now we're going to move down to our text field should change characters and range so this is what's actually going to be updating the view model with the new data right so right now we have user username is equal to new string what we're going to actually replace that with is our view model dot update username and put the new string in there get rid of the two dudes as you go on and then we're going to do the exact same thing for the password field so that we can keep that up to date view model dot update password a new string all right so now our data should be our data should be up to date with a slow coke can opening all right all right so now that we've gotten that all done we need to actually start looking at our validation so validation is one of those things that shouldn't be done by the view controller because again it's it's very dated specific or out specific so we're going to move that to the view model now so if you look we have this user validation enum we're just going to get that out of there and move it to our view model to the top and and then we'll move our validate function or method out of here into our view model all these things work perfectly because we're still using the same user model within our other classes make this bigger and that'll fix that so we got our validation in there and the last last a little bit and I know I know this is just a lot of copy and paste and stuff but it's pretty much what you're gonna be doing is a is moving our our actual login method to there so this is a little bit of the debate here on where our login logic should lie a lot of people think should be in the view model some people make their own classes some people still think it can go into the controller I personally don't think it should go into the controller and put it in the view model makes a really easy free to be able to change what service you're actually logging in with so for testing and things like that so we're going to copy and paste the login method out of this extension Mazal get rid of it now to the bottom of our view model class and that's all the logic that we're going to put in the view model for now and the only thing that's broken now is if we go up to our authenticate action and again actions are great for our view controller because they should respond to the to the view or what the user is actually doing so what we're going to do instead is just change this to view model validate and view model dot login all right so now let's let's see what happens I think that that should be good so if we build and run now our app still logged in let's see if I just type nothing in awesome is still validating if I type in eternity and Swift we log in so it's still working so again nothing really changed from the outside but let's take a look at what we actually accomplished our view model now takes care of all the logic for our app and really within our view controller it's still just setting up the UI it has the text field delegate there which makes sense from being a view and all that's doing is using the view model to set some things and that's pretty much it so now our bigger class is down to basically its core components and our view models now definitely reusable and in a good state and so I think that's it for this and I know this is very basic right there but it's just a good step and kind of seeing the process going between you two and in the next demo we're going to be going into some binding and some more impressive things so some more worthwhile things so let's go back into our slides here or I guess we should is there time for question I guess it's not much of a question but more of a request can you slow down just a little bit sure and in that one that was a lot of copy and pasting and stuff so sorry about that but we have to get through it to get to some more interesting topics so yeah if you have the slides definitely go back and check them during this break if we have one hi why are you using a class instead of a struct for the user view model the reason I did that in this case is that I do think that the view model has a lot of potential for actually holding today and I might actually want that to be synced between multiple classes if I happen to be passing it around so an example would be like if it's a table view and I had view models for each cell I might actually want that view model to be held at the view controller level so in a lot of cases like I'm a guy that always is pushing for strikes but in this case with view models I tend to make them classes just for that reason because sometimes data if it's actually holding since storing some data you can get some issues there but again yeah you can always start off making a struct at the beginning until it doesn't work right that's kind of the way that I like to look at so I don't know if you're familiar with the Model View presenter that's like more prevalent on Android how would you describe maybe the two main differences between model view model and Model View presenter so I off the top of my head I don't know the I've looked at Model View presenter but not enough right now to in front of all of you say anything intelligent about it but what I will say is that a lot of these design patterns use very similar concepts and at the core they're really just trying to break up your code and so I mean I think any of these are far better than what we currently do I mean Viper's like another technique that a lot of people use so yeah sorry I can't read right now on that but anything's better Hey so I noticed that you still have the art you have a lot of interface builder like I'd be action I'd be outlet stuff in the view controller do you see people who don't use storyboards to do all the view like stuff in code getting the same benefits out of doing mvvm that's a good question and so I mean I think I feel like mvvm came kind of like how I said before because now we're so relying on storyboards and interface builder that the view controllers just become that but if you're doing things through code then it would make more sense to actually have a view that is doing that kind of stuff and the view controller is just kind of orchestrating creating that but I still do think that you can definitely use mvvm for those practices you'd probably just have an additional file rather than having it all in the one one place but it still helps for code reusability and breaking it up so when you have so this view model is actually really great I my question is sort of if you have multiple view models like your in our cable cell or table view controller something like that and you have to do an operation that you know uses a bunch of view models and it's a network operation does that does that logic sort of sit in the view controller then because it's not really part of one view model or if they're like a super view model that's sort of collect and it is a collection of view models or yeah I mean I have so that's kind of the issue that I come across with table views for example and you'll get that in the lab a little bit but I mean for example in the view controller there you might have a view model for the controller that has I've done this before like where it has an array of view models in it for each cell to use right so the top-level view model is able to say like how many cells there are and all those kind of things but the actual view models to display information will be in there and so yeah the view controller doesn't have to do the logic in that it just has the one thing and that view model it's its job to expose all the right properties and all the right methods to be able to interact with those other ones hey maybe a tool like this already exists but I was just thinking a great tool would be a sort of static analyzer that it reads your code and advises you you know which clap which pattern to move your particular part of your code into you know so if you could you know click a button say give me an M bbm it would read your your horrible mV yeah yeah that's like a great there's a there's a project for somebody yeah I'll definitely start that one I'd like to use it when you respect that did you have one what is one me so kind of tagging along the questions that they had back there and when you mentioned the login logic with the debate of that going into the view model when I've been looking at nvvm one of the hard things that because I see it everybody do it differently is what do you put in the view model because there's basic business logic there Service logic there's action reaction and to my understanding the core concept is anything that manipulates the view should go into the view model to make it as generic as possible right and then you can have a service layer to do the rest so my question to you is how do you identify what should go in the view it was even mentioned earlier like an IV action and I feel like that's an action reaction type of thing so it should be like the view controller controls the action and then you get a reaction where if it needs to display something it gets it from the view model yeah yeah yeah that's the big that's the big deal with that is I mean iodine identifying it is you know one of the hardest parts at the beginning right because knowing what should go where is pretty much the core of making this work better but you know with that I agree I don't think that the way that I have it this is for the demo is just having the actual logics of the API inside of there but yeah I do agree that there should actually be more of another object that's doing that and you can use like protocols for being able to swap in and out which API method they're being called from a view model so the view model shouldn't really be tied down deep with the API like that but I see you're saying about you know actions not being like this action reaction thing and there are ways and we'll talk about you know different functional ways of doing that but I think that in iOS starting at the place of as keeping IV actions and changing the least amount will help you to actually organize code in a better way and moving for all right we're going to get going again and get into a little bit more of the interesting stuff so again yeah a lot of that stuff we just covered was like the two most of us but also it's not what most of us are doing most of us I think write pretty ugly code sometimes so let's hop into data binding so coming from the iOS world a lot of people probably don't know what data binding is so we're going to just cover that really quick and jump into a little bit of a good demo just showing us how that works so let's look at what data binding is so at the core what it really is is the connection between the UI and the business logic and that connection should be kind of automatic you can think about it so for example you're basically linking the UI to a certain model object through the view model and what that means is that anytime that the data changes in the model the UI will automatically update right because they're linked because of that and so a little easy example would be you look at a counter object here it has a count property that's just an int and then we have a method called increment count all it's going to be doing is adding one to the count and then calling itself in a second so it's just going to keep incrementing one by one so if we have to show that we have a label we want this label to be synced up with the count property and all that means is that every time the count updates for every time the count property updates we need it to update the label and then we'll have something moving on like this right pretty simple but not something that we've directly used before and then just to go over what two-way binding is it's just what it sounds like changes to the model update the UI and user input updates the model so that's just basically linking them both ways so anything that happens on the UI side would update the model and in turn because you updated the model it would update the UI just a little example of that same class counter we have a label as before but now we have an increment button so when we click that button it's going to update the count which in turn updates label pretty simple so how do we do this in switch there is a number of ways that people try to make this work because there's no direct way like other languages where you can just set them up in some way and some format that they automatically update each other and one of the first options is kvo which is not that awesome and just to remind everyone what it looks like you have the object to observe you have to make an NS object and the property dynamic which kind of gets away from our sweeper style and we have to actually rely on the framework now we have our don't worry about all this code but it's just to remind you you see in the net method we have to add observer and we have to use string Lee typed parameters here to actually listen for the property which of course is terrible and and in the future can cause crashes or like if we ever changed the property name and then we have this method that we observed value for keep out that we actually get the value and we can do something with it like updating the UI and again we have to do D init which also is prone for error so let's go on to the next one here are next option because we're not going to do KBO we don't want to rely on that would be delegation this one everyone knows create a protocol this protocol could define a property change for example the object over declares the delegate object and it'll have a method to be able to update the internal model and then every time you do that it's just going to call the delegate and say hey something change and here's our observer it's setting itself up for her the object that's observing set itself up for a delegate and it'll do something so the negative of this is it's very robust in the sense that we have to do all this work and we have to explicitly call the delegate methods at different times the positive though is that we can actually have a lot of control using this so rather than just having some kind of message that says hey the object changed we can actually very specifically say hey the object changed in this way or something like that you can picture a table view rather than saying all the data changed we can actually say like for example if we were doing a paging application or something we can say like oh we added data to it so only so the other object that's listen you can actually just update the new data rather than refreshing the whole table with you so that's kind of a positive of delegate of delegation but we're not gonna use that for now another option is functional reactive programming which a lot of you've heard of some people think it's the future some people are very skeptical about it a lot very few in the grand scheme of things are actually using it so let's take a quick example of what that looks like looks like Chinese it's not it's not that awesome and I really didn't feel like making an example for it so that's what you get yeah personally I personally don't use it I mean I have on the side but I haven't use it in production code so I don't feel comfortable enough actually say anything but it definitely solves a lot of these issues that we're talking about so it's definitely worth a look and then our last option that we're going to look at which we'll be implementing now this property observers so in this example you have an object to observe who is what we're trying to listen for and we can use the property observer didset to actually be able to to tell our observing object that data actually changed and you can see here we create the object changes value and we'll get it print out the one thing you'll see here is that we're actually not actually updating the listener anywhere right we're just printing something out so how can we accomplish that in Swift in a good way that makes us feel like awesome developers that's called boxing so just to take a quick look at what a box would look like you create this class object called box it's generic you would have four at the it's value that it would have inside of it is a generic type the did set listener right there is what arming property observer is where we'll be notifying the listener and you just create an INT method that sets the value that's like a box at the base level but you're looking at that and you're like okay that doesn't accomplish anything we're just hiding the value within another thing and you know we use it like that so the way that we can actually get some real power out of a box is by adding binding to that so let's take a look at what we currently had that's the box that we just had before just with some spaces in between and what we can add to it now is a listener so this is just a closure that takes a generic parameter and returns void the actual inner value in the did set property observer we actually can call that listener now with the new value and we add a method called bind at the bottom and that bind is just going to pass in a list that same kind of listener it'll set the listener and it'll call it immediately and the reason that we call it is so make sure your view is now binding a property on your view model to some part of the UI and when it initially binds rather than waiting for the next update to actually call the list they're in the didset it'll actually call it right away so that our UI can be synched up with our data from the get-go so we're going to take a look army will actually be implementing this in the lab so don't worry if doesn't totally make sense but the that's what at the bottom for you guys in the back but the Box int you just create it like we did before so right now we're making in a box of type int with 42 when we bind it we want anytime the value changes to actually print out the value changed and print out the new value so right away it calls itself and it says value change to 42 if we set it to 100 it will get called back and say value change 100 so let's actually see how that works in our demo too so you can leave off exactly where we left off last time but if not if you fell behind because I was going super fast in my speaking then you can just open up the demo to starter and you should be good to go okay so we're back where we were we have our view model on the left and our view controller on the right so what we're going to be actually working on is if you look at the app we have this jumbled up data at the bottom here we're going to what this is supposed to be is kind of a two-factor authentication token so what it would do is it would generate a token there and you know as a government employee you'd see that and then you'd actually have to write it in your other government thing to prove that you should be authenticated so let's start implementing that so we know that our view model has to give us this information right so we're going to go below our protected username here and add a new property called access code we'll make it optional and and it did set just for testing purposes let's just print out something like access code just so that we can see when it changes once we get it implemented we're just going to printing that out oh then we're just gonna be printing it out when it updates okay so how do we add the logic for this all that got removed from this file so at the top where our other constants are we're going to add a new constant called private let code refresh time and we'll just set it equal to 5.0 for now so that's gonna be how often we're actually going to be updating the code and we're just doing it for five seconds I'd be actually really hard if it was to factor to be typing that in really fast but it'll be good for demo for vistas okay so now that we have our refresh timer let's go to the bottom of our project and I'll actually create a new extension just to break things up for user view model and I will make it private because no one needs to know about this alright so what we're going to be doing here is creating a method that will actually initialize the access token and keep refreshing every 5 seconds in this case so we'll create a method called start access oops code timer okay and all we're going to be doing in this is calling access code and setting it and luckily we have a helper for this we have a login service that we can actually do generate access code all right so that's going to be changing it but right now it's only doing it once so what we're going to do is kind of that same little trick that you saw in the counter from the slides is we're just going to be calling ourselves every five seconds so we'll just do dispatch and rather than using the normal just a fat which takes weird parameters and it's annoying I made a helper method called dispatch after like this takes a number of seconds so we'll just pass in the code refresh time and in the block let's not use autocomplete anyway let's not use all that let's use trailing closure that's way cooler all right get rid of all that and inside of here we're actually going to do the updating so all we have to do is call ourselves so I'll start access code timer but right now this does create a retain cycle and I know sometimes we don't care about that in our demos but I can't live with myself there we go so now we if we ever get rid of this login view we won't have a retain cycle got to make that like that all right cool so let's build and run really quick and just make sure that our access code is working correctly it should be printing out at the bottom oh it won't yet we haven't even called it yet awesome all right so we're going to create a new init method now to actually call it when our code starts so if you look here below our access code let's create a new and knit method and we'll call it init with user so that we can actually do some injection later on in our testing so we can actually set up the user and we're just going to do self that user equal to user and we'll just do start access code tiger all right so now now our access code timer should start and it should be updating so I'm going to build and run again and okay we see right there it changed that's awesome and nice alright so every 5 seconds it's going to be changing and generating a new string to end but right now we still have our jumbled data are doubled access code in the app so how are we going to keep that label updated with this new value in our view model well we're going to use binding or a box and binding like we just learned so I'm going to open up the project navigator and I'm going to create a new file we're going to call it a new Swift file called box for simplicity click create okay so now basically what we saw in the slides we're going to implement and hopefully it'll kind of get more ingrained as going through it but we're going to create a box that's a generic right then the box needs a listener so we're going to type alias that and make it list in an inter listener all right we're going to make it a type of generic and returning void so it'll have a parameter that's generic that returns a void will actually have a property for that listener of the listener type we'll make it optional so we don't always have to have a list around a box it would be pointless to not but why not we'll have a variable for the value that's of type T and in the did set which is where all the power kind of happens this is where we're going to be calling the listener object if it exists and passing in the new value so we'll constantly be updating whoever is listening with whatever the new value is we'll create a just a default init method with let's see type T and it will just sell top value equals value all right and last but not least the most important part we've got to have our bind so bind listener of type of listener will make that optional as well so that we can nullify the listener at any point if we want to stop listening and in here we do self dot listener is equal to listener and we'll immediately call the listener with whatever the current value is so that the UI can update right off the get-go and so that's it I does some things that maybe we're not used to but let's kind of look at how we can use that now let's go back to our view model we won't need the we won't need the box code anymore because I've done let's look at our access code so right now we're just accessing it from the W controller and it's not a box so let's actually do that so if we change the access code because food into being a box so this is how we define it we're defining the access code of the box of type optional string so it doesn't have to have a value we can get rid of all this didset stuff and let's initialize it with a default value of nil so it's just an empty box right now but it's still a type string okay now in our code we should have an error so in the start access code timer it doesn't work anymore what we have to do is change access code to access code dot value is equal to the login service so now we're actually setting that box okay so now we have that box value and that's it we can go to our login view controller just here on the right and go to viewdidload for example and it's time to bind so what we would do here is do view model dot access code dot bind and then in inside of disclosure is where we'll actually be binding the object right so what we do is we do self dot what is the label called code label so this is that label that has all the junk right now dot text is equal to dollar sign zero so the parameter that's passed in will be setting to the text value and one important thing though with binding is right now our view model is owned by this controller right and this bind is retaining self so I know that's a lot of times we would just use week but this is actually a great place for unknown and the reason for that is because our view model should last at least as long as our view controller right it's dependent on that so we know that it this will break the retain cycle but it'll stay around as long as we need all right so that works or not there let's see if it works let's do build and run and hopefully what we'll see is the label automatically updating itself oh it did initially let's see if it does it again in five seconds nice alright so right now all we did is we set up a bind for our label and we can do something in there so you can imagine if you had your view model with a bunch of different properties you can bind those up to each different elements on this case it's a label and automatically have those thinking's so now in this case anytime anything ever changes that value so if later down the road we end up adding some way that the access code can change from another class this will automatically stay updated on't have to know that oh we have to call some delegate method or we have to do something to update anyone that's listening so that's pretty awesome and pretty powerful one thing I think since we probably have a little bit of time yeah since we have some time I just wanted to show you a little glaring issue that we might have with our view model so if we look at our view model at the top you might notice that our username and our password objects are just accessory right now right like the view controller can only determine if something changed by keep by keeping on checking on those right so it's just going to say like hey what's the user name right now what's using right now we have no way of updating them if the user name actually changed from some other source rather than the view controller so what we could do in theory is make these into boxes as well but let's look at what happens when we do that so if we create a box for this user name for example and let's get rid of the information there okay cool so now we have a box which we can now bind to let's fix a couple errors so user name value now so we always have to get the value of the box rather than the user named up value rather than just using the value itself all right and I think if we go to our viewcontroller there's one more issue we have to use view model user name value here okay so we fix the issues if we build and run right now nothing will happen nothing will work actually so what we do here is we're going to add the binding code view model the access code or sorry view model dot what is it user name dot bind and we'll actually just inside of here do a print so all we want to do right now is just see every time the user name changes so user name changed and we'll just print out the past and parameter like that okay and if we run that right now we say okay cool maybe it'll be changing Oh something about I didn't initialize the value let's just create a user name as a box a and B string okay so if I build and run right now and I open the console user name change initially so the initial point worked for what as I type nothing's happening we should be seeing stuff okay so the reason for that is that we're never actually updating the user name which is now a stored property right rather than just accessing what's in the user we're never updating it but one of the cool things and this is something I use all the time it's since our user is a struct anytime we change one of the user name or password properties it'll actually set a new user right it's it's a it'll copy it and so what that means is that in our user object now we can actually do a did set and do user name dot value is equal to the user dot user name so every time in our text field that we update the user did that method will actually get called and it wouldn't if it was a class so that's a good benefit there so if we run this now and open our debugger user name changed and as I'm typing it'll work so that's kind of cool so now we're able to see two different examples one where we're just using these computed properties to just access user and one where we can actually listen to a store property on the view model so that's pretty powerful and really cool and I think that's it for there one other thing I should show and now that I did all those changes to user won't work but if you look in the NB BM test folder I have a login test dot Swift class and it's right now it's all commented out but what I did is I just made some very basic tests on our view model and you can check those out and just kind of see how it works right now there will be an error because of those last little changes I just added on with the box but the cool thing is that when using that test you pretty I think I have like 95 code coverage for this view model now and we don't actually have to deal with testing our view controller because again our view controller is just doing very basic basic UI things we shouldn't really be testing out our UI kit right we don't need to know that a label actually presents the text when we set it so that's really powerful and cool so check that out and I think that's it for the demo we have time for questions yeah so yeah just raise your hand if you have a question I just have a quick question if you can elaborate a little bit about using weak versus on himself sure we'll go into a new talk now so the reason I'm using unknown there right so the difference is we're breaking the retain cycle by either using weak or unknown and generally we use weak when it's okay for the object to become nil at some point throughout the process but in our case since we have the view model should always exist while the view is this right like the view models core to display in information we know it will always live there that long so we use unknown to still break the retained cycle but in a way that kind of saves us and I know some people always like well why not just use weak all the time right but there's actually like a lot of different things you can read a lot of reports on ends up but weak has performance costs in the long run because it makes itself optional and so just generally speaking when you know that the objects going to live as long as the retaining object you should make it unknown that so the first option that you'd dismissed with Swift was KBO and for obvious reasons but building especially apps for OS 10 there's a lot of data binding built-in to interface builder do you know of a way that that is being used or is that being looked into as a way to add something into Swift where you can get string bindings similar to kbf I mean all these other things that were talking about with like react and rx Swift and things like that kind of have their own implementation for doing these binding and thing and those handle all the cases of having the UI Bale to bind and using signals to be able to update each other so I mean those those frameworks already kind of do that I don't know if there's like an active work from Apple to be adding anything like that I highly doubt that they're focusing on that right now but the reason I like to show this example of creating your own box rather than using those other frameworks is because I like going from this to one of those is super helpful it's a weight easier jump because again if you go just jump into then now it might look like Chinese too and so yeah I'm not sure if that totally answers your question but yeah more questions or we get alright then we can go ahead and start the lab all right cool so let's look here so in this lab you're going to be working on implementing the second page of or the second screen of that and what that means or that screen is supposed to do is display a list of all the nearby threats and I know you're all probably anxious to find out if there's any threats at this conference I've seen a lot of sketchy speakers walking around and so I'm curious myself so what you'll be using is delegation in this case so again I want to look at more native approaches to be able to accomplish similar things so in this case you're going to use delegation so again the negatives were that it's a little bit robust but at the same time it gives you a lot more power so hopefully they're using something like a collection view you'll kind of see how delegation is a good candidate for using using or sorry where table views are good can table views or collection views are a good candidate for using delegation so yeah if you have any questions or anything while you're going through it feel free to raise your hand or come up to meal I'll try to walk around and help people and yeah thanks all right hey everyone we're just going to wrap up really quick here hopefully you enjoyed the lab if you got a chance to do that but I just wanted to wrap everything up if you where we go and I'll start writing incredible code so let's just recap really quick what you learned in this session the first demo we learned how to refactor nbc-2 mvvm and the point again that was very you know like basic but that's what you have to go do I think it's actually better for you to just go visit a code base right now that already works find something simple take that code and try to refactor it into just in that component using nvvm and making sure that everything works the same way out to word and doing that you're going to start in graining this thought process in your head and moving forward it'll be easier easier for you to just imagine a new part of the app as doing that and implementing it from there straight on in demo 2 you learned about data binding so this was a basic example you learned about box in a box and data binding this is something that's a lot of different frameworks that I was talking about before our built on is something like this and I think understanding of that the core is what will really help you move forward because once you understand that data buying how it works moving to these other frameworks is way easier and it's kind of powerful you can actually use it for a lot of other things besides mvvm right like I can think of other ways that I would use data binding or at least the box objects in my app for any kind of structure and then in the lab you did mvvm with delegation and that again was to kind of show you that we don't need to use all these crazy ways all the time like you can actually just get started using mvvm using some of the practices that we already know delegation everyone here should be very familiar with and comfortable writing in their sleep so it gives you a lot more control over what messages you can send back and forth and yeah okay so some of the just to recap some of the benefits and limitations of mvvm so first of all it breaks up your code by responsibility this is obvious and that's what all design patterns are trying to do but I should write that it simplifies testing so again I kind of missed the part where I showed the actual unit test going because I started adding some boxes to some objects that the test didn't have ready but anyways it simplifies testing now you can focus on not what to test or like when to test you just get your view model test that whole thing and like for the most part you're pretty good at that point you don't have to think about creating view controllers and your tests and then somehow making them layout their sub views and then testing labels and things that's if you're doing that you're doing unit testing wrong I'm sorry if it also improves code usability so again if you kind of structured your view models in a way where they're using protocols then you can just be supplying in and out view models for different views at any time and the view has no idea what it's getting but all it knows is what it needs to display it stuff and so that's really cool and but the limitations again because there always are it requires binding or other work around so we saw some of those examples it has a potential for boilerplate we had talked to some people about how at the IDI side when it's a very simple view like even in my example it feels weird that you have a user model object with just two properties and then I'm having to create properties in my view model to just expose those right I'm just basically duplicating my work all the way across and that can feel like a drag imagine how our model object had ten properties or more which they often do so that can feel like a drag even though it definitely is improving your code base and then sometimes it feels like overkill so on the other side when you get to a big app you might get so complex like I know when I first started you know I read some article that felt all cool and for mvvm and then all of a sudden I started just trying to design like one of the hardest new things in my app to do that and I just go crazy and I made all these objects and they're all talking doing stuff and then I got the end of the day it was just like get reset - - hard like get rid of it all like it just wasn't working and so you know that's where it kind of becomes a problem and then it doesn't cover every case but NBC also doesn't cover every case so we're not losing anything there we're to go from here Astro talks about this a lot so check out the blog that's kind of like where I got started looked at some of his blog posts to get me going I think we even have different opinions on something so that's fine the whole goal is that you can kind of learn and figure out for yourself what's the best take on everything reactive cocoa or rx Swift if you dare so if you speak Chinese or if you just kind of feel like going for it that's definitely a good place to go I would recommend that you actually implement it at a base layer like using the techniques I showed in your apps to have a better understanding before jumping over and it'll be an easier transition go to your own code base go work on your own code base right now just go refactor like one simple view when you have some time and you'll kind of start seeing some of the benefits and if you have any questions after this my twitter attorney you guys should know that now if you're typing in the password to the code base or in to the out for a long time but I think that's it so yeah thank you [Applause]
Info
Channel: raywenderlich.com
Views: 88,117
Rating: 4.941606 out of 5
Keywords: mvvm, mvvm design pattern, design patterns, mvc alternative, mvc design, mvvm example, video tutorial, screencasts, mvc video tutorial, mvvm video tutorial, app, app archectecture, apps, app development, mvvm app development, mvvm app design, mvvm session, live session, live coding, tutorial, live tutorial, live tutorial session, rwedevcon, rwdevcon tutorial
Id: sWx8TtRBOfk
Channel Id: undefined
Length: 57min 50sec (3470 seconds)
Published: Mon Aug 21 2017
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.