I've put together a collection of my best iOS Developer interview question videos here's a list of what we'll cover and they are time stamped in case you want to jump around now of course I can't cover every topic you could possibly get asked about in an interview but these are very common topics that are asked about all the time all right let's get started the vast majority of iOS apps have some sort of networking component to them data lives on a server and the IOS app needs to go to that server download the data and
display that data nicely to the user on the device today's video breaks down the basics of how that works we talk about what is Json and how to use it and then we write a network called encode using async await and Swift and this process is a foundational skill for any iOS Developer and will almost certainly be asked about during an iOS Developer interview before we dive in I want to say that Learning Network calls is very tricky it took me a long time to fully grasp them and it took me writing a ton of
Different network calls to fully understand them this video is meant for the beginner to give you the foundational skills on a simple example but I want to encourage you that hey you're not going to be a network call Pro after this video or any singular video on the internet it is going to take you time and repetition to learn this so I want to let you know that before we dive in this is meant to be one of your first steps on this journey of Learning Network calls okay so we need to download data from
a server and make it look pretty on the device when working with data from a rest API that data will be formatted in what's called Json short for JavaScript object notation here's a basic example of a user object in Json you can see it's encapsulated by curly braces it has key value pairs in this example we have a username a bio and an avatar URL that's a super simple example let's look at a real life version of this in the GitHub API documentation so I'm going to get a user section of the GitHub documentation over
on the left here you can see all the different areas you can go into so I see I'm in user uh get a users what I want to be in Now so this is documentation it'll tell you what's in the API over here on the right you see this default response now because I have my screen blown up it's a super little window but you can see right here's this curly braces there's a login there's an avatar URL down here you'll see a bio now this is just an example of you know the response what
I like to do is take this URL here in the curl copy it and then if you open up your terminal you can type in curl and then paste that URL now you see it's api.github.com users and then username this is like the placeholder so let's delete username and I'll type in my username s-a-l-o-e-n0400 you can type in your GitHub username hit return and this returns real data from the API so you can see here's my login see here's my bio iOS Developer specializing in Swift you can see you know follower count so this is
what I really example of Json would look like and again you can see it's encapsulated by the curly braces you can see the key value pairs right the key is login the value is sln0400 and this is an example where I just get one object back it's very common that you're going to need a list of objects So I'm going to down here in the next prompt here curl same thing except now I'm going to do slash followers and I know this from the API I just want to show you if I hit return this
is going to be a list of my followers now so I want to show you this we'll scroll back up to the top here's where I typed it now the reason I want to point this out is because this is another common example of Json you see this bracket here it probably looks familiar from an array so here we get back an array of my followers right there's the login the Avatar URL and then you see it separated by comma here's another follower here's another follower so I want to point this out because yes the
Json could return a single object or could return a list of objects I mean you can do a lot more but these are two very common examples that that I want to introduce you to for working with Json and a quick note about the GitHub API this is an example of an open API some apis require you know authentication where you have to have a login and a username some apis require an API key because this video is meant for the absolute beginner right writing your very first Network Call learning this tough subject I wanted
to keep it as simple as possible just know that Network calls are very deep subject we're just scratching the surface and dealing with API keys and oauth that's an adventure for another time we're sticking with the absolute Basics okay so now you know the data is formatted in Json you've seen real examples of it so let's get back to the task at hand and that is we need to download this Json somehow convert this Json into models in our Swift Code base and then use those Swift models to build our UI to show the final
result to the user when I'm building this I like to break this down into Steps step one is to build out the UI with dummy data and this helps me visualize you know what I'm working with step two is to look at the Json respond fonts that you see here and use it to create the models in our Swift Code base and then step three is to actually write out the networking code and then step four is to use that networking code and connect the UI with the final result okay step one build out the
UI with dummy data here I am in xcode I already have this built out but as you can see super basic Swift UI code I wanted to save some time here and this step goes hand in hand with designing the feature of course if you're designing your own app right if you're working for a company they have their own server they have a designer giving you a spec that's different you build what they give you but if you're designing your own app this is the step where I look at the Json and I say okay
this is the data I have to work with right I have an avatar URL I have a bio right I have the the Twitter URL I can only build my GitHub profile screen to include what data I get back right and this is what happens when you're working with someone else's API whether it's GitHub YouTube Twitter you're limited by what they give you so that's why in this step look at the Json build out your fee feature and again I like to build out my dummy UI to visualize what I'm working with and in our
simple GitHub profile user page we're just going to have the profile picture their username and their bio now that we have the basic UI sorted I move on to step two and that is creating the models that I'm going to use from the Json so here next code let's do that I'm going to Create all this in one file by the way I'll talk about that in a second but let's create a struct called git Hub user so this is the object for the user that we're going to use now what properties do we need
again looking at the UI we need the profile picture the username and the bio now pulling up the Json you can see the username is called login I have the Avatar URL and I have the bio so that's what I want to work with now back in the day a swift developers used to have to parse the Json manually and it was a major pain I'm not even going to get into that nowadays we have a nice protocol called codable so I'm going to make GitHub user conform to codable you can see here and real
quick actually you see the documentation right there bull down down here says codable is decodable and encodable this just combines both of them but the use cases when you're decoding something that is when you're downloading the data from the server you have to decode that Json into your models and codable is when you're uploading something say you're creating a tweet we have to encode that tweet on the app into Json and send it up to the server so we're just going to do Codable technically since we're just pulling we could just do decodable but we're
going to keep it as codable for both of them now when working with codable your property names need to match the Json exactly now there's a more advanced caveat you know if you want your property names to say whatever you want you can use coding Keys that's out of the scope of this beginner course you know if you just make your property names exactly match your Json that is what you're going to do 90 of the time so we'll say let log in and that is of type string and then going back our Avatar URL
you can see is let Avatar underscore URL and then bio is just bio so let bio of string now I'm going to contradict myself a little bit because here's our GitHub user and we are matching our Json exactly so this will work but in Swift right look at our Avatar URL that's snake case we don't typically write our property names using snake case it's not how we do things in Swift right we use camo case so instead of Avatar underscore URL we're going to do Avatar Capital URL and when we write our Network call we
can create our decoder and there's a property called convert from snake case on our Decoder that we're going to use that's just a sneak preview we'll come back to that so that's one potential gotcha when you're matching your Json exactly and again this is just because that Swift convention to use camel case now we have our model object ready to go okay so let's write this network call and I'm going to do this right on our view here in our Swift UI View and this is purely for educational reasons and your understandings I remember when
I was learning it was very helpful for me to see everything all in one place right now in a real project you know you'd refactor your network calls into a view model or an API service network manager your GitHub user object would be in another file but again when I was learning having everything in all those different places it was difficult for me to make the connections in my head to know what was what so to be clear I am spelling everything out on this screen to keep everything in one place so hopefully you can
make those connections you know this video is not about refactoring and project organization but just knowing a real project you would organize it and refactor it but again keeping everything in One place for the ease of your understanding okay so the function here on The View we're gonna say func git user and we're going to mark that async because we are using async away and we're going to Market throws because we want to throw errors now you don't have to mark this throws but when working with network calls there's so many things that can go
wrong right they may not be connected to the internet uh maybe you know you have the wrong URL or the server is down right so many things can go wrong with a network call so you pretty much always are going to have it throws here and we want to return a GitHub user that's the object after we make our Network call that we're going to return from this function so open curly brace close curly brace now the first thing we need is the URL that we're going to point to to get the data from if
we go back to the GitHub API here right get a user that's what we're working with and then here you can see the URL this api.github.com users username so I'm going to copy this back to xcode we're going to say let endpoint equal and it's going to be a string paste this here now we don't want this Dummy username right you can put in your name I'm going to put in my name or put in whatever name you want of a GitHub user now in real app maybe the user you know can type this in
and then you search based on that but again we're just hard coding to demonstrate how the network call works so now that I have my endpoint we're going to use what's called URL session which in Swift is basically how you make Network calls let me type out the code and then I'll explain it so I'm going to say let data comma response equal try oh wait and again this is uh Swift concurrency async await URL session Dot shared dot data from URL this is an example of a get request so there's four main types of
requests you can make with network calls there's the get which means you are just pulling down data read only there's post which means you are posting data to the server you're sending things up to the server right get would be downloading post would be uploading right if you created a tweet and uploaded it to Twitter and then there's the put which means you're editing something and then there's delete which obviously you would be deleting something those are the four Main basic types of requests again we're doing a get because we're just downloading and pulling the
data so from URL but you can see I need a URL object and if I go back to just typing in the data so we can see that quick little documentation data from you can see I get back data in a URL response so that's why here I say here's data and response so what the data is it's going to be the data you know the Json the response is response codes we'll get back to that in a second so data from URL so now I need a URL object this looks like a URL but
this is a string so in Swift We have a URL object that we need to convert this string to and when we initialize URL object it returns an optional so we need to do some unwrapping here guard let URL equal here's our URL string right we're initializing a URL from a string the string we're going to pass in is that endpoint that we just had up here so we're going to pass in this string to our URL initializer and it's going to return a URL object which we're going to use in our URL session but
it can return an optional so all I'm doing here is handling the error we'll say Throw error we'll come back To that in one second I just want to finish this placeholder so the URL that we're going to pass in is the URL that we just created right here on line 32. let's talk about these errors real quick right we're throwing this error isn't going to work we can create our custom error objects to handle each error specifically and this is a common practice with network calls so again I'm just doing this all in one
file maybe you'd have a separate error file but we'll say enum GH for GitHub error I'm just putting the GH in front of it to name it something you can name it whatever you want I just can't be normal error because that already exists in Swift and our custom error needs to conform to the error protocol so I can say case we'll say this is invalid URL so if the URL fails I'm going to throw the error called GH error.invalid URL I'm going to put this on a new line for structural purposes so again we're
creating a URL if that URL can't be created we throw the error invalid URL and then if we have a good URL we're going to call URL session share.data from that URL and that is going to return data in a response so now we need to work with the data in the response so First we want to check the response because what the response is if you're familiar right 404 not found you know 500 server error or 200 everything went great these are all the HTTP response codes on the internet and this this is your
opportunity to handle those accordingly so let's do that we'll say guard let response equal response as I'm going to cast this as an HTTP URL response so I can get the codes here and then get the response dot status code again this is that 404 not found or 500 server error so I want to just make sure it equals 200. 200 means everything is A-Okay we're good to go else and I want to throw but I don't have the air yet so again down here in GH air we'll say case invalid response and then I
will throw GH air dot invalid response now again this is the opportunity I'm only checking for 200 if we have 200 great we're good to go if not throw a generic invalid response error this would be your opportunity if you did get a 404 not found or 500 to show very specific errors to that code again for your app and when dealing with network calls it's very important to be specific about your errors right have you ever used an app and it Just says on unable to complete the task and you have no idea what's
wrong this is your chance to tell the user exactly what is wrong which is what you want to do and for the sake of time I'm just giving you a couple examples to point you in the right direction so now that we have a good 200 status code that means everything was A-Okay now we want to work with our data to convert the Json into our GitHub user object so to do that we want to do a do we want to create our decoder so let decoder equal Json decoder right this is how we're going
to decode this Json and then this is what I talked about earlier we want decoder dot key decoding strategy equals dot convert from snake case so pulling up the Json remember Avatar URL had that underscore space URL well again in Swift we use camel case not snake case so luckily Swift has a built-in it'll convert it for you so that's why if I go back to my user I can have Avatar URL in camel case because what convert from snake case does it deletes the underscore and capitalizes the first letter that's what convert from snake
case does so again this is the gotcha where you may not want to match the Json exactly Now you could match the Json exactly and keep it snake case have the underscore your Swift Code will just look weird and other Swift developers will be like what's this snake case stuff here so that's why I want to use convert from snake case but again if it's one word or it's already in camel case you want your property names in your object to match the Json exactly again with the exception of you know converting from snake case
okay finally let's return try decoder dot decode and then we want to pass in a type and then from data so when we're decoding we have to tell it what type we're decoding into so we're going to say GitHub user.self that declares the type from the data well that's the data we got back here from our URL session up here in line 36 so we're going to type in data and then a do try you know requires a catch this error handling and then if this fails we will throw again we need another error we're
going to create another error here called case invalid good data and then up here what we're going to throw we're going to throw GH air dot invalid data and again all I'm doing is giving you an example of how you can really Customize your errors and let the user know exactly what is going wrong if something goes wrong if you get this invalid data 90 of the time the reason this will fail to decode right because what this line of code does here is it is trying to use our decoder here using codable to decode
the data we got back which again is this Json you see here into a GitHub user object in Swift that's what this whole section is doing now it will fail again ninety percent of the time there's many other reasons it can fail because you didn't match your property names correctly so our Network call is written let me run through it again as a refresher right so we're calling git user we marked it async so we can use async await we also marked it throws because we want to throw a few errors because again so many
things can go wrong in a network call and we're returning a GitHub user and we need to know what endpoint to pass it to right right so this is the user's endpoint and again where I got that from was the GitHub rest API documentation I want to get a user like you see here on the left and you can see the URL for that that I already have highlighted is right here So the documentation will let you know what URL you want to point to so back to xcode cool I need to create a URL
object from this string that's what we're doing here as long as that's good then I use my URL session to get data from the URL again this is an example of a get request but we're just downloading right we're not uploading anything we're not editing anything we're just downloading the data and I need to pass a URL that I created up here on line 32. now this returns a tuple of data and response so again the response is what we talk about first this is all the you know 404 not found 500. we want to
check to make sure we have a 200 so we're doing here that means everything is good to go cool so if we don't get to 200 we're going to throw the invalid response error show it to the user you know handle it if this is good we go to 200 back now we can work with our data here so that's what we're doing here in this do try catch we create a Json decoder and the reason I created it was so I could set the key to coding strategy and because I want to convert from
snake case right that's this Avatar URL issue we had here if I didn't have that issue with snake Case on Avatar URL I would not need this line of code right here okay and then like I said we try to use that decoder to decode the Json into a GitHub user and from that data again that's the Json we got back if that works we're good to go we're going to return a GitHub user the function worked properly if we fail to decode we're going to throw the invalid data error okay so that is our
Network called written now for step four is to actually use this network call and connect it to our UI to show the final results okay so I'm going to scroll up here to our Swift UI view remember this is normally refactored this get user this is probably in a view model somewhere so it's not as messy but again keeping it all in one place so up to our view here so in order to call this I want to below the padding here we'll do a DOT task now a DOT task is used for as you
can see at the bottom here adds an asynchronous task to perform before the view appears it's kind of like on appear if you're familiar with swift UI but it's ready to go for asynchronous code for example that our async await Network call so that's what I want to do here I want to call this but I need to set a User equal to what we return right we're returning a GitHub user object but I don't have the concept of that in my view so we can do that real quick at State private VAR we'll say
user and then it's up type GitHub user and that is optional because when the view first loads we don't have that right we don't have it until we make our Network call so in order to call our async Network call here I want to do do we'll say user equals try await get user So This Is Us calling our Network call right here so when the view appears I need to have a catch here let's just put that in there for now we're going to handle the errors in a second but yeah so I am
setting the user that I created here and this is a state variable which means in Swift UI once my network call is completed and I set this user to the user I get back then the UI will update which we'll get to in a second so I'm setting user equals to the result of my network call which again we went through that I'm doing all that Parts in the Json setting the user cool so if it is successful great I set the user to the user I get back my UI updates we got to write
the code for that in a second but if it's not successful Here's where I can handle the various errors so I would do catch GH error dot invalid URL and then I would print you know in valid URL catch GH air dot invalid response and obviously you wouldn't just print this you would show like a pop-up or do whatever you need to do in your app you know to let the user know what's going on and then finally catch GH error.invalid data print and again I know this looks long and tedious but hey if you're
going to do proper error handling and showing the user exactly what's going on it is long and tedious I could just have one error be generic and you're unable to complete the task at this time please try again later that's not helpful to the user so you could be lazy and not do all this that's not very good and then we'll do our final catch which is kind of like the catch-all we'll say unexpected error do command B should work okay so like I said this is just an example of uh handling uh very specific
errors okay so now that I have my user the final step is to update the UI to take in the actual user data so for example username is not just text username right it would be user Dot Login and that is an optional so we Want to provide a default thanks we'll say login placeholder of course if you're building a real UI you'd want to make this look nice some placeholder now for the bio again user.bio and if that is nil we'll say bio placeholder whatever that is for you and then now we need to
handle our Avatar URL which for that we're going to do async image which is nice for Swift UI we don't have to make a separate Network call switch your eyes this async image already built in it does take a URL so we'll say URL from string and that will be the user dot Avatar URL and if that is now if our users know instead of passing in the Avatar URL or passing a blank string which will give us a placeholder that's what this placeholder is right here and we'll use our Circle here as the placeholder
that means while it's loading or if the URL comes back nil then it'll just show that gray Circle again if you're designing your UI make the placeholder nice looking let me actually take out this frame and put it on the async image itself so I can reuse that okay so now I get back an image so there's just a normal Swift UI image which means I can do things like dot resizable dot aspect ratio dot fit And finally dot clip shape of a circle because I want it to be rounded okay so to recap basically
I created the async image which will pull the user's Avatar URL create an async image from that if that doesn't work we'll show the circle placeholder and then the text I'm using for the login will be the user's login if that's nil show the login placeholder same thing with the bio so now when I run my preview let's refresh it it should make the network call there you go sl0400 there's my profile picture there's my bio let's try some other developers here so I just need to change the username in the endpoint like I said
in a real app maybe the user could type this in you know however you want to do in your app but let's say two straws run it back we should see Paul's stuff yep there's Paul's profile picture his username his bio uh John sundo we're making our Network call it is working and I know this video threw a lot at you with writing all the network calls the async await throws you know async image definitely don't be afraid to go back and re-watch it like I said at the beginning Network calls are very tough topic
if you're just learning them it's Going to take you a while you're going to have to watch many different videos you're gonna have to hear it explained many different ways you're gonna have to write 50 of them like this is a process and again this video was meant to be one of your first steps in that process a very common iOS Developer interview question is to explain the difference between classes and structs I'm going to teach you the answer to that question by explaining value types and reference types and I've got a nice little analogy
using Google Sheets in Microsoft Excel to help you remember and then I'll teach you when you should use classes and when you should use structs classes and structs are both ways to create objects in the Swift programming language as you can see here I have a class called car which is creating an object the car has a year make and model more realistic examples in an app would be something like a user or a product but for the sake of explaining this concept we're going to stick with our simple car so the main answer to
this interview questions on classes versus structs is that classes are reference types and Structs are value types what does that even mean well let's write some code to show you an example so I have my car class here let's create a car we'll say VAR my car equals and I'll initialize the car you can see I need to pass in a year make and model so say 2022 make Porsche color gray so I've created a car with the year make and color because this is a class this is a reference type what that means is
that it's a reference or pointer to specific data so for example if someone steals my car right so if I do VAR stolen car equals my car right so I took this my car object and set it equal to stolen car well now I have two variables again it's a reference they're both pointing to the same piece of data which is this car here so on the stolen car if someone wants to make you know my car a different color it's going to affect the original my car let's see this here so if I do
stolen car dot color equals yellow and then if I do print my car dot color you notice I'm not printing stolen card.color I'm printing my card.color if I run that you're going to see my car.color prints out yellow and this is where the Google sheet analogy will help you remember this So the way a Google sheet works right you share the sheet with multiple people and then when multiple people make changes to that one source of truth right they can all make changes to that Google sheet it's a shared document that's kind of how reference
types work again I change the color property on the variable stolen car but it also changed the property of color on the variable my card that's demonstrated on line 18 by printing out mycard.color so again classes are reference types and if you create multiple variables of the same class they're all going to point to the same piece of data and if you change that piece of data on any one of those variables again we have my car and stolen car is going to change that property for all of those variables that are all pointing to
that same piece of data that is a reference type now let's talk about structs and value types so I'm going to copy this class here and then I'm going to comment it out just so you don't lose all the code here and then we'll paste that in here instead of a class being a car we'll do a struct of a car and then trucks have member-wise initializers that's another topic so I don't have to have that in it and I have my struct of a car same thing again they're both ways to create objects in
Swift but structs are value types remember classes or reference types structs are value type types when a value type gets passed around it is copied and this is where the analogy of the Microsoft Excel spreadsheet comes in right if I have my own Excel spreadsheet I made all my changes to it I save it I make a copy of it and I email that copy to you well now when you get that copy that's yours you can make all kinds of changes to that spreadsheet you can do whatever you want to it it is not
going to affect my original file version so that is the analogy for Value types where again reference types was like a Google sheet where everyone can make changes to the one source of Truth let me demonstrate that in code so I'll come up here copy the my car variable what kind of gonna do the same example but you'll see now if I do VAR stolen car equals my car well now that it's a struck that basically just made a copy of my car and assigned it to the variable stolen car so now if I do
stolen car.color equals we'll say red now now When I print my car dot color again my car was the original object that I created it is still going to be gray right help right that's how it should work run it great there it is right and if I did print stolen card.color now it's going to print out red because again struct is a value type so it created a copy of my car and assigned it to stolen car we're again as a class to reference types all pointed to the same underlying data now let's talk
about when you should use a class versus a struct in the pros and cons of both a benefit of classes is that they have what's called inheritance which means I can subclass or car class up here I can create a subclass of car maybe called race car that inherits all the basic properties of a car right our year make color but I can also add more properties to that right I can maybe add a number right race cars have numbers and a team race cars have teams so you can see it gets all the basic
car stuff but I can add on the unique stuff that a normal car doesn't have but a race car would have that's called subclassing and when you subclass you inherit everything in the parent class another common Example and I'll show you some documentation that will help out here is if you say class my custom button and that inherits from UI button and if I option click on UI button I'll go to the documentation so when I make my custom button I don't want to reinvent the wheel everything Apple has done to make a button work
like look at all this stuff in the documentation that you you get customizing color Edge insets you know setting the title I'm going to go down to the bottom here of all the properties that are on it right set title title color all the stuff that Apple has built in a button you inherit when you create your custom button and then now you just add differences you want to make to make your button custom maybe you want it to be a circle and always be pink who knows but that's what you can do with inheritance
you can build on top of the UI button now that sounds like a really cool benefit but as you can imagine when you're inheriting everything of a UI button which also inherits from UI view you're starting to inherit a lot of bloat and extra baggage you may not need so that is where structs Come in and value types if you don't need all that inheritance you can just use a struct and that's why trucks are a lot more lightweight and performant and if you've written Swift UI you'll notice a lot of Swift UI is built
on structs for that exact reason right a swift UI view is a struct so it can be created and redestroed all the time and it's not so heavy so when you need an inheritance or you need a reference type that's when you go for a class when you don't need inheritance you want something lightweight and performant then you go with a struct generics can be intimidating and confusing angle brackets single letter types protocol conformance what's going on here this video teaches you what generics are with a basic and real life example and then we'll talk
about The Balancing Act you have to do with generics because once you learn them you're going to want to use them everywhere but you can easily add unnecessary complexity to your code so let's make sure you don't do that generics can eliminate co-duplication by creating a general solution that can handle various types here's an abstract example to help illustrate the Point let's say you have a function that can drive you home from work this function will work no matter what the vehicle is right it doesn't care it could be a motorcycle a cyber truck a
Porsche 911 GT3 as long as it has a motor and wheels the function will work it doesn't care what type of vehicle it is so you have the drive home function and then you have the angle brackets with the T colon and drivable in the middle so this is a protocol conformance or a constraint on the generic so inside the angle bracket we call the generic something right now we're calling get T that is convention to use a single letter variable typical T sometimes U sometimes V you could if you wanted to like name it
vehicle as you see here but again common convention is to just use the single letter T so we're calling our generic T and then after the colon we're constraining it or we're telling it what protocols it has to conform to so like I said our function will work it doesn't care what the vehicle is as long as it has a motor and wheels and that is our protocol drivable so you see drivable here requires a motor and wheels and you see our function takes in the Parameter called vehicle which is of type T which again
is our generic T can be any type as long as it conforms to drivable so a quick example you see I have a Porsche 911 GT3 object and a motorcycle object both of them conform to drivable they both have motor and wheels and then you can see I create a 911 by initializing the Porsche GT3 and I create a motorcycle by initializing motorcycle and you can see I can use my function here by passing in either the 911 or the motorcycle the function function will work it doesn't care what actual type it is as long
as it conforms to drivable that was a high level example just to introduce you to the topic if you weren't quite following we're going to dive in deeper so let's write a basic example all from scratch to practice this concept we'll create a function called determine higher value and if we want to make it generic that's where the angle brackets come in and like I said we're calling our variable t or our generic T and if you just wanted to take literally any type no constraints this is enough but we do want to constrain our
generic and again all constraining your generic means is it has to Conform to a certain protocol so we're going to conform to the comparable or comparable whatever protocol so again we'll take any type as long as it conforms to comparable and then we're going to take in two parameters here we'll say value one is of type T and then value two is also of type T so they have to be the same type right I can't compare an INT and a string have to be the same type and now we'll determine the higher values so
we'll say let higher value equal we'll do a turn every operator here value one greater than value two if that is true value one will be the higher value and then if not value two there might be a better way to write that that looks repetitive but whatever not the point so we'll say print higher value is the higher value and you'll see us use this okay so again let's walk through the function signature we're determining the higher value we're saying hey we want to take in a generic well we're going to name that generic
T and then we're going to constrain that generic it has to conform to comparable okay cool and then we take parameters whatever parameters you want value one that is of type T and value two is of type T so they have to Be the same type so let's see this in action so I will say determine higher value of you know three and eight and then if I run it you'll see 8 is the higher value cool that was an INT now let's do strings of Sean and so by the way strings are alphabetical order
when you compare them so do that it'll say Swift is the higher value because Swift comes after Sean alphabetically so again anything that's comparable we ins floats doubles strings even like look dates so I can do date dot now or I can do I don't want to create a whole date so let's do date dot distant future right so the distant future date should be the higher value so I'm going to play this and we'll see year four thousand and one so January 1st 4001 is the higher value than right now okay so like I
said you're passing in strings in doubles it doesn't matter this function will work as long as it conforms the comparable now if I try to compare a date to a string like that's not going to work you'll see me get an error so it does have to be the same type again that's why we're designating it t here but as long as they're the same type you have this one generic piece of Code that can handle various specific types and generics are all over the Swift language behind the scenes so look at something you use
all the time in an array so I'm going to say let number array and I'm going to declare it like this so I can dive into the documentation say array repeating let's say I want to repeat the number 3 10 times and you'll see over here right there's my array all the threes but the reason I did this because I want to dive into the documentation on array so if I option click on array open in developer documentation you can see right here the Declaration array has a generic of an element so what that means
is if I have an array of ins I can still do things like numbers array actually I have to make numbers array a VAR if I'm going to manipulate it here numbers array dot append new element and you can see it knows it's of type int right here so if I append a 4 I can do that to the numbers array now let's do VAR string array equals array again repeating here this time we'll repeat Sean and we'll just do it five times so now I still have this dot append on array right I don't
have to have a specific a pen Function for Strings and a specific a pen function for INS because in our array is a generic of type element I can do append count first of all the stuff arrays have no matter what the type is whether it's an INT or strings right so I can do string array dot append and we'll say Swift right and that will still work and then again back to the documentation that is because array is a generic of type element so again generics all over the Swift language behind the scenes now
let's look at a real life example from an app I built for my course GitHub followers the app we pulled down a list of followers you can tap on a follower to see their information so we have a network call called Fetch user as you can see here now I've removed all the air handling and the response validation to make this super simple code just know that if you're not familiar a real Network call is much more involved than this but again stripped it away for Simplicity of generics so this is not a generic function
right we're calling fetch user from URL it returns a specific type of user and then you can see down here in the do try catch we're decoding user.self So this network call is very specific to users however it is very common in an app to make a network call to fetch an object and then decode it using codable very very common like here's another example if we were going to do fetch repository you can see very similar code fetch repository it returns a repository type we make the network call we decode it using decodable or
repository.self it's the same code just swapping out user for repository so instead of writing separate Network calls for for each specific type we have right this is only an example of two what if we had five different types we were doing we can make this generic as you see in this function signature again the angle brackets after fetch data we call our generic T the constraint we put on the generic and again the generic constraint is just making it conform to a protocol we want it to conform to decodable because we're fetching data from the
server and we're decoding it we need to pass in the type this 4T DOT type because we need to you know let the network call know which type it's going to be and then we pass in the URL and then you can see we're returning T which Again is whatever type we pass in that conforms to decodable and then you see the code is the same right we make our URL session share.data make the network call in the do try catch we're decoding it but instead of user.self or instead of repository.self you can see it
is T dot self so we're making the T the generic so we can pass in a user a repository or whatever other object we have again as long as it conforms to decodable now that you understand the basics of generics let's talk about The Balancing Act because once you learn this skill you're going to want to put generics everywhere right every little bit of repetitive code you're going to want to make it a generic or the dreaded trap of oh let's future proof this in case we write more Network calls like this spoiler alert most
of the time when you future proof that Future Never Comes that's called premature optimization and you should avoid it because adding generics everywhere can really add unnecessary complexity to your code so here's my advice only use generics when it's like a slam dunk use case in my opinion even going back to our Network calls and GitHub followers we're fetching A user or fetching a repository that was only two Network calls that were exactly the same even if there's only two I wouldn't use a generic because concrete types are way easier to read way easier to
understand what's going on now like I said If instead of just a user or repository maybe you're fetching a project or you know five other things from the GitHub API and now you have five or six of these Network calls that are all the same to me slam dunk case use a generic that's awesome but again if there's only one little bit of repetition don't automatically throw generics at it you're just over complicating things we just scratched the surface on generics they're a very deep and Powerful topic but hopefully this video gave you the fundamental
understanding to start you on your journey of learning generics and help you answer that pesky interview question about generics what are all these parentheses what's up with these dollar signs escaping like who are we running from trailing closure syntax what does that even mean look closures are tough these are all things that confuse the hell out of me way deeper into my career than I'd like to admit let's Make sure you understand closures a lot faster than I did closures are self-contained blocks of functionality that can be passed around and used in your code to
put that simply they're functions that can be passed around to illustrate that let's create a closure and put it to good use here I am in my xcode playground all I have is an object of a student that has a name and a test score and then I have an array of those student types we're going to create a closure to filter out the students by their test score VAR top student filter and that is of type now of type is the key word here to explain this because just like our student has a name
that is of type string a test score that is of type int our closure is a variable that is of type and this is where the parentheses come in it's essentially the function signature so I'm going to type this out and we'll walk through and explain it so you get one set of parentheses and then the return type is the other set of parentheses and that equals and then the actual curly braces to define the scope so let's walk through these parentheses one by one because I know this confused me greatly when I was first
Learning closures so the first set of parentheses is any parameters the function takes in however we don't need to name them we just need the type so we want to take in a type of student now of course if you're doing something with an INT or a string that's where you would pass this in we're dealing with our custom type here of student so that's why we passed in that and then this is going to return a Boolean I'm going to back up and explain this real quick because you may have seen you know sometimes
it doesn't return anything so you may see empty parentheses or sometimes if it doesn't return anything you can see void as well those empty parentheses and void are the same thing just two different ways to say it in our case we're going to pass in a Boolean because this is a filter we're going to look at our student and if our student has a score of greater than 80 we're going to return true that means there are top students so that's why we passed in a student and returned a Boolean we just want to check
if they have a score greater than 80. so return student but we can't do this quite yet we're missing a piece here where we need to name our parameter Here student in you've seen this before so this is basically the parameter name so we can use it down here in the scope of our closure so I can do return student DOT test score I don't know why the audio complete's not cooperating but greater than 80. let me run it real quick just make sure I didn't miss anything should be good cool everything's good to go
and actually maybe this will help let's write this as a function so you can compare the two because I'm assuming you're familiar with functions a bit so I just copied and paste that so to write a function right it's Funk top student filter I'm going to put an F after it for function and then instead of having all this right here I'm just going to go ahead and delete that right you would say hey this takes in a student of type student it returns a Boolean and here's our scope and we would say return student
DOT test score greater than we'll say 70. so to compare the the function and by the way these are very similar you can even use the function you'll see we'll do that in a second but I just kind of want to put these side by side so you can see how similar it is like I said it's a property With the name of type just like you know string and int the type here is the function signature right it takes in a type of student and returns a bull that's what's going on here type of
student returns a bull and then here the student is what we named it we can name it whatever we want just like we can name this parameter name anything we want and then you see obviously in the scope is basically the same so hopefully that clears up what these parentheses are when you see that in the closures again it's just any parameters and what it returns just like a function parameters and what it returns so now that we've defined our closure up here in top student filler filter filter has a t there we go but
anyway now that we have our closure we're going to pass it around using our variable so let's do that let's say let top students equal students by the way students is our array up here this is our array of all of our students dot filter and you can see our filter takes in a closure and just like we said here is the type taking a student and it returns a Boolean so the only way we're going to be able to pass in our closure is if it matches that perfectly right Takes in a student and
returns a Boolean let's say our closure up here had a student and an INT right by the way they say you can have multiple types maybe student Dash age if you had multiple types in your closure I guess would be multiple parameters now our closure wouldn't work because it doesn't match exactly so I'm going to delete that because I want it to work so now I can just pass in top student filter and now let me paste in a quick little for Loop to save some time just basically just prints off the student name we'll
run it and that filter should work yes we have Luke lay and Ahsoka those scores have to be greater than 80 right Luke has an 88 Leia 95 Ahsoka and 86 so our filter is working by passing in our closure there again closure is a function that can be passed around and this is a lot neater than if we wrote it out so let's demonstrate that well real quick let me demonstrate how we can also pass in this function so let me do top student filter with a capital f at the end right that's what
this is up here and then now when I run it were greater than 70 this is why I did this so we can differentiate so now when I run it I should get a longer list of students which I do because more students up here are greater than 70. so again whether it's a property or a function very similar a closure is a function that can be passed around and used now that you've seen that let's start talking about shorthand and what all these dollar signs mean so I'm going to rewrite this filter here or
I re-autocomplete it here so filter is included so as you can see this is going to give me a closure that takes in a student and returns a Boolean if I hit return I get a little bit of the shorthand and it automatically goes to Trail enclosure syntax which we'll talk about more in a little bit but the introduction if I do command Z Trail enclosure syntax is when you can omit this argument label when your closure is the last argument we'll talk a lot about that in Swift UI because Swift UI uses that heavily
a little bit more in the video but our closure is our only parameter so of course it's our last parameter so when hit return we get trailing closure syntax which is omitting the parameter names in the parentheses and just going right into the body of the closure like that so now we have Our argument name and we don't have to define the type the reason we don't have to define the type is because it knows this running filter on an array of students right our students array right here has Type inference it knows it's an
array of students it's not an array of strings not an array of doubles or anything like that it's students so that's why we don't need to define the type and we can just call this whatever we want you can see the capital S for student means it's the student type we're going to name it lowercase student just as the name again we could have named this person right you can name it whatever you want student obviously makes the most sense but we know it's of type student so here we can write the same code so
I'm using simple one lines of code but obviously this could have been 40 lines it could have been super complex filtering code that is why you might not want to write it out all at once you might want to put it away into a property so it can be reused passed around very easily versus right now I'm writing it out like on site within the scope of the filter again it looks fine right now because it's just one line Of code but I want to use this simple example to show you the shorthand these parameters
come with a built-in shorthand syntax you've probably seen dollar sign zero or dollar sign one what that represents is each parameter here so right now we only have one so it's dollar sign zero in a second I'll show you an example where we have dollar sign zero and dollar sign one so how I can slowly make this shorthand is if I don't want to use the actual named property here get rid of that and get rid of the end and then now instead of student down here I can replace that with dollar sign zero because
I only have one argument there is no dollar sign one it's just dollar sign zero so I know that's the student and now when we only have one line of code we can omit the return and if we're going to omit the return we can put this all on one line to be nice neat and clean so that's your introduction to the shorthand and with the dollar sign zero and the dollar sign one is so right now we just have top students we filtered out all the top students based on if their test score is
greater than 80. now let's actually sort this so you can See an example of dollar sign zero and dollar sign one and just more repetition on closures because again closures are tough so let's say let student ranking equal top student so we only want to take the top students dot sorted by and here again you can see this is an example when we have two of these parameters we have student one and student two and it returns a Boolean so if we were to write a closure for this one we would have to make sure
we had two students in it right so we'd have to be student student and then of course we would write different logic to do all the Sorting here but like I said I just want to point out that oh and we would also here have to have student two but I wanted to point out that if you are going to use a closure in a built-in like sorted or filter it has to match exactly or if you wrote a function yourself it has to match exactly so I'm gonna do a command Z to get our
closure back to that and I'm gonna hit return and walk through that shorthand again so like I said you could have student one student two and then do return student one dot test score greater than student2 DOT test score and this will sort them Based on Whose test score is higher but again back to the shorthand we don't need Student one student two I know that is dollar sign zero and dollar sign one so we can get rid of that to make it cleaner and then I'll replace student one with dollar sign zero and student
two with dollar sign one now if you add three or four parameters up there it'd be a dollar sign two dollar sign three and so on like I said before we don't need the return so we can put this on one line and there you go so like I said if you've seen a lot of these closures with the dollar signs and dollar sign one dollar sign two those are essentially shorthand Syntax for each property like we just showed with the student and student one and student two I hope that cleared up all the dollar
sign Syntax for you I know that was confusing for me as well when I was starting out let's talk about trailing closure syntax before we get on to to escaping let's go to a swift UI project to see how this is everywhere in Swift UI here I am in my course called dub dub grub by the way you can check this out Sean allen.teachbowl.com if you're interested if you've ever written a v-stack or an Htac in Swift UI you've used trailer enclosure syntax and if you've written a lot of Swift UI you've done that many
many times so let me explain that here I am in just a basic little button let's say I wanted to put this text in a v-stack so I do that v stack cool now when you wrote the v-stock you just did open curly brace closed curly brace and you probably thought nothing of it if you didn't understand Trail enclosures but that's what it is it's a trail enclosure so let's talk about what a v-stack really is so if I do v-stack hold option to get all the parameters there right they're just optional and Swift UI
is riddled with optional parameters and default values I'll show you that in a second but what I want to point out to you is cool here's a parameter you can dot leading spacing we'll say 10 but look what does it end with it ends with content and what does that syntax look like to you that looks like a closure and the closure is the last argument so we can omit it and just do the trail enclosure syntax which is is going right into the body of the closure the braces and real quick to show you
if I command click onto the v-stack jump to definition Go to the init here you can see the alignment has a default value of Dot Center spacing default value of Nils like I said default values are everywhere in Swifty that's what allows that clean syntax and here you go does this look familiar We'll add view Builder that's a different topic but you can see the last argument is the content that closure looks familiar right it takes in no parameters and it returns of type content so back to the v-stack real quick that is why we
can get rid of this and that's why you can write a v-stack which is a simple v-stack open curly brace close curly brace Trail enclosure syntax all over Swift UI if you've ever written a network call prior to async await you've dealt with completion handlers or closures they're the same thing let's take a look at this function signature for get followers by the way this goes up to the GitHub API pulls down a list of followers to display on screen okay so parameters username page completed though this is the closure here and it's marked at
escaping we're going to talk about what that means but to review the closure right our closure takes in a result type and the result type returns a follower Or GF error and then it returns void so it doesn't return anything so again like I said this could easily be just closed parentheses same exact thing but why is it marked at escaping well the closures that we were doing before like when we were filtering the students those happen instantly right they get called right away they happen right away no big deal on network calls this fires
off and it goes up into the cloud to GitHub API and depending on your network right it could be super slow it could take 10 seconds could take a millisecond maybe you're not even connected to the internet could take forever so what escaping does is it allows the closure to live on past the lifetime of the function that called it speaking of the function that called it let's actually go look at that so on the follower list VC which is that screen you can see here in the get followers function I call networkmanager.share.getfollowers and again
as you see here we're using the trail enclosure syntax because that is the last argument in the function but what happens get followers fires off and then that function is done however the closure is still living it Outlives the function because it is waiting to get the information back from the network call so that is why you mark it at escaping so it can live on past that now this is where things get a little tricky with retain cycles and memory leaks because most of the time when you do a network call you're capturing a
reference to self because once you get that list of followers back whether it's 10 seconds later 15 seconds later one second later you have to update the UI on the phone so our closure still has to have a reference to whatever called it in this case it's a view controller in UI kit so that's why you got to be careful with Escape enclosures we marked it weak South here so it's a weekly held reference so it can break that gets into memory management automatic reference counting all that stuff that's a whole another topic I have
a video on that I'll link to that in the description if you want but that's what escaping means essentially the closure has to live on past the life of the function that originally called it if this was helpful and you enjoyed my teaching style check out my courses at shawnis.teachable.com see you in the next video We're talking about filter map reduce I'll show you how to chain them together then we're going to talk about compact map and Flat map a good way to think about these higher order functions is they are shorthand Syntax for a
basic for Loop filter map and reduce iterate over an array and spit out their results into a new variable so I'm going to need an array so I'm going to copy and paste that here as you can see I have an app portfolio of my object here of an indie app which has a name monthly price and users and as you can see I've created four Indie apps with different names monthly prices and number of users and thrown them into an array called app portfolio this is the array that we're going to use with the
examples on filter map and reduce let's dive into filter first so let's say I want to filter through my portfolio of Indie Ops and pull out the free apps so right now fit hero with the monthly price of zero is the only free one so let's say let free apps equals say app portfolio so this is the array that I'm going to iterate over dot filter and you can see it takes an enclosure and a simple way to write this is With a trail enclosure I'll explain that in a second so we'll do dollar sign
zero dot monthly price equals equals 0.00 a brief explanation of this Trail enclosure is the dollar sign zero it's every item in the array for example the first iteration over the app portfolio array is the Indie app creator view dollar sign zero the second iteration equals fit hero dollar sign zero over the third iteration equals buckets and so forth so it's going to check every element's monthly price and if it is equal to zero it's going to spit it out into this free apps array so when I come down here in print free apps in
the console down here you should see just fit hero print out Indie app fit hero monthly price of zero but the way Filter Works is you just need to pass in a conditional so this has to equate to true or false as you can see it equals equals zero or not so let's try another one uh users let's say if users is greater than 5 000 and instead of free apps we'll call this High users right I don't want to filter all my apps by which ones have high users so now when I run it
you should see the array here buckets has 7598 users Connect Four has 34 000 users so again it filtered out all the apps with high users based on this conditional that I passed into the filter and as I said in the intro these are basically shorthand Syntax for for Loops you could do the same thing by doing this very basic for Loop here right you have an array called high users you go for app in-app portfolio so it's going to iterate over all these apps it's gonna say if app.user is greater than 5000 go ahead
and append that app to the high users array up here and then we'll print out High users if I print this again we should see the same thing buckets and Connect Four same thing we just got so essentially what filter is is a way to take these you know whatever five lines of code we'll delete that and to put it into a nice one-liner all right now let's talk about map so a very common use of map is to pull out all of a specific property so let's say I wanted to pull out just the
names of the Indie apps put them in a list and sort them alphabetically so say let app names equals app portfolio dot map and then again you pass in the closure dollar sign zero dot name and then now if I print app names I'm going to comment out the Filter print so we don't jumble up the console here and get confused here so print app names you see Creator view fit hero buckets Connect Four so again map went in just pulled out all the names I could have pulled out all the prices I could have
pulled out all the users and put that into its own array and then now that you have that into its array you can also dot sorted right and then now that will put it in alphabetical order so you can see pulled out all the names of the array and sorted them in alphabetical order let me actually run it it see buckets Connect Four Creator view all in one simple line of code so again shorthand Syntax for basic for Loops now that's the example of pulling out a specific property but let's say I wanted to add
a transform to that property let's say I wanted to do increased prices so I can do app portfolio map over that array instead of dollar sign zero dot name I'm gonna do dollars on zero monthly price but I want to multiply it by 1.5 say I want to pull out all my prices and then also multiply them by 1.5 so another aspect of map is it'll iterate over that and apply a transform or an operation to each element so now instead of Print app names I'm going to print increase prices we'll run it and you're
going to see an array of all my prices that have been multiplied by 1.5 if I were to increase them okay on to reduce and then we're going to start with a super basic example and then I'll show you a little more we can do so super basic let's say let numbers equal I don't know 3 5 9 12 18. so what reduce does it will reduce all these value values into one and the most common way that you use reduce is to you know sum up an array so say I wanted to get the
total sum of all these numbers so say let sum equal numbers dot reduce and then reduce has a very tricky autocomplete but again you can pass in simple closure here so we do a starting value so I have an INT so I want my starting value to be zero we're going to come back to this in a second and an operator so I'll do plus so the plus means I want to sum them all up so now if I print sum and then let's comment out increase prices so we don't clutter up the console now
when I run that you will see the sum of numbers is 47 1812 395 is 47. now again remember the initial value was Zero let's say I wanted the initial value to be 100 so Now it's going to add basically an add 47 to 100 so I get 147. so you can start with an initial value and then whatever you want to do now let's say I wanted to subtract the total of this array from 100. now instead of the plus I do a minus now it's going to be 100 minus 47 which as you
can see is 53 down there so the simplest version of reduce we're going to do a little more complex version in a second but the simplest version of reduce again you start with an initial value and then you add an operator in here okay now let's do a little more complex example let's say in my app portfolio I want to get just the total number of users right I want to add up all the users from each of my Indie apps so here we can do let total users equal app portfolio again that's this array
up here that we've been working with DOT reduce and again the initial value we want to start with zero and then now we want to pass in another closure to add these two together so we do dollar sign 0 plus dollar sign one I'll explain this in a second dot users and then here we will print total users so this operation we're passing in here again remember I told you dollar Sign zero is the placeholder for each iteration through the array dollar sign one is the next iteration so you're adding those two together so when
you're adding them up you're adding here in Creator view you're adding four three five six two one seven five six then you're adding that to seven five nine eight so that you're going through and adding those together that's what the dollar sign zero and dollar sign one mean so when we print total users we're gonna get that number again let me comment out some and it's forty seven thousand seven hundred ninety one that is the total users of all my app and again we went through and reduced just the user's property of the app portfolio
down to one variable called total users now let me show you how you can chain filter map and reduce together to do some complex calculations all on one line now a little caveat here this can get a little uh messy if you take this too far so always consider code readability versus trying to get everything on one line that's my caveat but I just want to show you an example of what's possible and I'll let you use your judgment on what's readable code and what's Not so let's try to figure out a recurring monthly Revenue
so each of these apps has a monthly Price Right 11.99 399 and they have a number of users so monthly recurring revenue for each app is you know monthly price times number of users but we want to get the total for a whole portfolio not just each app so we got to do some combinations here so for chaining we can say let recurring Revenue equal app portfolio dot map so the first step we're going to do is for each item in the array we're going to multiply monthly price times dollar sign zero dot users now
we have a little issue here because if you look monthly price is a double users is an INT so we're gonna have to cast our int to a double so we can multiply that once we've mapped each of our apps recurring Revenue again monthly price times users then we're going to tack on or reduce at the end of that to total up that array to get our total monthly recurring revenue for our whole portfolio that's the process that we're going to do here so what it's saying here is I need to make this a double
so we can cast the dollar sign users to a double so now if I print just to show you these steps here if I print recurring Revenue that's coming out total users so if I print recurring Revenue we're going to see is an array a of the recurring revenue for each app so this is Creator views recurring Revenue fit Hero Zero you know buckets was thirty thousand Now by tacking on our reduce I can sum up this total to get the overall portfolio recurring Revenue again you can just chain them so the map like I
said spits out its result into a variable well that variable can be held like temporarily in memory if you tack on another reduce here and then we want to start with zero and then this is just a simple version right we just add the plus we want to sum that up so what happens is we map out and get each app's recurring revenue and then we tack on or reduce at the end and then the result of that we will get spit into recurring revenue and then we're going to print out recurring Revenue so if
I run this this should spit out one number for my overall apps recurring Revenue so 150 000 for my app portfolio and if you wanted to know what it's going to be after Apple's cut you can you know multiply each one by 0.7 because that's all you're going to get or if you wanted To account for taxes all that stuff so now we're taking each app's recurring Revenue so multiplying it by 70 because that's you know the developer cut then we're reducing that run it again now we're 150 Grand a month turned into 105 000
a month so like I said you can combine Maps filters reduces but as you can also see this code gets to be uh quite unreadable especially to newer developers so like I said be careful with this power but just you know they can be combined and for certain situations it makes for a super clean one-liner but it can get out of hand now let's talk about compact map and Flat map these are relatively new additions to to Swift I shouldn't say I'm getting old it's like Swift four point something but they weren't around from the
beginning so to put these really simple what compact map does is it removes Nils from an array let me show you an example we'll say let nil numbers which is an array of int but they're optional right maybe you know in your array you have one nil 17 nil three seven nil 99 right for some reason when you get in Array you can either have new or a number but when you want to use this array you Just want to get rid of all those Nils and only deal with the numbers so to do that
let non-nil numbers equals nil numbers dot compact map and then you just pass in the closure of dollar sign zero and then now if I print non-nil numbers let me comment out recurring Revenue run that print the non-nil numbers you can see I get 11737.99 just got rid of the Nils so again the simple way to remember compact map is it filters out the Nils now for flat map again a simple way to remember this is that if you have an array of arrays it flattens them into a single array let's take a look let
array of arrays and that is going to be up type an array of int so let's say do an array of arrays equals and I'll keep these shorts keep the typing to a minimum so you see I have an array of arrays right each array is one two three four five six seven eight nine so what flatmap does is let's say let single array equals array of arrays Dot flat map and again dollar sign zero so now if I print single array let's run that and you can see it took one two three four five
six seven eight nine and put it all into one array where it had an array of arrays so you can imagine if maybe You have a bunch of different groups of numbers and you gather them all together into array and you're like I don't care about each array I just want to know the total there you go flat map is there and let's say before you flatten the array you want it to do something to the array well you can do that in the closure here so you can do a map and then pass in
another closure again we're getting into some complex examples let's say dollar sign zero times two so I'll tell you what this is so within the flat map I passed in a map to where each item in the sub arrays the one two three the four five six the seven eight nine I want to multiply those by two right I want to double those and then after I double them flatten that into a single array so now when I print single array instead of one two three four five six seven eight nine you're gonna get all
those numbers in a single array but doubled so run that should get two four six eight ten yep there you go when you need a collection of something in Swift You instinctively reach for an array don't you stop it stop and think would a set work here because if it does you get some serious benefits Like much better performance and some really powerful methods to help you compare different sets today you're going to learn the differences between sets and arrays and when you should use each which is a very common interview question by the way
as well as some superpowers of sets that you probably didn't know about let's compare sets versus arrays both are collections but here are the key differences an array can have duplicate items in it for example if you had a list of first names in a class you could have the same first name more than once an array is always in the same order that example of students in a class again this array you see here that order is not going to change unless you do something to change it of course every time you access the
students array that order is going to be the same that's why arrays are less performant than sets is because it keeps that order anytime you want to look up an item in the array or do any manipulation on the array it has to check every item in that array so the time complexity is O of n which basically means as the array goes larger and larger and larger the longer it will Take to do the these lookups or mutations the key differences for a set are that it can have no duplicates so like that student's
example where we had multiple first names well the set nope you can only have one of each item sets are also unordered so anytime I access this student set that order is not guaranteed I'm going to get a different order every time probably now you may be thinking well having duplicates and having everything always be in the same order those are really desirable attributes of an array but again remember the trade-off that makes arrays less performant whereas a set when it's unordered everything is unique and everything in a set has to conform to hashable and
this allows for constant time lookup so remember the array if you wanted to look something up or or map over the array the time that takes will be proportionate to how large the array is whereas a set whether the set has 10 items in it or 10 000 items in it that look up time will be the same will be constant time so if you're dealing with small data you know there's only 10 to 20 items in an array it's probably irrelevant but If you start dealing with really large arrays this is something you must
know these are the key differences you need to know between a set and array but sets also have some really cool methods I'm going to show you so not only do you get better performance with a set you get these really powerful methods that help you compare and pull out data from various sets let me show you some examples in code here in my playground I have four different sets as you can see I have one called Swifty wide devs Swift devs kotlin devs and experienced devs and you can see some of the names overlap
so imagine we have lists of various developers that have these qualifications and we want to compare these sets to pull out you know common items or make sure one group is not in another group now of course these examples are real simple there's only two to five names in it but as I'm doing these examples imagine you had a set with a thousand names in it first up let's see where two sets overlap for example I want to see experience devs and Swift UI devs now you can probably tell just by looking at it right
now that Sean is the only one that overlaps but let me show You the code to pull that out again imagine you had a list of a thousand names you know you wouldn't be able to just look at it so we want to say let experienced Swift UI have equal Swift UI devs that's this set here on line three we can say dot enter section of you can see you pass in another set experience devs so what this is going to do is it's going to see where the overlap is between an experienced devs and
Swift UI devs and it's going to put it out into its own set here so if I run this you can see over on the right the only one is going to be in there is Sean because that is the only one that is in Swift UI does and experience devs so like I said if you got a list of a thousand names you wanted to see which names are on both lists simple little one-liner to pull out all those names again this is the the power of sets and I have a bunch more examples
to show you of the cool stuff you can do next up is kind of the opposite of intersect is subtract so let's say I wanted a swift developer that wasn't experienced maybe I wanted a junior developer specifically so that's what I want to check for they want to be in the Swift Dev set but not in the experience Dev set so that's what we're going to check out so we can say let junior swim shift Dev equal Swift devs dot subtracting experience devs so now when I run it you'll see the only name I believe
it's just just James I believe James is my only Junior developer here yep there it is James so if you look at the experience devs you've got Sean Ava Olivia Leo Maya and you see Olivia Maya Leo they're all in there Shawn's in there the only one that's not an experienced Dev is James so you see you can subtract the differences between two very large lists and just to show you that let me take out Maya from The Experience devs real quick and run it again and then now you'll see James and Maya because Maya
is no longer in the experienced steps another cool one here is disjoint so we can check to see if there there's any overlap between two sets and this returns a Boolean so I'll say Swift UI devs.is disjoint with kotlin devs if there's not an overlap it will return true if there is an overlap it will return false you can see the Swift UI devs or Sean and James and the kotlin devs Olivia Elijah Leo Maya Dan there's no overlap so that returns true now if I change Kotlin Dev to Swift devs there is going to
be an overlap so is disjoint returns false so again if you had a huge list and you want to make sure there's no overlap between the lists there you go disjoint is for you now Union is a way to combine two sets so for example Swift UI devs and Swift devs Ah that's fairly similar let's just combine that into one list but you know in a set you can only have one name so if I were combining two arrays I would end up with two Sean's and two James in this combined array but because I
want uniqueness in this set when I do this Union it will compare these two sets and combine them but it will actually turn into the the Swift devs array because you know Sean and James already in there but that's what it will do it will do Swift UI devs.union with Swift devs and if I go down here and run it you will see over here Sean James Olivia Maya Leo and again that is the Sean James Olivia my Leo because we just combined these two we unioned them now let's say we want to compare the
two lists of names and we want to see who only belongs to one list right let's take Swift as and kotlin devs say we don't want Someone who's like cross-platform developer kind of knows a little bit of both we want Specialists we want someone who only focuses on Swift Dev or only focuses on kotlin dev so again we can see if they're exclusive only to one of them so I can say Swift devs dot it's a symmetrical difference of kotlin devs now here this will give me whoops I got to call to something let Specialists
right I gotta this will spit out another set here so run that and you'll see who are the Specialists Elijah Sean James and Dan and you can compare the Swift devs and the kotlin devs and you can see Elijah's only a kotlin Dev Sean is only a swift Dev so you can see they're the unique ones to the two lists so like I keep saying if you had two super large lists of names and you want to do all these comparisons sets are just a lifesaver these little one-liners spit out so much good stuff and
I save the simple ones for last so subset if you know what the word subset means pre-self explained story so it returns a Boolean so you can say Swift UI devs. is subset of Swift devs this is going to return true right because you can see Sean and James in Swift devs are in Swift UI Dev so Swift UI devs is a subset this is a quick again little one-liner check if you want to see if something is a subset that should return true and then let's change Swift devs to kotlin devs and then that
should return false because Swift UI devs is not a subset of that superset is basically the reverse so you see Swift devs dot is superset so that means if it's a superset of the subset of Swift UI devs this should return to True again because Swift UI devs being the superset contains Swift UI devs run it just to check true again so subset superset checks pretty simple and then insert delete and find say Swift devs dot insert new member we'll say Joe goes into Swift devs now remember the order doesn't matter on an array you
append it to the end you're just inserting it here and then the order jumbled up but there you go you can insert Joe or I can do Swift devs dot remove it's remove Sean and I can do Swift devs dot contains Maya and then here I will print Swift devs down here so now when I run this you can see I've inserted uh Joe I've removed Sean so Swift devs does contain Maya is true and now the new Swift devs set that has added Joe and Remove Sean there you go there's Joe and there's no
more Sean so again insert remove contains those are the constant times super performant things on a set again if you have a super large data set I'm teaching you about optionals I'm going to show you four different ways to unwrap them we're going to talk about optional chaining and then I'm going to show you some examples of how these are used in a real code base an optional in Swift is something that can either have a value or be nil for example our app could have a user object where the age is optional and that's
because in our app we don't require the user to enter their age but they can if they want so our code needs to be able to handle both situations hey is the age actually going to have a value or is it going to be nil and that's what this question mark denotes a good analogy is to think of this age property that has a question mark as a box that's closed you don't know if that box is going to contain a nil or you don't know if that box is going to actually contain the integer
value of 41. and the way we handle that in our code is by unwrapping the optional so here's our user object that I Mentioned before let's create a user real quick let user equal a user will initialize that with a name of Sean in the age is nil so the first way we're going to learn to unwrap is with the if let and I'll tell you about pros and cons of each of these methods as we go so for the if let we can do if let age equal user dot age and you see user.h
is the optional you see that question mark down there so what this means I'm going to run through this so when we say if let age we're creating a new property to store the value in if user.h has a value we're going to store it in this variable called age if it's nil it goes into the else block because age could be you know 41 or it could be no so if we have the value here we can say print users age is and then we'll print out the H because it has a value so
it'll go into the else block if user.age is nil so we can now print user did not enter and age so if I run this we're going to go into the else block because look Shawn's age is nil this user that we created on line nine that's the user we're using right here so if I run it you see user did not enter in age so now if I change on line 9 my age to 41 and I run it you're Going to see it's going to go into line 14. user's age is 41. so
This Is Us unwrapping the optional like I said we don't know if it has a value or not so we have to handle both situations if it has a value cool and we just did a print statement but you can imagine there being like a whole 50 lines of code doing whatever you need to do down here right we just did a simple print statement and then else if it's nil maybe you want to show an error do something here in the else block now a downside to using IF flat again I'm going to talk
about the pros and cons is you have to use age within this scope so what it means if you have some logic right like say you want to do like if age greater than 40 you know do something now you can see we're starting to get pretty nested here I'm going to delete this to clean that up uh with our code and it can be very hard to read so if let's if they get out of control can lead to this Pyramid of Doom that you see here so that is one of the downsides now
of course if you just have a simple you know one line of code in here and it's not super nested great go for it but a way to prevent that Pyramid of Doom is to use guardlet And that'll be the next example so regardless you need to use a function because one of the features of guard is an early exit from the function so let's create a function called check age and that takes in an INT and we're basically just going to do an age check like if they're over a certain age we can do
something in our app whatever that is but we don't know if age has a value so we want to unwrap that optional so we want to do guard let age equal age else return so I'll say print age is nil so guard like I said is good for the early exit from the function because let's say we're doing a bunch of code down here like again like if age is greater than 40 you know do something but because this logic relies on there actually being an age we basically say hey if age is nil just
return don't even do all this code below I like to refer to this as like the Line in the Sand the guard statement if the guard statement fails it's just going to return and none of the code below it will execute so again it provides that early exit which is nice and it avoids the Pyramid of Doom because once you have your age variable here now you can use that within the entire scope of the Function whereas if flat remember you had to use it within this scope right here just the top part of the
if statement and then that could get super nested but with the guard statement you can use it and you know in the whole scope of the function now something that's new in Swift 5.7 I believe is this boilerplate of garlic age equals age you've seen you know everywhere if you've been coding for a little bit now you can just do guard let age if the naming works out for example up here the naming doesn't work out I can't just do if let age because we're using user.age that has a little extra thing but in the
very common boilerplate example we have to do like if let age equals age or guard let age equals age you no longer have to have that same name it'll just use this variable name that you use there so let's run this function here check age and we'll pass in user dot age because that is the right now it's 41 so it does have a value let me actually add a print statement and here you are old let me comment out these print statements so we don't get confused in the console so we'll run it because
because there is an age right it should go past the Guard statement right because it's it is not nil so it should say you are old right it went in ages greater than 40. you are old now if I go up to line 9 again here make my age nil it's not going to make it past the guard statement so run it so basically if age is nil it's going to go into this ages no as you can see here and then it's going to exit from the function so this code never even runs in
that situation which of course for us is just one simple little line but I mean there could be like Network calls there could be a whole bunch of code that relies on you having a property here so you can definitely save running all that code if you don't need to okay moving on to nil coalescing so no coalescing is great to provide an easy default value so I can say let age equal user dot age double question mark or zero so what I'm saying here is hey check user.h which remember up here right now it
is no I'm going to comment out all this if let stuff to stop all the errors and stuff so right now my age is nil so if I say let age equals user.h that is nil so what it does it provides a default value it says hey if this is nil here give it this default value and put that Into age so if I were to print age down here and let me get rid of of these print statements again so we're not confused run it now age is zero gives me the default value because
it's nil now if I go up and change Sean's age to 41 and run it now age is 41 down there now I want to go back to what I said a easy default value and this is a case where it might not make sense because providing a default value of 0 for the age could mess up some calculations or things you're doing in your app so a place where it may make sense is if you say let name equal well let me actually go back up to the user Let's Pretend the user.name now is
optional so see how you can make something optional real quick just add a question mark to the end of it so now if I do user.name and you can see when I type in name it shows that it's optional right here and then if the user's name is nil then I can provide something like not given so you can see how if you're providing a list of usernames in your app showing not given when it's nil is a good default value to have versus maybe passing in 0 for a default age might not work out
so well so again no coalescing a simple default value or works best Okay now let's talk about Force unwrapping which can be a controversial topic let me show it to you and then talk about it for a second so I can say let age equal user dot age you can see that is optional and I can just say bang exclamation point what this means is let me comment that out to not be confusing here what this means is basically it's it's forcing the unwrap even if it's nil act like it has a value and this
will lead to crashes so let me do print age and let me make age nil up here so age is nil and I basically said let age equals user.h if it has a value hey smooth sale and it'll work if it is nil your app's going to crash so let's run this and you should see the crash and if you've been coding you've probably seen this a ton fatal error unexpectedly found nil while unwrapping an optional value that means you're forcing wrapping somewhere and it's biting you in the ass you don't want to do that
now many developers will say never ever ever Force unwrap and to be honest with you if you're a beginner just learning that is probably will be the safest way to go never Force unwrap however as you get more experienced it does become a little more Nuanced and I believe 95 of the time never Force unwrap but there are certain situations which I'll show you in my code base where it's fine to force and rap at least in my opinion but again there are many people that will say to never Force unwrap so you'll hear that
a lot okay let's comment this out so we can stop the crashes and let's talk about optional chaining to finish this off so this is when the entire object is optional so let's say my name in the age are not optional but the user itself is optional so let's dive into that here so we'll say VAR optional user is of type user but I put the question mark after that so the whole user is optional maybe the user of our app doesn't even have to create a profile with a name or an age so if
I want to say let name equal optionaluser dot name you see it fills in the question mark right here so that means the whole user itself is optional and not the name so what will happen is if optional use user is nil the name will be nil this automatically makes this property here on line 53 called name and optional so this is called optional chaining because you're really after the name but the whole object isn't optional and then Of course you can unwrap this in the typical ways right we can do some no coalescing you're
not given that'll work so name will be not given if optional user is nil you know or you can say if let new name equal optionaluser dot name say print new name so this just shows you what chaining is again once you understand the chain you can unwrap it however you want using no coalescing Force unwrapping guard lead all the stuff that we've just did but just so you know if the object itself is optional then to get to the properties on them you're going to see optional chaining now let me show you examples of
these in a real code base to give you a little more context so here's an example of if flat where I'm checking the cache so on this screen the Avatar the channel name and the number of subscribers up top here I am caching that information because what was happening every time I went to the screen it was fetching the data and the UI would flash like as the new data fetched so I didn't want that so I wanted to show the older cached information because the Avatar and the channel name don't really change and the
subscriber number might Change every once in a while so basically what I do is I cache the old information and then show the new one once the network call has completed to get the new channel info so that is a great thing for if let because if I look in my cache and the cache is nil then I just move on and run all the network calls and all that stuff if I have an item in the cache then I set my channel info to that cache Channel info and update the UI that you see
here and the reason this is good for if LED and I'm not using a guard is because I don't really care if it's nil or not right whether it's nil or not I still want to execute the rest of the code whereas if I used a guard I would have to have an early exit I would have to return out of the function and I don't want to return out of the function so you want to use guard when having something be new makes the rest of the function irrelevant here's an example of using guard
lit on this screen where I can drag and drop calendar items around and when I drop them I want to make sure the day has enough room for it because I limit the number of events in a day and the date on those objects is optional so you can See if the date is nil then I don't even want to do all this other code so that's a great use for the guard lead you see guardlet date equals date and again I just haven't updated my old code in Swift 5.7 I don't need this boilerplate
I can just do guardlet date but basically there is no date just return false and the function don't even run that stuff so again that's a great use of guard when you want that early exit here's an example of no coalescing again in this UI back to that channel header with the Avatar channel name and subscribers like if the channel info is no it's another example of chaining then I want to provide a default value of just n a for the channel name you can see I use it down here as well if Channel info
dot abbreviated Subs that's the subscriber count in the upper right hand corner if that is nil I'm sorry if Channel info is no right because I get channel info from a network call so it's nil until I get actual proper data then I want to show an N A if that comes back wrong for any reason and then finally an example of force unwrapping like I said 95 of the time you should not do it but here's an example of where I think it's okay and to be clear there will be developers that disagree with
me and and that is fine but here this is date math so this is all Apple system stuff right you're getting the year component for today's date and then you're calling dot start here I am Force unwrapping this data interval so this is all Apple system stuff none of this is my code none of this is anything calculation wise this is all straight up Apple's stuff I'm sure there may be some crazy crazy Edge case where you know this could be no but here's the pros and cons of force unwrapping if you do unwrap your
optionals as you saw in the previous code you add the iflet the garlic no coalescing you start to get a lot of extra code and you can see here I'm doing a ton of date math in this app which is mostly using all of Apple's built-in system stuff so I would be forcing wrapping it everywhere and make my code hard to read I'm not saying that's a reason to force unwrap what I'm saying is this to me is one of the examples of a nuanced reason when Force unwrapping is okay this video is meant to
be your very first step into unit testing so we're going to talk about What even is unit testing and why is it important I'm going to show you a real example in code and then we'll talk about should you even bother writing these unit tests a unit test is where we test a small piece of code to ensure it gives us the expected outcome think of a basic function that takes in two numbers and adds them together and in my head I like to think of functions like little factories right in this case it takes
in two inputs right two numbers and then it does something to them it's adding them together and then it spits out a result in this case it'll spit out the sum of the numbers so what a unit test does is it makes sure that that factory is working as expected and it's doing what it's supposed to be doing because let's say six months down the road a new developer comes into this code base and maybe they change the plus sign to a minus sign well when we write unit tests we're testing to make sure that
that function is adding numbers together so if a developer comes in and changes that our unit test will catch that because that test will fail and we'll dive into a more detailed example later in the video but That's an introduction to what a unit test is and what it does and I want to stress the word unit because that's the whole point ideally you want to test the smallest piece of code possible now the example I just showed you adding two numbers together you can't get much simpler than that but you can imagine if you
had a function that was 40 50 lines of code long which you shouldn't really have anyway but the idea is if you have a really long involved function that is going to be a nightmare to test so if you want to write good testable code you want to break it down into the smallest chunks possible which you should probably be doing anyway so why is unit testing important and what are the benefits well first and foremost it can prevent errors or regressions what's a regression you ask well I think we've all been there you ever
had a piece of code that was working and then later on you came in maybe you tried to add a little functionality to it or you did a little refactoring or maybe you deleted a line of code you thought wasn't doing anything and then bam everything breaks well that's called a regression because things were working now They're not working so you went backwards and a lot of times regressions are are sneaky right you can change something in one area of the code but then it breaks something in another area because everything's interconnected and that's why
having great unit tests written right when you're testing that the factory is doing what it's supposed to be doing you can catch those regressions when you run the tests and fix them right then and there so as you can see having good unit tests gives the developer a level of confidence right a level of safety that you can maneuver in the code base change things refactor things and you know your tests are going to catch any errors you may introduce so this allows a developer or developer team to work a lot faster due to that
safety and confidence and this is really really important when you're working on a large team of developers now this is a good time to point out that your tests are only as good as you make them what I mean by that is if you don't think of all the edge cases or all the ways that your code can break and write a test to cover that well then your tests aren't really going to save you and Learning how to write recognize these edge cases and write tests for them does just come with time experience and
practice right you're not going to finish watching this video and be a testing expert it's going to come with time okay let's dive into a code example here I am in xcode with a basic tip calculator app for example the user types in you know 500 they can drag the slider to see the tip and then what the bill total would be so I'm not going to go over all the Swift UI code because we're really focused on this tip calculation code because that's what we're going to test but if you do want to follow
along I'll scroll back up to the top pause the video there's the code scroll down a little bit pause the video there's the rest of the code but again we're focused on testing so down here into our calculation struct which by the way I just put in the same file just for ease of use on the video a lot of times you'll see your models or anything like this in a separate file let's walk through what's going on with this function you can see I'm calculating the tip I'm taking in the entered amount which is
a double and then the tip which is a double so where am I getting The entered amount and the tip so the entered amount here on the on the slider the on change is this text field now the entered amount here is a string because it is in a text field so I do have to convert that to a double so essentially you know that will return a nail if they entered like some emojis or maybe multiple decimal places or if they entered a string that can't be converted into a double this will return nil
and I'm just doing I'm just printing invalid entry this is where you would show them an error and then cool once I know I have a good amount it's a proper double then I am calculating the tip by calling calculation dot calculate tip of amount with tip slider and then as you can guess tip slider is coming from the slider here where I pull out you know zero to 100 you can tip zero percent or 100 and then I pass in the tip slider amount there and then I calculate the tip in the total amount
so this is the small piece of code the unit that we want to write tests for so the first thing we need to do is add a test Target to our project now if you're creating a brand new project from scratch you'll see this pop-up check that little box and you'll Get what we're about to do you know for free out of the box but if you have an existing project that you haven't written tests for we need to add a testing Target and that's what we're going to do so I'll go to file new
Target here you can type in test you can see there's UI test or unit testing bundle which is a unit testing bundle UI test is a completely separate topic now you can see you'll get tip calculator tests that's fine for now all this should be good hit finish and there you go now you have new tip calculator tests over here and this gives you basically boilerplate of how tests works or you get set up tear down Test example we're going to dive into this later but what I want to point out is if you just
kept it default tip calculator test tip calculator is the name of the app by the way that's like a test for your whole app and as you can imagine a big app that file is going to get a little unruly so what you want to probably do is and this gets into project organization which is subjective but this is just my recommendation is create new files for every section of your app now of course our app is only a tip calculator but you can imagine if you Had 10 screens and you know a bunch of
different functionality you'd want a different file for each little section of functionality just to keep things organized so I'm going to do that right click new file say unit test case class hit next we're going to call this calculation tests because my struct is called calculations I'll show you that in a second so hit next yep make sure your target is on the tip calculator test Target not just the app Target hit create cool so you see I basically got the same thing the only thing that changed was uh the name but again I wanted
to point that out because you know you're probably gonna have a lot of these files testing different areas of your code so the reason I call this calculation test is back to my content view is because I have this struct called calculation now this simple example only has one function but you can imagine if I had something called calculation maybe I have 10 functions that are calculating a bunch of different stuff so that is why I named it that now we're going to delete all this because we're going to write our own here now back
to the content view I'm actually going to pull it up side By side we're going to get rid of the preview so I can see the code here cool so I got my calculation code here and then my tests over here so the first thing I like to do is test what we call again the happy path like if this code works properly what should I expect so when you write a test you want to call it funk and then test it always needs to start with test and then whatever you're testing so I'll say
successful tip calculation the basic structure of a test is you want to basically set up your variables do something and then assert what the result should be so oftentimes you'll see given when then you'll also see this called arrange act assert I kind of like the arrange act assert better you'll see why once we do this so the first thing we need to do is arrange our data essentially so for calculate tip we want to give an entered amount and a tip amount and here's where we're setting up the scenario that we want to test
and because we're testing you know the the happy path what's supposed to happen we're not going to give it anything crazy so we'll say let entered amount equal 100.00 100 dollars and it will say let tip slider equal 25.0 and I'm Adding 0.0 so it can be a double and it doesn't assume it's an inch so like I said we're setting up our parameter setting up the scenario that we want to test so that's us arranging or those are the Givens so now we act or when you know when this happens or we act so
now we want to say let tip equal calculation okay so I don't have access to this calculation struct and this is something you're probably gonna have to do most of the time so you can do at testable and then import your app name so tip calculator what this does is this gives your testing file here access to all the objects in your app so now I will have access to this calculation struct so we're actually going to create that up here we'll say let calculation equal we'll initialize uh brand new calculation struct so let's tip
equal calculation dot calculate tip of entered amount with tip slider and I'm going to put this onto two lines so we can make that neater okay so I am calculating the tip it's basically running this function with these parameters being passed in so that is the act that is what is happening so now I want to assert I basically want to give it the answer so we Use XC assert and you can see there's a bunch of these here a certain nil true false equal not nil so whatever testing situation you're in whatever you want
to test use the proper assert most of the time you're going to be using these top ones right true false equal maybe nil you'll see us use no in a second so we're going to use equal so we want to make sure our tip which is what we calculated here on line 20 equals 25 and that is because you want to make sure a 25 tip on 100 equals 25. so you are manually giving it the answer because you want to test to make sure that this this Factory this function is doing the the proper
thing so now if I click this little Diamond I can run this test and you can see tests succeeded get the green check marks because it is working as expected now you may be thinking well if I'm giving it the parameters and giving it the answer like what's it testing because let's say on this entered amount Plus or times tip percentage uh let's say we you know just did a minus instead of a multiple sign you know another developer came in there changed it maybe by mistake or maybe thought they were doing something well now
when I run my tests Because I've set up these parameters that hey this should equal 25 well now it's going to fail because you know 99.75 is not equal to the 25 as expected so you can see how now if someone goes in and changes the code later the factory still has to do what it's supposed to do and that's what the test is checking for so let's change this back to the multiple sign right entered amount times tip percentage and then let's run our test again to make sure they're working green cool good to
go test succeeded so that is the happy path that is as expected but again your tests are only as good as you make them you want to cover the edge cases and the various ways this can fail so the next thing I want to test is if I close out my assistant editor go back to my content view to get my preview up just to show you this well we're relying on the user to enter a bill amount so sure when they enter hey my bill was 100 bucks things will work but we want to
cover you know when the user does something silly right what if the user says my bill was negative forty five hundred dollars well a bill is not going to be negative so you don't want to calculate a tip on a negative so We want to account for the case where they enter a negative and if you look at our calculation we are accounting for this Right Guard entered amount greater than zero so if I go back to my tests here so now I'm going to copy and paste this test down here and we're going to
call this instead of test successful tip calculation we're going to call this test negative entered amount tip calculation and it's fine if you're testing names are really long and descriptive so entered them out let's test negative 100. so if we look at our code what should happen when we pass in a negative well you can see guard entered amount make sure it's greater than zero if not we're returning nil and real quick the reason I'm returning nil is because that's where I'm going to show the error I'll move this over real quick so we can
see if tip comes back nil we're just printing bill amount or tip cannot be negative that's where we would maybe show like an error to the user again just a contrived example for educational purposes but that is why I'm returning nil so I also wanted to show you how to assert nil and test this so now we're testing the negative amount entered So what should happen when we calculate the tip with negative 100 again enter an amount will be less than zero so we're returning nil so down here in our assert this is the only
thing that changes really is instead of assert equal let's do XC assert nil and what is nil tip should be nil that's what this calculate tip returns so we're saying hey when we get a negative amount it should be nil so if we run our test this should pass again because our code has change we're writing the test to make sure if it does change we'll catch it so for example let's say some developer comes in here and I don't know they they decide to take out this guard statement on line 78 I'll just comment
it out well the code will still work right because if a user just only enters positive numbers we'll never even see this bug we'll only see this bug if the user enters a negative number so now when we run our test and by the way you can do command U to run all of your tests or you can just hit the little triangle there but you see this one failed because this line of code is gone someone thought it wasn't useful but now we caught it with our tests and I'm going to stop here with
The code examples but you know we could test a negative tip amount would be very similar to that and again you want to think of all the edge cases all the way this function can break and then write a test case for it that way if someone ever does come in and change the code like you just saw the test will catch it and you'll know right away okay let me put this line of code back do a command U to make sure my tests are all passing cool test or pass we're good to go
now you may be thinking like okay we did all this code all these checks for a very simple small chunk of code and I only did two examples there's more to be had here you might be thinking like man in a in a real app with tons of code I'm going to be writing tons of tests that's a lot of time effort and work like is that worth it okay there's no doubt that writing good tests takes a lot of work time and effort there's also no doubt that there's a lot of benefit from that
work and effort so the magic question to ask yourself is all that work and effort worth it and as always in programming it depends there's no concrete right answer for everyone because here's the deal like here's what I want you to think about whether you're an indie developer a small startup or a huge company one of the most if not the most valuable resources you have is your developer time and effort like where you focus your developers that is so valuable to a technology company so as you can imagine if you're a small startup and
maybe you have one developer two developers and you're still trying to figure out the product right you're still iterating it's changing a lot maybe you don't have a lot of users well it makes sense that the best use of that developer's time is to focus on the product build something users actually want to get users if that developer is spending half their time writing unit tests for features that are going to change in a month well you can imagine that startup in that product is probably not going to move fast enough to succeed now of
course that's an extreme example but let's go to The Other Extreme say your YouTube you have a billion users and you have a team of a hundred developers well now unit tests are a very important part of your workflow and absolutely critical to allowing that team to effectively work on that insanely large code base and make Sure things don't break for your billions of users so those are the two opposite ends of the spectrum on like should you write unit tests so where you fall on that Spectrum you know depends on again how many users
you have how large your team is what's the maturity of your product you know is it constantly changing still because you're still trying to figure it out so that's why the answer to should you write unit tests for your project is it depends and hopefully that example of those two extremes will help you to navigate that a little bit and it's not all or nothing either right it's not like either I write zero unit tests or I go for 100 code coverage which you probably shouldn't do anyway right even if you are that Indie Dev
or small startup if you have a critical piece of code something you know is not going to change yeah go and write unit tests just for that little bit again you can write unit tests for whatever chunk of code you want so that's why the answer of should you write tests how much should you write it's different for every app project team Etc never use a Singleton you hear that a lot but are they always bad Singletons come up a lot and iOS Developer interviews so today you'll learn what is a Singleton the pros and
cons of a Singleton and when and where to use them what is a Singleton a Singleton is an instance of a class that can only be created once and is globally accessible throughout your code base let's take a look at an example of a Singleton that Apple itself uses user defaults user defaults is how we persist data onto the device for example if I wanted to show this onboarding screen only the first time my app is ever used I would store Boolean like is first used into user defaults so that the screen only shows Once
here's the key question to ask yourself before creating a Singleton is it vital that there is only a single instance of this class if a second instance were to be created would that mess things up and user defaults is a great example of this because we want that persisted data to be consistent imagine if every time we wanted to fetch from user default or write new data to user defaults we created a new instance of it so now this example of is first use well in some user defaults it would be true sometimes it would
be false right you can see I would be Very inconsistent so you see why it's vital for there to only be one user defaults so anything we store in there is going to be the same when we go to fetch it by the way that dot standard after user defaults is the shared instance of user defaults which makes it a Singleton I'll tell you about that later in the video when I break down the anatomy of a Singleton now for the pros and cons of a Singleton the first pro is that there can only be
one it's Unique so if uniqueness is what you need like we did in that user defaults example there you go Singletons are good for that the second Pro is also a con which we'll talk about in a little bit but it's convenient remember your code base has Global access to that Singleton so in the example of user defaults no matter where I am in my app no matter what file I can call user defaults.standard in either fetch or write new data to it doesn't matter where I am but I want to be clear if the
only reason you chose a Singleton is because it's convenient you're doing it wrong that is not the way to go the main reason you choose a Singleton is because you need that uniqueness you need there to only be one instance Of this class creating a second one would mess things up the convenience is just a bonus now for the cons of a Singleton and we'll start off with that Global accessibility that convenience that I just talked about because you can imagine if you have a big code base you see all these files and all of
these files can access that shared resource you know that Singleton where you can imagine you know this file might be updating the Singleton which could cause a bug in another file so you can see how it can quickly turn into this spiderweb if you know hundreds of files can all access and make changes to this Singleton it can lead to some very tricky bugs so you got to be careful with that and because all those files are accessing the Singleton directly from their file that makes testing pretty tricky because you know the the functions in
that file may rely on data from the Singleton but it's coming from an external Source it's not all self-contained in that function so testing gets tricky along those lines the whole set operation of concerns that's good for programming that gets real muddy because again all these files down here are accessing the Same resource however a common way to fix this issue is to use dependency injection to inject your Singleton into these files rather than accessing the Singleton directly from the files dependency injection is a topic for another video that's coming soon how do you create
a Singleton how do you guarantee that only one of them can be created well here I have a simple example and I kept it simple because really there's only two steps the first step in the class of my Singleton is the static let shared equals my Singleton so here I'm creating a property called shared and I'm initializing an instance of my Singleton the class now the second line is what guarantees the uniqueness this private init so the initializer is private I can't initialize an instance of my Singleton from outside of this class so if I
can only initialize the class my Singleton from within the class that's exactly what the static let shared equals my Singleton is doing I'm initializing that instance and then now anytime I want to use my Singleton for example you see the function down there do something that's on my Singleton I call my singleton.shared do something So how you use your Singleton is that dot share and that's exactly what we were doing in user defaults when we did user defaults.standard or you may see file manager file manager.default or URL session URL session.shared to be clear that dot
shared.default dot standard that's just the name typically you see dot shared in Singletons but they're all doing the same thing they just chose to name it default and standard or shared it's the same thing so our Singleton's the worst design pattern in iOS no Singletons are a tool just like a hammer a hammer can be used wonderfully to make beautiful things a hammer can also be used to do some pretty bad things Singletons have a bad reputation because they are easily abused and a lot of developers have used them so use them sparingly don't overuse
them and you'll be all right dependency injection is when you give an object what it needs rather than that object creating or finding it itself and it can be intimidating because the name is all fancy and there's a few different variations on it right initializer injection property injection method injection Should you use protocols or even property wrappers there's a lot going on this video teaches you the core concept on how to use it and what the benefits are for our example we're going to use initializer injection which you may also hear Constructor injection because why
not right dependency injection is not intimidating enough as it is let's call the different variations multiple names too like I don't know anyway initializer injection let's use the Chipotle app to demonstrate that here's our parent view right the list of things you can get you know burritos bowls quesadillas when you tap on an item like a burrito it goes to the child view which shows a list of ingredients for that burrito so what our child view needs is access to our network manager which has our API calls because it needs to pull down that list
of ingredients and it needs access to our bag which is our order so when we're adding these ingredients we can add it to our order so with dependency injection instead of the child view which is the ingredients list creating its own network manager creating its own bag object we Have our parent view give the child view the dependencies right the network manager and the bag object and we do that through the initializer let's take a look at that in code here we have a very basic version of a network manager you can imagine this is
what holds you know all your API calls again super simple version for the example just the function that says fetch ingredients here's our bag right this has an array of items because we're building that order and then we have a function called place order again in real life these two dependencies are objects the network manager or the bag will be much more involved much more complex but again keeping it simple for the example this is what it looks like when our burrito ingredients view model here again this is the child view the list of ingredients
for the burrito it is creating its own network manager it's creating its own bag so this is without dependency injection and then you can see it uses the network manager to fetch the ingredients and then it uses the bag to place order with dependency injection we don't want to create these within the child Do we want the parent view to pass them in and like I said we're going to do that through the initializer so instead of these properties creating new objects itself we're going to make them of type network manager get rid of the
equal sign put a colon get rid of the parentheses for the initializer put a colon there so now we just have properties called network manager that are of type network manager and bag that is up type bag and now we're going to build an initializer to accept values for those objects passed in so we'll do a knit and you can see we get the autocomplete here network manager takes in a type of network manager and a bag takes in the type bag and then you see self.network manager equals the network manager in the bag that
we passed in so now anytime we create a burrito ingredients view model part of the initializer it's going to require hey give me a network manager give me a bag that is US injecting the dependencies the dependency injection and then you can see we're still using it network manager fetch ingredients and then bag place order now here's again a quick pseudo code example I'll paste it in here here's the meal Category view as you can see this would be the parent view that has the burritos the quesadillas Etc you can see the network manager and
bag get created in the parent view and then again more kind of pseudo code here because if you're using Swift UI maybe this would be a navigation link to present the child ingredients view or for your UI kit maybe you're you know a destination view controller so this is not exact code just to be clear because it's going to be different in Swifty wire UI kit they want to confuse you I just wanted to make it super simple see you understood that however you're navigating to that child view again the list of ingredients for burrito
this is where you would create the view model for it right burrito ingredients you model and then you pass in the network manager you created in the bag you were created at the parent view so again this is us injecting the dependencies into the child view rather than the child view creating them it sells now you may be noticing your potential downside of this initializer injection now whether it's property injection initializer injection method injection they all have their pros and cons and Use cases that's above the scope of this you know core concept video but
potential downside of this initializer injection you see we have two dependencies and the initializer is not that bad but imagine if you had four five six seven dependencies okay now this initializer gets a little unruly so again there's pros and cons to each way now you may be looking at this child view and say well that's a very minor difference and hey we even added more code so isn't this a little more complex why are we doing this what are the benefits of dependency injection so that's the second part of the interview question if you
get asked this right they're going to ask what is it and then why would you do it so the first reason you might do it is to simplify the flow of data so in this example where the parent view the list of meal items right the burritos of quesadilla is passing in all the information the child needs right that's one flow very easy whereas before where the child view the ingredients list it had to create its own network manager it had to create its own bag you can see the flow of data is getting a
little more messy and this is a super Simple example imagine if you had a giant app with tons of views turns into a giant spider web so to help ease the understanding of how data is Flowing you know dependency injection makes it very linear the next two benefits kind of go hand in hand so the first we'll talk about the separation of concerns with dependency injection we're removing the responsibility of the child to create its own dependency they still need to know how to work with those dependencies right they still need to know what to
do with the network manager but it's not their responsibility to create it that simplifies and caramelizes things which also makes it easier to swap out components right if you make a completely new networking layer you just inject in the new networking layer which goes hand in hand with improving tests that's a big thing for a dependency injection because when you try to test the child view instead of it having to create the network manager create the bag and all that stuff you can just inject in a mock version of the network manager and then run
your test so the ability to inject either a mock Network layer or the real Network layer and your child knows how To handle it regardless that allows you to test the child object way easier understanding the concept that dependency injection is giving the child object its dependencies or what it needs versus the child object creating it itself that is the key and then the other key to answering the interview question is to list off a few of those benefits I just told you the delegate and protocol pattern is a one-to-one communication pattern in Swift it
allows one view to communicate with another view for example The View controller in our bottom sheet is communicating with the main view controller it's communicating that when the iPhone button is tapped okay main view controller go ahead and update your UI with all the iPhone stuff again it's a one-to-one communication set up with delegates and protocols delegates and protocols can be confusing so I do have a starter project to keep the video as focused as possible on the topic I will review it here in 30 seconds it's mostly UI code you can see the screen
I have set up with an image view a UI label and a button at the bottom so you see here product image view name Label product button and then most of the code on the screen this setup UI is just all UI code right where I'm configuring the image configuring the label configuring the button and then setting up constraints you can see the image there and then the other piece of code is actually presenting the other view controller the bottom sheet right so when I tap choose product we get this bottom sheet and that's what's
happening right here in this present product selection VC you can see we're setting up the sheet with the detents medium that's how it goes halfway up we're showing the Grabber and the view controller I'm showing is the product selection VC let's go to the product selection view controller let's get the simulator back up again just three buttons iPhone button iPad button MacBook Pro button all this code here it looks like a lot of code I know it's just setting up the UI I'm configuring three buttons and then setting the constraints on those three buttons and
I do have actions for those three buttons right when the iPhone button is tapped right now we're just dismissing it tapping on the MacBook we're just dismissing it that's the Overview of the starter project as you can see I've done nothing with delegates and protocols it's just purely UI setup but let's start talking about those delegates and protocols as I mentioned in the intro we need to communicate between these two view controllers our product selection view controller and our main view controller right the product selection one is one with the buttons the main view controller
is in the back so that is a perfect scenario for a one-to-one communication which again delegates and protocols let me back up and explain the the concept of delegates because this was a light bulb moment for me to understand the concept of a delegate basically delegate is sitting back waiting to be told when and what to do you don't call delegate methods themselves they get called automatically when they're told what to do that's the big picture context to keep in mind as we build this it'll make a lot more sense once we you know code
it up okay so if the delegate is sitting around waiting to be told when and what to do something has to give it that order something has to give it those instructions and I like to use a boss in an intern Analogy so in our case the product selection VC this card right here is going to be telling the main view controller what to do the product selection view controller the half sheet has all the information it knows what was capped it knows the iPhone was tapped it knows the iPad is tapped and it has
to pass that message along to the main view controller so it will update its view here I don't have the code set up so it's not updating but this image will change to an iPhone or a Mac whatever so in our case the product selection VC is the boss the main view controller is the intern the main view controller is just sitting around hey tell me what to do and I'll do it right it's just waiting to be told so to set that up in our product selection VC which is going to be the boss
in this case we need to create a protocol so protocol and we'll call it product selection delegate and what a protocol is is essentially to keep it super simple is a list of commands think of it like the job description right if you're going to be my intern here are the tasks that you need to know how to do so for us we're going to create a function called did select product and We're going to pass in the name of the product which is a string and also the image name so we know what image
to update and by the way my image names in my assets I have these built into the project which you can download I have a link to in the description to a Dropbox file to download the project but you can see at the iPhone iMac super small but those are my assets the images are in there and you can see their names iPad iPhone Mac so I pull in my simulator so you can see here we need to pass in the name of the product so we can update the label it won't say Apple product
line it'll say iPhone or whatever and then we need to pass the image name so it knows what image to show here now in our simple example we're only having one Command right this is like the job description this is what the enter needs to know how to do you could have did action two Funk did action three and these are just kind of placeholders for other things that could potentially be done on your screen I just want to point out that a protocol can have many commands right it's a list of instructions a list
of commands our simple example is only going to have one but Again I want to make it clear you can't have more than one now that we have our our job description essentially right telling the intern what you need to know how to do we need to actually have a quote unquote intern on our product selection screen so for that we have a variable called delegate and that is of type product selection delegate that's what we just created up here and that is going to be an optional because we're gonna have to tell this view
controller what the delegate is in our case it's going to be the main view controller we'll come back to that in a second but I want to set up our product selection view controller which in this case is our boss and I know I'm repeating myself but I think repetition is the key to really learn this stuff so like I said job description in the protocol here is the actual job position if you want to use that analogy so now our boss is set up we have the job description we have the position now let's
go to our view controller and essentially apply for the job so to do that we need to conform to the product selection delegate so in order to do that you do comma product selection delegate Up here in your class definition of the view controller now xcode's going to yell at me do a command beep it says type view controller does not conform to protocol selection delegate because in order to conform a product selection delegate we have to have these functions in place this did select product the tasks of the job so back to view controller
xcode will fill these stubs in now this may look familiar if you've ever built a table View and UI kit you have to implement the table view delegate methods if you've ever done like location manager there's a location update delegate method and again those methods are just sitting back waiting to be told what to do and they fire off automatically and you'll see that you'll notice I'm not actually going to call did select product in the view controller we're going to call it from somewhere else and then that will fire off automatically so actually don't
like the position of this my variable is up top and then my functions so we'll put it down below view to load so now that I have signed up for the job I need to do something when I get told what to do this job so in our case we're going To set the product image View and pull up the simulator again right the product image view is the image of Apple products and then the product name label is where it says Apple product line so I want to do product name label dot text equals
name and you'll see we're going to pass in this information and I want to do product imageview dot image equals UI image named image name right we're passing in this information we haven't done that yet you'll see that in a second but our intern right our intern has signed up for the job I'm conforming to the delegate and I know what to do when I'm told hey do your job like I said I don't call this did select product from The View controller The View controller is a delegate it's sitting back waiting to be told
what to do once it gets that order it's going to go ahead and do this job so that's the premise of the delegate so there's two more steps we need to do if I go back to my product selection VC to continue with this analogy I have my job description I have the job opening well back in my view controller I say hey I'm applying for the job and I know how to do the job so let me get hired so to speak so here where I'm presenting present product selection VC right I'm creating it
I'm initializing a brand new one and then I'm doing all the modal presentation to make it a half sheet that's what all that code is and then I present it well now that I have this destination VC I can set the delegate here so I can say destinationvc.delegate equals self now self in this case is the view controller I am signing up for this job remember the destination VC is a product selection VC so if I VC short review controller if you haven't picked that up yet so now that's this variable right here that I
am setting when I create a brand new product selection VC I'm also initializing it with a delegate that I have set here equal to self the view controller is saying hi sign me up I want to be your delegate I want to be your intern so now that this is connected the main view controller right that has our product images is ready to do the job the final piece of the puzzle in our product selection VC or in this case our boss is to actually give the order give the command to do the job now
when do we want to do that again pulling up the simulator We want to do that when the iPhone button is tapped when the iPad button is tapped when the MacBook Pro is tapped we're going to give the order hey update your UI with the iPad update your UI with the Macbook so to give those orders we do that in our iPhone button tab now this is just my educational example with the buttons this could be anything going on in this screen maybe it's on a countdown timer maybe it's when they push a button six
times like whatever triggers this right in our case it's a button tap but this can be any trigger where you call this line of code where you say Okay delegate now you say did select product and because we tapped the iPhone right we're in the iPhone button tapped the product name I want to pass in is iPhone 14 and then the image name is just iPhone so you're telling the delegate okay do your job delegate and here's the information you need to do your job and if I go back to the view controller this did
select product is going to get fired off and whatever name and image name I pass in on my main view controller I'm going to set my product name label to that name and the product image view to the image let's run this And see it in action and then we'll set up the other two so I'm choosing product tap iPhone now my delegate the main view controller knows hey I'm going to update my label to iPhone 14 and I'm going to update my image to the iPhone so let's go back and do the other ones
so back to product selection VC I'm going to copy and paste this command here so copy that put it in the iPad button tap put it in the MacBook button tab so instead of iPhone 14 we're going to say iPad Air and then that image is just iPad and then instead of iPhone 14 for the MacBook we're gonna say mac book and then the image is Mac so now when I run it no matter what button I tap it should update accordingly so choose product hit the iPad bam there's the iPad Air choose product hit
the MacBook Pro there's the MacBook I guess I could have called that MacBook Pro on the label that's neither here nor there but now you can see there's two views communicating in a one-to-one pattern in today's video we're talking about the UI view controller life cycle methods you know viewed load view will appear view did disappear all that stuff I'm going to talk about when each one is Called you know what you should be doing in each one and I'm also going to share a common example of the difference between view to load and view
will appear because that's a very common situation new developers get themselves into they're also going to dabble into the whole view will layout sub views and view did layout sub views before we dive into the details of each one let's talk about when these methods are called because I think that's a source of confusion for people just starting out right you may see a method and then you're expecting a very explicit method call to actually call that method well these ones get called automatically by the system so you're not going to see you know view
to load get explicitly called now when they're called that's what we're going to dive into with the specifics of each one but just know they're called automatically now when you create your own view controllers you're subclassing a UI view controller and when you subclass the UI view controller you're inheriting all these view lifecycle methods so when you're using viewed load in your view controller that's why you're calling super.view to load because you Want to get all the magic that Apple built on The View controller and then the code you enter in view to load is
your own custom code for this specific subclass of view controller now I just use view to load as the example but that applies for all these lifecycle methods so if you're wondering why you're calling super in these that's why first up view did load now if you did load gets called when the view controller's content view gets created in memory or loaded from the storyboard what's the content view let's pull up a storyboard to show you this real quick so here on the left we have the view hierarchy of a view controller if you've ever
noticed when you create a view controller on storyboard you get this view right here by default this is the view controller's content view so when that view first gets created in memory view did load gets called this has nothing to do with what's displaying on the screen this is when it gets created in memory or loaded from the storyboard now because it's loaded from the storyboard if I go to a screen here that is why all your Outlets will have a guaranteed value in view did load right that's Why your Outlets can be implicitly unwrapped
out optionals you may have wondered like why am I force unwrapping these Outlets well again in view to load your Outlets are guaranteed to have a value that's why we can do this now let's move on to view will appear and then we'll do the example and the difference between view to load and view will appear now view will appear it gets called just before the content view is added to the actual app's view hierarchy so just before it actually shows up on the screen so let me talk about the word appear real quick because
being added to the app's view hierarchy means it's in the view hierarchy however it may not appear on your screen and that could be for a reason maybe your view is you know my view.hidden but it's still in the view hierarchy or maybe there's another view on top of that view so just because it's not actually showing up on the screen view will appear still happens because it's actually in the view hierarchy so I wanted to clear up that confusion you know view will appear doesn't necessarily mean it's actually showing on the screen again because
you could have Dot is hidden or if you could be on top of it but it's still there now let's get into a very common example on when to use view to load and view will appear right this happens all the time in apps so let me pull up the simulator here so here in this app here so this search VC view to load is called bam this is there now let me go to the next screen this is the GitHub followers course by the way so now uh this is the search VC this is
the follower list VC right now when I go back right view did load is not going to get called but view will appear gets called because on a navigation controller you're just putting a new view controller onto the stack but this search VC is still there so therefore view to load only gets called that first time but every time I come back to the screen view will appear gets called now here's how we're using this in this app right so here on the search VC we're using it to reset the username text field to blank
so every time we come back to the screen we want that text field to be blank if we didn't have this line of code that salen0400 would always still be there but now let's move Setting the navigation controller uh to false into view did load up here so this will prove that view to load only gets called once right because of the very first time we run it we're going to set that navigation bar hidden equal to true right okay look no navbar and then we go to the next screen hit get followers now there's
a nav bar right we're showing the nav bar on this screen but when we go back to the the search VC we don't want to show the nav bar it's just a styling choice but when we go back because viewed load only got called that first time now we have a nav bar here with this search thing right because this navigation set navigation bar hidden to True is not getting called so that's why we call this in view will appear right so remember that view did load only gets called that once however view will appear
is going to get called every time the view comes on screen so now that we have that back in view will appear every time the view comes on the screen we're making sure we hide that navigation bar so this is just one common example of using you know view will appear overview did load a lot of beginning developers get caught Up on that they're not sure why the behavior is happening and they don't understand that viewed load only gets called that first time and then if you want to change stuff every time a screen you
know shows up you got to do it and view will appear all right let's move on to view did appear so right we just did view will appear so that happens before the view appears so you can change it and then now you have view did appear so this is what gets called after the view is in the apps view hierarchy and could potentially be showing up on your screen so you want to do stuff here like maybe animations right because if you start an animation in view to load or view will appear it may
start a little bit too soon right you want a visual animation to start once the screen you know is showing up now moving on to view will disappear right so this is very similar to view will appear except instead of getting called before the view is added to the apps view hierarchy this gets called just before it's removed from the apps view hierarchy so you'd want to do stuff in here like committing save changes right uh so let's say you're you're have a form on Your app up and before you dismiss the form you want
to make sure you save everything like even if the user dismisses you know prematurely maybe you want to save it for some reason so you would do that and view will disappear because you want to make sure you do that before the view is gone and then you have view did disappear so this is something you'd want to do after the view has been removed from the views hierarchy now let's wrap this up by talking about the less common ones and that is if you will lay out sub views and view did layout sub views
now if you will layout sub-use is called when your views bounds change and it's before all the sub use have been laid out very common example of the View's balance changing is when you rotate from portrait to landscape on your phone right you can see the View's bounds changing kind of in real time in the animation so view will layout sub use gets called after the views bounds change but before it relays out all the sub views that you know are on the screen and by default like view will layout sub views and view did
layout sub views like there's no default implementation they're just there to Give you the programmer access to this point in time so you can make changes if you need to so if you will layout sub views gives you that chance you know again in the example after you rotate your device before it lays out all the sub views on the screen you have the chance to to do any customization and then view did layout so I've used again gives you that chance after the sub use have been laid out if you need to do anything
like maybe an animation or something like that now this is a huge topic that I could do hours and hours of videos on however we're going to keep this video at a high level because the entire point of this video is for you to be able to answer an interview question now during an interview they're asking you a lot of questions so they're not going to expect you to be an expert and deep dive into this topic they're just going to want to know that you have a very basic General understanding of what's actually going
on with concurrency and threading and with that being said we're going to talk about the different thread types the main thread the background thread we're going to talk about cues a little bit serial cues Concurrent cues and then we're also going to talk about how Grand Central Dispatch kind of ties it all together and you can move things around from different threads and cues all right let's dive in so let's start with the big picture and what is concurrency basically concurrency is doing multiple tasks at the same time now what allows us to do this
is Apple's multi-core processors here I have picture just an example of the latest A10 processor which is a quad core processor in the iPhone 7. so the more cores you have the more tasks you can do at the same time now all these tasks are being executed on what are called threads imagine threads is kind of like this major highway each lane in the highway is a thread in each car in that lane is a task being executed on that thread now you notice here pictured I have a lane here on the left the express
lane that's real clean and Speedy and that is called our main thread and the reason we want to keep our main thread you know speedy and clean is because that is what our UI is done on so for example if you clog up this main thread with a very you know time intensive task your UI is going to Freeze and your user is going to think your app is locked up so that's why we do all those time heavy tasks on the background threads keep the main thread clear so the UI is still responsive now
all this management of the main thread and all the background threads you can have because you can have you know a lot of background threads can get really hard and tricky however luckily Apple has built something for us called Grand Central Dispatch and NS operation cues which is basically just an API built on top of this threading to make our lives as developers easier and essentially it just handles all the heavy lifting of creating and managing threads for us as developers we just work with a QR pass give that to Grand Central Dispatch and it
just handles all the thread management stuff for us it's pretty nice so by now you're probably asking what's a cue imagine a queue like people lining up for Star Wars and I don't know what kind of crazy people do this certainly not me definitely definitely not me I lined up for Star Wars and I loved every second of it but anyway it's a line so the first person in the line is the first person to go into the movie theater It's called First in first out and that's really all a cue is you just line
up tasks and then the task that went in first is the first one to get executed the second one is the second one to get executed let's take a look so here you see all our tasks come in task one is the first one to go it gets executed first then tax two will get executed then three and so on and so on there's your basic cue now there's two types of cues we have a Serial cue and a concurrent queue we're going to talk about the differences there we kind of just saw the serial
queue so we'll run through it again real quick but the serial cue the tasks come in in order and then task two doesn't start until task one is 100 complete test three doesn't start until test two is 100 complete so everything happens one at a time in order now let's take a look at a concurrent cue so in a concurrent queue everything still starts in the same order so the tasks are going to start one two three four however task two does not have to wait for Task 1 to complete to start so therefore things
will happen quicker but as you can see it's going to be unpredictable on how things finish so you Can see things start in order one two three four however certain tasks are quicker than other tasks let's take a look at that one more time now imagine task 2 being something like downloading a high-res image whereas task 4 is you know just downloading some text so test two certainly starts first however task 4 happens much quicker so yes concurrent stuff you're doing stuff at the same time so it ends quicker however the order of completion is
very unpredictable so this leads us into the pros and cons of each when should you use a Serial cue when should you use a concurrent cue let's talk about the serial queue first so in a Serial queue it's a predictable execution order so everything happens in order one two three four two doesn't even start until one is done so this prevents race conditions which we'll talk about in a second it's very predictable let's take a look so again the tasks come in task one gets completed task two gets completed test three test four Etc everything's
in order one at a time pretty clean however as you can imagine this is slower because everything is happening one at a time task two doesn't even start until task one is Complete so concurrent cues are faster because yes they still start an order but everything is kind of happening concurrently or at the same time however this results in an unpredictable order and what I mentioned earlier in race conditions so we're going to look at our example again here in a second but I want you to imagine something first imagine task 3 and task 4
are related and your code has some conditional logic that is relying on task 3 to be complete before task four however you put it on a concurrent queue so you can't guarantee the order of completion now sometimes task 3 will be done before task four you can't really predict that it all depends on how the system is managing the threads and the resources and again that's why it's called a race condition because you can never be certain which task is going to finish before the other task and again that's why it has an unpredictable order
again remember the concurrent queue is a much faster a way to execute a group of tasks however you just have to not care about the order they get executed in so for example let's say you're saving a bunch of user preferences you don't care what order they Get saved in you just want to be saved as quick as possible so that's when you would use a concurrent cue and vice versa when the order of execution is absolutely imperative then you would want to use a Serial queue Now by default every app gets one serial cue
which is the main queue and then four concurrent cues which are your background cues of various priorities now you can create your own custom cues but for the most part this main queue that you get in the four concurrent cues in the background that's usually more than enough for what you need um if you want to create your own custom ones that's probably more a little more advanced but just know that you can do that so how do we switch back and forth between these cues now you've probably seen this little bit of code before
this dispatchq.maine.async and then you do some code in there a very common case when you would use this is what I have shown now let's say you downloaded some Json data from the internet you're populating a table view once all that stuff is done downloading you want to reload your table view to show your data well all that downloading stuff is happening on a background Thread now you want to shift to a main thread to update your UI remember the main thread is kind of like the UI thread so here what this code is doing
it is dispatching off the background thread to the main thread and then here we are reloading our table view data this is a very common little chunk of code and updating your UI on the main thread is something you'll do all the time as a developer so you'll see this a lot now you can move stuff to a background queue manually here using dispatchq.global and the qos stands for quality of service and in this case we want it to be on the background and then you just run whatever code you run run in this block
now to be honest with you I have almost never used this code to manually send something to a background queue I'm not saying you're never going to use it but the previous example of moving something to the main queue in the main thread is much more common than manually sending something to the background thread but I did just want to show you this so you know it is possible but again Far and Away the most common way you're going to use Grand Central Dispatch is moving stuff from a background queue to the main Queue using
this dispatchq.maine.async and then doing something like reloading your table View first I'm going to start off with a brief description of what automatic reference counting is and then we're going to dive into some code to go over some examples all right automatic reference counting now this is Apple's way of handling memory management of objects for you now what it's doing is for each object it's keeping account of how many strong references are pointing to that object for example let's say I have a person class Sean there's also a camera class a phone class and a
Macbook class now these classes can all have a strong reference pointing back to Sean so automatic reference counting is going to say that the count is four so if I even if I made Sean equal to nil to try to get rid of Sean from memory automatic reference counting won't allow it Sean will not be released from memory because there's three other objects pointing back to it how do we fix that we need to make those strong references a weak reference so let's dive into some code and take a look at a real life example
okay let's do this first let me Walk you through the basic setup if you remember in the introduction I talked about a person class a camera class a phone class and a Macbook class in order to simplify this coding example we're just going to deal with two of the classes the person and the MacBook but it will still illustrate the point perfectly so let me walk you through this person class let you know what's going going on here a person gets initialized with a name and a Macbook the MacBook is optional you may not have
a Macbook maybe like Windows I don't know and on lines 13 through 15 we have our dnit call now this only gets called when the object is actually released from memory so this is going to let us know when our object is clear from memory and we don't have a retain cycle or if it doesn't get called we do have a retain cycle so you'll see this in action here in a little bit and then the MacBook class is very similar uh the MacBook has a name the MacBook has an owner which is a person
object up here this class up here on 24 through 27 it gets initialized with a name and an owner which is the person object and again that's optional as Well just like the MacBook here for the person and then same thing the D init this gets called when the MacBook is released from memory okay let's dive into some code so the first thing we need to do on the left here is create our variables so let's go ahead and create Sean and Sean is of type person and it's optional and then VAR uh we're going
to call our MacBook Matilda I have no reason why just what I want to call it and that's optional as well so we have our variables created I'm just going to break this up into functions this obviously isn't a real app but I'm going to break it into functions just to separate the information and hopefully that makes it easier to learn so let's go ahead and create a function called create objects and in here we're going to go ahead and initialize Sean and Matilda so Sean equals person and see our initializer method lets this autocomplete
so the name name is going to be Sean and the MacBook right now is going to be no I haven't gotten to the store yet to go buy it so I don't have a Macbook yet let's go ahead and create Matilda she's sitting in the store waiting for me To buy her so she's up type MacBook and again the initializer method lets us go ahead and give her the name and the owner is no haven't bought her yet so there you go so here's what we've created now so just by creating these objects as you
can see in the image here we have one strong reference Sean has a reference to itself and Matilda has a reference to herself you notice MacBook and owner still nil there's no references to each other there so all good starting out let's go ahead and call this here just so when I run it uh stuff actually happens and just to prove that we only have one reference and we can dnit each other so let's go ahead and just set Sean equal to nil and Matilda equal to no go ahead and run it so as you
can see down here in the console our dnit methods got called for both the MacBook and the person so Sean is being de-initialized and Matilda is being de-initialized so everything's working fine no routine Cycles here okay let's go back up to create objects and get rid of us uh kneeling out uh Sean and Matilda let's create another function called assign properties And what this is going to do is now we're going to create the strong references that are going to cause trouble this is going to cause the retain cycle so let's go ahead and fit
Sean dot MacBook I went to the store about my MacBook and it is Matilda and then Matilda now has an owner and it's me Sean so there you go so as you can see in this image now we have strong references from Sean and Matilda pointing back and forth to each other and this is the bad thing this is the retain cycle so Sean has a strong reference to itself strong refers to Matilda but Matilda is actually pointing back to Sean now too with a strong reference so back here in assigned properties let's go ahead
and make Sean equal to nil now let's go and make sure we call assign properties here at the top now if you remember what I said in the intro because there's an outside object pointing to Sean in this case matilda.owner is pointing to Sean Sean will not be removed from memory and the reason is is you only get removed from memory when the automatic reference count equals zero so even though I got Rid of Sean's strong reference to itself there's still Matilda pointing to Sean so there's still one left so it's not going to be
de-initialized so let's go ahead and run it to prove that okay so it's running uh you're just gonna have to trust me on that my simulator's on another screen nothing got printed out so there's no way for you to know but trust me it's running in our dnit method over here in lines 13 and 14 of our person class is not getting called and again the reason is because there's still a strong reference pointing from Matilda to Sean so Sean cannot be de-initialized now as I mentioned in the intro the fix for this is to
make one of the variables weak over here in our classes now this depends on how your data is structured for this example let's say the MacBook is the Lesser important object so we're going to go ahead and make the MacBook the weak variable so as you see here on line 22 I made the owner variable which is a person weak so now if you look at this updated image you see Sean still has a strong reference to itself it still has the strong reference to Matilda but now there's no longer a strong reference pointing from
Matilda to Sean so now when I make Sean Nill he's able to be released from memory because Matilda's not holding on to him from the outside anymore so let's go ahead and test that go and run it and as you can see in the console now our dnit method for Sean is getting called and Sean is being de-initialized so now let's double check something let's test out let's go ahead and print Matilda dot owner right Sean's no longer memory Matilda should no longer have an owner let's go and run that so as you can see
in the console again Sean is being de-initialized so Sean's gone he's away from memory and now Matilda's owner is no Matilda no longer has an owner because Sean is gone so we've cleared our retain cycle and just for good measure we can go ahead and set Matilda equal to nil as well now now that the Sean strong references don't exist go ahead and run that just to double check so as you can see bolsha and Matilda can now be removed from memory whereas before when they have their strong references pointed back to each other neither
one of their strong reference counts would have ever gotten to zero so they could have never been deallocated for memory If you have a lot of these throughout your code it really affects the performance of your app