Building a NearMe App in SwiftUI Using MVVM Pattern

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
before we dive into the implementation details let's go ahead and take a look at what you will be building in these sections you can see that this is a near me app it's going to tell you where you are which is in cupertino in the simulator and i can go ahead and type anything i want if i want to search for something now if i go ahead and type in coffee it will show me all the different coffee places near my current location i can also change the view to a list view to better see what each coffee location kind of looks like and what are their names but since coffee and gas and groceries is such a common thing i've also added these categories that you can simply select and it will filter out all the different things that are available and you can see that the filter also works when you are going to a list and you are selecting these different things we will be building this using ios framework for sif ui we will be using the mvvm design pattern and the built-in controls for safe ui for map let's go ahead and get started all right everyone let's go ahead and get started so in this lecture we'll be doing a couple of different things we will be adding to the info.plist file so we can request access to the permission for the user which we will need in the future when we are asking the user for their location so for the position we will have to go to info.plist file and this is a requirement if you don't do this if you don't ask for the permission then you will never know where the user is so because we are trying to build an application where we can find out where the user actually is and then based on their location we are giving them suggestions about coffee shops burger shops or whatever they want so it is very important that we find out users location and in order to find our user's location we need to ask them that hey is it okay that if we use your location because our app kind of depends on it so let's go ahead and add a key and this key as you can see it's called a privacy location when in usage description there are some other keys also if you can add right now i'm just going to add this key and this will be the message near me requires your location in order to provide best recommendations okay you can write anything you want over there that's perfectly fine now let's go to the content view you can see on the content view we display kind of like the hello world if i want to display a map the first thing i'm going to do is import mapkit mapkit contains the views that i need in civ ui that will enable me to display a map and in ios 14 and sift ui they have introduced a map view which you can use there are several different overloads of the map view you can see you can pass in the coordinate region coordinate region with annotation annotation content and a lot of different stuff but right now what we want to do is to just display kind of like a default marker just some latitude and some longitude and that's it in order to do that what i'm going to do is i'm going to create a new group for extensions and we will go ahead and add a new extension i mean this is not you don't really need this but we will need this in the future so why not just implement it right now and i'm going to go ahead and extend mk coordinate region so i'm going to extend that i'm just going to also provide extensions over here just for the name of the file so that we know that this is an extension and in this i'm going to simply create like a default region so i'm going to go ahead and say extension mk coordinate region you can see it's not really coming up because we still need to import a couple of different things which is map kit and now it should be okay i'm going to go ahead and create a static function which will be called default region so i'm just going to say default region and it is mk coordinate region that's what it's going to return from this particular property and now i can simply copy paste something some sort of a region it can be any region that you want so there we go all right so this default region is going to point to our apple campus so you can use anything you want and let me see what's going on over here not function sorry it's a var there we go now we can go back to our content view and we can try to use our map so map and we can pass in the coordinate region now pay close attention to what you can actually pass in because the type that you need to pass in to the map function for coordinate region is not mk coordinate region it's basically binding mk coordinate region so if i try to pass in something like this coordinate region and simply saying mk coordinate region dot default region the one that we just implemented it's not really going to work it's going to complain because the default region is of type nk coordinate region but it actually wants the binding mk coordinate region all right so there are many ways to fix this what i'm going to do is i'm going to go ahead and simply create a small function and i'm doing the all of these different things because we will eventually need these things in the future so that's why i'm kind of like laying the groundwork for all of these things so i'm creating a function called binding and it's going to get region and it's going to return me the binding mk coordinate region and from here i can simply go ahead and return dot constant mk coordinate region dot default region so basically now we have wrapped around this default region which is mk coordinate region with binding and now i can simply go ahead and call get region let's go ahead and build it and now it's successful let's go ahead and try to refresh our screen and let's try to run it also okay so we can see over here that we have added the region let's go ahead and try to run it on an actual simulator although this is an actual simulator but sometimes you will see that the explore xcode previews doesn't really work as expected when you are working with uh you know when you're working with some other place and there we go so at least we get our map to to get displayed so that's perhaps pretty good now i can go ahead and zoom in and zoom out of the map and everything so that should be okay right the other thing that we want to do is now we want to find the user's location and that is what we're going to do in the next lecture so let's go ahead and do that in the next lecture all right so before we go to the next lecture sorry i do need to tell you that the mk coordinate region these latitude and longitude coordinates are not for apple campus this is for somewhere in houston near the museum of fine arts and you can always change this latitude delta and longitude delta if you want to kind of zoom in so if i go ahead and say 0.05 and 0.05 and run it then you'll be able to see that it's kind of like zooming into that museum district area uh houston museum of national science harmon park so that is the latitude and longitude for that particular area all right so that's why it is zooming over here and not apple campus because these latitude and longitude belong to houston and not of the apple campus all right so now let's go ahead to the next lecture and we'll be talking about how to find the user's current location all right so our next task is to display the user's location on the map for this i'm going to go ahead and add a new folder and i will call it managers and the reason that we're doing that is that i'm going to create something called a location manager and the location manager will be responsible for giving us the updated location of the user so let's go ahead and add that i will add a file called location manager and now let's go ahead and implement it import mapkit class location manager it is going to be conforming to ns object inheriting from an object and we will also go ahead and make it conform to the observable object and you'll see that why we do that and inside over here we will create a private instance of location manager which is of type cl location manager so clocation manager is actually already built in to the ios framework it's part of the map kit what is it part of the foundation actually let's go ahead and remove that it's going to build it there we go so it's part of the map kit all right and this is going to give us a location once the location is available we are going to go ahead and say cl location and we will initialize it to nil and we will assign it over there and since this is marked with published whenever we assign this it is going to throw an event which our ui can handle or our view model can handle okay let's go ahead and override the init which is the constructor we will call the super if there is any super for ns object we should call that and then we are going to go ahead and set for the location manager which is of type clocation manager we are going to set the delegate to self it is going to complain right now because we are not conforming to the delegate don't worry about it we will fix that issue next up we are going to talk about the accuracy of location manager i'm going to set the accuracy to be the best accuracy which basically means that it is going to take a bit of time not that much time but a little bit of time to find your location but for our case it should be okay next we're going to set the distance filter and i'm just going to set it to none which basically means that we are not filtering on any distance so if it's 5 minus 10 miles 50 miles it doesn't really matter next up we will request for the permission and this is the most important step because remember that in info.plist file we added this particular key when you request for the permission it is going to ask you that hey do you accept do you give your permission so that we can track you we can get your location and finally we will call location manager dot start updating location this means that whenever the person moves whenever the user is going to move from one place to the other place the start updating location is going to give us the updated location next i'm going to go ahead and create an extension for the location manager and i'm going to make sure that i am using or conforming to the cl location manager delegate now some of you might be asking that why did i created an extension why can't i just do it over here you can definitely do it inside this class it's always a good idea to separate out your code a bit so i know that this particular extension i will write all the code that will be related to the delegate functions of cl location manager delegate so it's basically just for the organizational purposes one of the functions and the only function i will be interested in is called date update locations and did update location is part of the cl location manager delegate it will be called whenever the user's location is updated we will get the location equals to locations dot last so we'll get the last location from an array and if we were not able to get anything we will simply return and finally we will go ahead and put it location equals to location all right we can also wrap this around in dispatch so dispatch queue dot main dot async just so that we know that this particular location is actually being set inside the dispatch because it is marked with published and there you have it this is how you will find the user's location now we are finding the user's location which is right here and we assign it to our location property which is right there which is great but we still have to display the location or display the user on the screen and for that we can use the content view and the map itself does have something called a show you the location that's fine but we still have to call the location manager inside the content view somehow so instead of calling it right inside the content view we will create a view model and the view model will use the location manager to find the location so in the next lecture we'll be working on creating our place list view model which will keep track of everything that is happening on our content view screen so let's go ahead and implement our view models all right so now let's go ahead and start implementing the place list view model which will be responsible for the entire screen which displays the map and anything that goes on to that screen i'm going to go ahead and add a brand new group and i will call this view models next i'm going to go ahead and add a new file swift file is perfectly fine and we can call this place list view model there we go let's go ahead and import combined because i might be using combine actually all right here we go place list viewmodel which is an observable object that's going to conform to that and that can only be applied the observable object interface can only be applied to the classes that's why the place list view model is a class next up i'm going to go ahead and create a private property which is my location manager i don't really want this to be exposed to the view we will create it as a location manager inside the init initialization function of the place list view model we will go ahead and initialize our location manager and this by doing this the location manager is going to invoke everything inside the init which is also going to start updating the user's location now what we want to do is when the user location is updating or constantly updating when the user is moving we want to get the updated location so i'm going to go ahead and say locationmanager.location which you can see that this is a bindable property that we created a publish property dot sync so now i'm going to subscribe to it i will get the location and now i can do something with the location now whenever we are doing this kind of a subscription the sync is going to return a cancelable event basically a reference to the publisher so we need to make sure that we are keeping a hold of it or else we will lose that meaning the memory will consume it or the memory will not refer to it so that's why we're creating cancelable and that is part of the combine so that's why we imported combine let's go ahead and assign cancelable over here there we go so we are holding up that reference so making it alive we will get the location so go ahead and first of all we will make sure that the location is unwrapped after the location is unwrapped we can put it into our own property which is inside place list view model which will show the current location so i am going to go ahead and add a new property over here which will be current location and you can see that the current location is not of type cl location is cl location coordinate 2d so for that i will go ahead and import map kit so the whole purpose is that from the view model if we want to provide anything to the view i want it to be in a very raw format like location 2d which is a structure which contains the latitude and longitude now i can go ahead and perform a dispatch queue dot main dot async and i can perform the or set the current location equals to location dot coordinate now since the current location which we declared right over here is marked with published every time i'm going to assign a new location or new value to it it's going to notify whoever is listening so now our ui can actually listen to it all right so let's go back to our user interface which is our content view right there and you can see that in the content view we're not even using the protocol or for the place view model so i'm going to first of all going to create an instance of place list view model there we go all right so we have created the instance of place list view model now we want to return the location that we are actually getting so how do we do that how do we return the location right now you can see that we created a function called get region which is kind of like displaying or returning hard coded location but we don't really want to do that we want to get the actual location so let's see how we can do this i'm going to go inside the get region function and inside the get region i can go ahead and possibly i can say let coordinate equals to place list viewmodel dot current location which is actually coordinate if this is not working if there's a problem then go ahead and return a constant value and in this case i can return the default region because something bad happened and we are not able to get the actual location if however we were able to get the location then i can say constant value again mk coordinate region and we can pass in the center which will be coordinate and the mk coordinate span which will be you can pass in anything you want over here i want to zoom it a little bit so i'm going to patch in 0.05 which means that it is going to return a little bit like zoomed in into the map all right there we go the map currently that we are using is kind of like a very plain kind of a map which simply says coordinate region it has nothing to do with show user location or anything but as we explained earlier on you have many different ways of showing the map this is a coordinate region this is annotation and all that stuff interaction mode show user tracking or show you the location with user tracking we can use this one at this point so in this case we are again going to call get region interaction mode now what exactly is interaction mode interaction mode simply means that how you are going to be interacting with the map all right so what kind of interaction mode should we provide over here well this is completely up to you what kind of interaction mode you you want do you want the user to pan and then you know pinch zoom and all those things i'm just going to pan in or pass them all which means that they can do whatever they want show user location yes please true and user tracking mode meaning if the user is moving what should the map do so we want the map to start tracking the user so let's go on the top and we are going to declare a user tracking mode which i have declared right here and i'm saying follow so kind of like follow the user if the user is you know walking around try to follow the user and now i can pass in the user tracking mode over here user tracking mode all right and it might be the binding property so we're going to have to pass it like this all right so there you have it let's go ahead and try to run it and see what happens and there we go and you can see that now our user is actually displayed right there which is great now i'm obviously not in cupertino but you can change these location by going to your features in a simulator location and you can see that right now it is selected as apple you can do freeway drive or city bicycle ride or city run or even a custom location so if i'm going to go to freeway drive sometime it starts on its own but let's see okay we might have to zoom in a little bit you can see that if i zoom in you can see a little bit that it is actually doing that but when i zoom in what's going to happen what's happening is that it keeps on resetting because the user is actually moving so it gives me a different point of view of zooming in but you can definitely see the user is going along or it's in a car uh i don't want the user to be in a car right now i just want the user to be in apple campus we're just going to use that all right but you can change these things any way you like so this is great because we are able to display the user's location now now the next step for us would be to display the landmarks well first we need to find out the closest landmarks like closest burger store closes you know coffee shops and right now if you noticed if i launched the app we don't even have a text box to write something to say something that hey i want a burger or i'm looking for you know some other things so we don't even have a text box to search for those place marks so we definitely need to add a text box and then we will be able to search all the landmarks and then eventually we'll be able to display the landmarks so let's go ahead and work on the text box and also look at that how we can perform a request and get all the landmarks closest to the user's location all right so now it is time for us to find the landmarks but before we do that we need to go ahead and update our code to accommodate the text box right now you can see that in our content view we are simply displaying the map well the question still is that if you're only displaying the map then how is the user going to say that well i want coffee i want burger i'm looking for a restaurant i'm looking for a gas station so let's go ahead and fix that the first thing i'm going to do is i'm going to go ahead and embed the map into a v-stack there we go so nothing really different i mean it looks exactly the same after this what i want to do is i want to create a text field so let's go ahead and do the text field and text field is actually pretty simple to create i'm just going to say text field and we can use some sort of a text over here i'm just gonna say search and the bindable string now the good thing about this bindable string is that you can either have a string right over here somewhere in the state or you can create it in the view model and for now i'm going to just go ahead and create it over here and i will tell you the reason why we are doing that later on so search term string there we go and now i can go ahead and simply say search term this means that anytime i'm going to pass anything or write anything into the text box it is going to go into a variable a state variable called search term okay so there's our text box a little bit of text box you can see we can also go ahead and save text field style and the text field style we want is the rounded border text field style and since we're putting it in the v-stack it might be a good idea to go ahead and add a bit of padding to the v-stack there we go and now it looks much better okay so now what we want to do is when the person types in the text box and presses the return button in the keyboard we want something to happen we want to submit it and we want to perform the search so if you look at the text box it does have a little bit of different overloads so if i type in text box over here or text field you will see the one this one it actually says on editing changed and this one also says on editing change as well as a comment so the remaining part or most of the part is the same we're going to bind it to search term editing change basically means that whenever we are typing in the text box do we want to do something for now i'm just going to leave it blank not really going to do anything over there and this is the one that we're interested in which is on commit which is going to get fired when we actually write in the text box and press the return button in the keyboard and this is where i want to go ahead and call or get all landmarks based on what we have typed in the text box but how do we get the landmarks we can go ahead and add the code into location manager or we can create a different service to get all the landmarks or for now i can simply go ahead and add it right there in the view model but you can create a separate service for getting the close by landmarks if you think that this is going to get bigger then perhaps it's a good idea to move all the code that i'm about to write into a separate service function search landmarks you're going to pass in something search term which will be a string and based on the search term we are going to go ahead and search for landmarks near the user's location for this i'm going to first of all going to go ahead and create a request which is mk local search request so let's go ahead and create that and i'm going to go ahead and set the property which is called the natural language query to the search term which means this is basically what we're searching for next i'm going to create an instance of mk local search and pass in the request which is request and we're simply going to pass the request let's go ahead and add the equal to sign and now we can perform our search by calling search or start it's going to give us a completion handler the completion adder is going to be consisting of the response and the error or hopefully there is no error if there is an error we're going to go ahead and unwrap the error and we can go ahead and print it out else if there is no error then still we are going to go ahead and unwrap the response that we are getting from the search.start function and then eventually hopefully it's going to give us the map items so we're going to go ahead and simply get all the map items let's go ahead and also display the map items so that we know that we have gotten something so this is our function it's called search landmarks now we can go back to our content view and right over here we can say place list view model dot search landmarks and then we can simply pass in the search term awesome let's go ahead and run this we're not really displaying the landmarks anywhere but if we are able to get the landmarks we should be able to display it on the console so i'm gonna simply search for coffee and you can already see that as soon as i press the enter key or return key it prints out all of this different information these are each one of them is an object of type map item or a place bar and you can see that it contains the name of the coffee or name of the coffee shop there's starbucks you can see starbucks pete's coffee and many other coffee locations maybe another coffee shop called bittersweet so at least we are able to get all the different coffees or whatever the user is searching for and we can display it on the console let's go ahead and run it again instead of coffee now let's search for burger press enter okay there we go so now we got some burgers you can see over here mr beast burger burger king so everything is related to burger five guys the habit burger grill wendy's again another burger king and so on so it really depends what kind of positions or what kind of locations or landmarks are available near my current locations and is trying to find out all of those different landmarks now this is great we can find landmarks and we can print it on the console but the real question is well user will not be looking at the console user will be looking at the screen where the map is so how can we get those map items and somehow put it on the screen so let's go ahead and do that in the next lecture now let's go ahead and talk about that how we can finally display our map items our search landmarks on the screen now in order to put something on the screen it is always a good idea to create some sort of a view model that is containing that is having all the data that the view requires we have already created one view model and you can see it's called the place list view model i think we should create one other view model which will resemble a landmark so i'm going to go into a view model and add a new file now once again you can call this place viewmodel or landmark viewmodel you can call it anything you want i'm just going to call it landmark view model landmark representing each landmark like each coffee shop you can call it place view model also there we go all right so in this one i'm just going to go ahead and import mapkit and you will see that why we are importing map kit because we need to refer to the cl location coordinate 2d that's why struct landmark view model this will be an identifiable and we will see why we're doing that also because it needs to be identifiable for annotations for the map view to work this landmark view model will take in amk placemark mk playsmart basically simply represents each placemark which means a coffee shop like vent kept coffee shop like starbucks a burger join like wendy's or five guys or smash burger so these are all place marks we will go ahead and conform to the identifiable protocol by creating an id property and now we can go ahead and create some properties that we can return so over here we can have placemark.name or it's going to return an empty we can also have the title of the placemark which can be placemark.title or we can unwrap it and it can return empty if it's failing to unwrap and finally the more important one is the coordinate which is going to return to you cl location coordinate 2d and we're going to return placemark.coordinate so this is our landmark viewmodel which represents every single landmark let's go back to our place list view model and what we will do is we will create an array of landmarks so i'm going to go over here and create an array of landmarks perfect now when we're fetching the stuff which means when we are inside these search landmarks we got the map items we can go through those map items by running a map items.map and we will go ahead and return a new landmark view model which relies on the placemark which we can get from that particular map item so we can say dollar sign 0 which is a map item dot place mark perfect and this is going to return us something and that's something we can go ahead and assign to landmarks there we go so this is great we were able to assign the landmarks now we need to feed these landmark view model array to our map so let's go to the content view right now you can see the map is pretty basic it doesn't even allow anyone to enter the annotations or the landmarks itself so we need to use some other kind of a overload for our map for this to work right now we're using the region interaction modes show you the location user tracking and we can go ahead and add annotation items this is the annotation items that we are talking about which is going to be the landmark and we can go ahead and say place mark place list view model dot landmark so this means that we are assigning it the array of landmark view model now what i'm going to do is i'm going to go ahead and get the landmark for each landmark we are going to go ahead and return something called a map marker and we can simply go ahead and pass in the coordinate of that landmark so core donate i may have to retype this whole thing again if it's not working but looks like it should be okay all right let's go ahead and build our app now perfect the map marker is basically a map marker annotation which is already provided in the map kit if you don't like the map marker you can use a map pin but map marker is actually pretty good it's a nice flat design and it looks really nice okay so now let's go ahead and search for coffee shops and there we go so these are all the coffee shops near our area one thing you will realize is that as soon as i try to move you can see that it kind of snaps it in like if i try to move it kind of snaps it in back to the center and the reason for this is that our location is being set again and again because when we use when we created the place list view model inside this we were calling the location manager and we are getting the new location every single time and it gets assigned and then our map gets updated anyway we can solve the problem later on right now you should be happy to see that all the different coffee shops are actually being displayed now if i go ahead and search for burger you can see it changes because there are different burger joints near our area unfortunately i cannot really interact with any of these landmarks for now uh maybe that will be fixed in the future uh in ios 14 it is still not working so in this section we have seen that we can search for different place marks and it will tell you all the different place marks on the map that is great but there are a lot of improvements that we can do like we should be able to a little bit pan and view different landmarks we should be able to see these landmarks and places in a list instead of a map and maybe it's also a good idea to put some sort of a category bar right here where people can just select coffee gas restaurant hotels just by clicking on it instead of typing it so we will do all of those things in the next section let's go ahead and get started some people like to display maps and annotations and landmarks on a map but other people like to display it in a form of a list or even view it in the form of a list so how can we add a list view also along with our map view the first thing we need is a way to switch between a list and a map and what we can do is right over here we can add some sort of a segmented control where the left side will be the map and the right side will be the list so let's go ahead and first add our segmented control a segmented control in city y is created using picker so i'm just going to go ahead and add a picker and a picture you can see it has many different arguments it takes so we're going to go ahead and say select selection where is the selection going to go so the selection is going to go into a state variable so we have to go ahead and define a state variable so state private var and i will simply say display type but should we put it as a string or do we even know the display types well we actually know the display types i mean there are only two display times either it's going to be a map or it's going to be a list so probably a good idea to go ahead and create an enum which can represent a display type one of the case will be the map and the other case can be a list this means that we can change this display type into a display type enum and by default we can set it to map because it is a map now going down to our code over here for the picker we can go ahead and pass in a bindable display type which means that anytime a person is going to select a button of a segmented control this display type will be populated with the correct value finally for the content is what we want to be displayed in our segmented control now you can do all the fancy stuff over here i'm just going to go ahead and say map and the tag part is very important because the tag is the actual one the actual value that gets transferred to the selection so the first tag is map and the second tag will be list you can go ahead and use images if you want to but i'm just going to go with the basic text and that's perfectly fine so display type over here now the final thing is that we need to set the picker style and this is where it becomes a segmented picker style let's go ahead and see how it actually looks like in our preview so let's load the preview on the right hand side we may have to load it again sometime it doesn't work but there you go you can see that the segmented control is displayed with map and list and the map is actually selected because of the selection display type and because we have initially selected the map so this is great now based on the display type based on my selection i want to either display the map or i want to display the list so how do we do that well first of all we will check over here if the display type is equals to map then we will display the map so we will move all this code and there we go else if the display type is list then we will do something else all right so how do we display a list well we can go ahead and display the list right over here but probably it would be a good idea to create a separate view which can display just the list and what i'm going to do is i'm going to go to my near me app and going to add a new folder new group and i will call it views inside the views i'm going to go ahead and add a new surf ui view and i would call it landmark list view landmark list view and the landmark list view is only interested in displaying the landmarks and that's it that's its job just to display the landmarks and it's going to display or it's going to have a very simple structure so instead of the text we will have a list now the list needs some sort of an array to work on so the first thing probably we should do is we should go ahead and say that the landmark list view depends on the landmarks which are of type landmark view model so in order to create a landmark list view you should pass in an array of landmark view model we're going to create a list and we're going to pass in the landmarks and for the id we're just going to use the id which is already a property on and landmark view model we're going to get each landmark and for each landmark we can display a couple of different things we can first of all put a v-stack with some sort of an alignment also so let me go ahead and put an alignment and we can say leading is fine and for spacing 10 is fine i'm going to also go ahead and delete the landmark list view preview because i don't really need it right now but eventually if you need it you can add it and for text we're going to say landmark dot name and maybe even i can go ahead and say that the text is a headline a little bit more bold and finally we will have landmark dot title perfect now going back to our content view we can go ahead and simply display the landmark list view over here if the display type is list this mean i can say landmark list view and now i need to pass in the landmarks which i already have in the place list view model i can go ahead and pass it let's go ahead and build it perfect and i'm going to go ahead and run it in a simulator ok now let me go ahead and search for coffee great so on the map it displays and the map is selected let's go ahead and select the list view oh great now i can actually see all the different coffee shops but in a list isn't that cool and pretty simple well let's search for something else let's search for burgers okay so this these are the all the burgers that are closest to my location and if i go and select the list you can see in an out burger super duper burger the counter so all of these burgers are available in a list format also so this is actually really really good that we are able to do that at this point i realized that you know i order coffee too much and burgers too much and gas station also i mean these are just common requirements right i mean why do i have to type these common things would it be a good idea if these common things like gas stations and restaurants and burger and coffees and all of those things are just somewhere on the top over here like already selections already available selections and i can simply click on them and it will just work this is called a landmark categories so in the next lecture let's go ahead and see that how we can add these categories so that we don't have to type for these common things like gas stations and coffee and restaurant and burgers we don't have to type anymore we can just tap on it and it will just work so let's go ahead and see how we can do that in the next lecture now let's go ahead and implement our common landmark category view this means that instead of writing gas or instead of writing coffee and burgers we can just tap on some icons which will automatically search for common landmarks in order to do that i'm going to go ahead and add a new view of ui view and i would go ahead and call this landmark category view perfect now inside the landmark category view first of all i need categories that's the first thing right so you can go ahead and save your categories in the database you can save it in a xml file or a plist file or a json file whatever but since our categories are constants i'm just gonna hard code it there we go next i'm going to go to the body and write some implementation we do want it to be scrolling so i'm going to start with a scroll view and this scroll view you can scroll in a horizontal direction so i'm just going to say horizontal let's go ahead and check out our view over here okay nothing there yet now i can go ahead and put an etch stack horizontal stack and i can go through each of these views this will be categories id will be self because it is already string and we will get each category after getting each category i can display the category but it depends how you want to display the categories i can use a button with an action and a label for the button i'm just going to go ahead and display the text for the category you can already see it's displaying button but what i'm going to do is replace it with the category so it's going to say the name of the categories there we go perfect after that we can go ahead and add some padding some foreground color some background color and we can even clip shapes so i'm just going to copy that stuff because we have written those things a lot of different times before so for button i'm just going to add a couple of different things now one of the things that you can see over here is a selected category thing selected category property the selected category is going to keep track of which category you have selected and based on their selection the category can highlight between different colors between white or a gray color so let's go ahead and refresh our preview and we will see that how the categories are being displayed and hopefully we'll be able to select the categories also so there we go you can see the categories being displayed perfect now if i run the app right now and i select a category the first thing you'll note is that well they're not really highlighted and the reason that they're not highlighting is that we didn't really do anything in the action you can see action or a button click is completely empty so let's go ahead and implement that so what should happen when you click on a particular action well the first thing is that we will go ahead and provide or set selected category as a category great now when we select ooh great looks pretty good and we can actually scroll so this looks really really good but we still have a problem currently we have selected the category and we are inside a control call landmark category view if we want to give the selected category to some other view how do we do it well one way of doing this is by creating a closure on selected category and this will be a closure with a string argument it's not really going to return you anything this means that you can go ahead and call on selected category and pass in the selected category so i can simply say on selected category and i can pass in the category this means that anyone on a different control who is using the landmark category view can go ahead and use on selected category event or closure to get the selected category now let's go back to the content view and we will try to use our control which is a landmark category view first i'm going to go ahead and resume the preview and where do we want to add this category so i'm just going to add it a little bit above the picker so i'm just going to say landmark category view and the only thing you need to pass in over here is on selected category that's a closure we will get the selected category and using the selected category we can use place list view model dot search landmarks and pass in the category remember i said that we are using search landmarks and we're going to pass in a search term and why didn't we automatically bind it to a property in the view model well that's a reason we can simply go ahead and pass a particular category like burgers and coffees and restaurant to the search landmark function which will perform the search for us now let's go ahead and see what is going on over here this is saying on selected category is missing okay that's not a big deal because this is more of a xcode preview thing we can go ahead and make it right let's go ahead and implement that on selected category and in this case i'm just going to go ahead and make it work by simply saying we're ignoring the actual category and we're not really doing anything so this is in the landmark category view okay let's go back to our content view and let's go ahead and run this oh it looks really nice now because you can see the category is being displayed on the top and if i select on a category you can see that it is updating and it is telling me of all the different pharmacies all the different hotels and everything and i can even go to the list view and guess what all the different hotels are already populated there if i go ahead and click on gas if i go ahead and click on groceries coffee you can see it is refreshing as well as the map is also refreshing this is super awesome one of the last things that we need to do is sometime on the map i want to just you know pan the map but it doesn't really allow me to pan as soon as i'm panning you can see that it kind of just sticks to the current user in the center and the reason is that we are updating the location all the time so if you look at our manager over here we're calling start updating location it means that it is always updating the location so even if i am really not moving that much it's always giving me the updated location and centering on that location now we don't we do want it to center that's fine but we don't really want it to center all the time if i am swiping or if i am panning using my finger then i don't really want to center on myself i just want to check out the map so let's go ahead and check out that how we can create a recenter button that can also allow us to pan and then get to the center but also allow us to perform a panning gesture on the map all right so now let's go ahead and look at our final issue that we are facing it that we need to fix if i go ahead and run the application right now and we have seen this issue numerous number of times everything works correctly i can check out the groceries i can check out the hotels i can check out the coffee shops and so on but if i try to like pan a little bit if i try to move the map it just centers me again and again it kind of forces me to see the center or it's focused on my location i don't really want that when i'm panning like this i just want to be freely panning meaning just looking at different portions of the map so how can i do that well there are a couple of different things that we need to do the first thing we need to do is we need to add a gesture on our map so let's go ahead and find our map right here it's going to get a little bit complicated over here or crowded not complicated i'm going to go ahead and say gesture so we are trying to perform a gesture on the map and i can perform a drag gesture there we go drag gesture and on the drag gesture i can say on changed so on change expired whenever the you're dragging you're panning on something now when the on change is fired we need to set some sort of a flag which is indicating that hey we are dragging right now so what i'm going to do is going on the top of this screen and going to declare a brand new property called is dragged and we will initialize it to be false down over here in the on change we can now set this property to be is dragged to be true this means that we are currently dragging because it is changing we are dragging when we are dragging what we want to do is we want to make sure that we show some sort of a button overlay button on top of the map now currently we don't really have any kind of a button so what i'm going to do is i'm going to add a brand new view and you can create the button over there also but i'm just trying to be a little bit more creating all of these different components and i will call this recenter button it doesn't really have to do anything with re-centering it's basically simply a button with a particular display now in this button i'm going to go ahead and create a very simple button with an action and a label and if we look at this button you will see that it's nothing more than a very simple button okay great but in the label we can actually create a different display for the button by using a label and passing in kind of like a system image so i'm going to go over here and say re-center that's the label that's actual text and the image can be anything i'm just going to say triangle okay it looks kind of like that that's perfectly fine i can add a bit of padding to it let's say 10. i can add a foreground color as well as a background color and all of those things we have done previously so i'm just going to copy paste it over here you will see that we have a foreground color we have a background color and it looks pretty nice when you tap a button we need to tell the parent view that you have tabbed the button we're going to use the same approach as creating a on tabbed closure which is an empty closure because we're not really passing anything to the parent we're just simply saying that the button has been tapped over here in the recenter preview i'm going to make sure that i pass something so i'm going to just pass an empty closure and in the action of the button which is actually called when you press on the button i don't even need to do that i can simply go ahead and say on tapped over here because that is the correct signature there we go so now we have created a recenter button which is simply a very simple button with a different display and the reason i did it in a different file like a recenter button view and not in the content view is that i don't really want to pollute further my content view it's already kind of getting out of control a little bit even though it's okay but we can still refactor a couple of different things finally let's go ahead and first check out our view we can go ahead and add an overlay to our map the overlay will be dependent on if the map is being dragged or not if the map is being dragged then i can go ahead and return any view and in the any view i can return re-center button now why are we using any view well because it's drag can have two states one of them can be a if it's being dragged but the other one can be if it is not being dragged so if it is being dragged we will do this or other way around meaning if it's not being dragged let's see where we are uh it's kind of getting out of control over here now there we go so probably we have to do it over here then we will go ahead and say any view and we will return an empty view an empty view basically simply means that it's empty it doesn't really have anything all right let's go ahead and build it so that we know that at least the code that we're writing is correct we will also want to do some sort of an alignment for the overlay and we will simply say bottom and i would also try to add like a padding or something and we can do the padding a little bit later but if you want you can simply go ahead and add some padding to it all right so if it is being dragged then go ahead and show the recenter button and if it is not being dragged then we will do something else now if you click the button recenter button which means that okay i'm done dragging and go ahead and resume like re-center it we want to re-center it so how do we recenter it we will go ahead and call place list view model dot start updating location don't worry this function doesn't exist and is dragged equals to false the start updating location function we need to implement in our view model so i'm going to go back to my view model which is place list view model and in the place list view model i will go ahead and implement start updating location so let's go ahead and add that function you can add this anywhere you want so right over here will be fine you can see that the start updating location function is actually simply calling the start updates of the location manager so in the location manager now i will go and i will create a function called start updates as well as stop updates so let's go to location manager and create these two functions these functions are kind of like just a layer i mean they don't really do much they call the location the real location manager or stop updating and start updating now another thing that we want to do is when we have assigned the location when we have finally got the location in our place list view model which is at this point we should go ahead and stop the updates so self dot location manager dot stop updates this means that we are only going to get the location once and then we're just going to stop it unless and until the person says hey i want to re-center and then we can get more locations all right all right so now let's go to our content view and let's go ahead and give it a try i'm going to go ahead and run this and now let's go ahead and move oh now you can see that is pause it's not really getting the location but if i press recenter now it's re-centered so this means that i can go and look at the map a little bit i can look at the sunnyvale or i can move around the area or i can go and hang around over here on the ocean side or the lake side and then if i re-center boom i am re-centered so this is really good because it allows me to look at different groceries so if i want to check out different groceries oh i can check out this one over here near the sylvan park and if i want to quickly jump to my location i can simply say recenter so this allows us to pan the map which is great it also allows us to filter all of these different things you can see that we are filtering which is great and panning perfect so this concludes our building of the near me app completely using sif ui with the mvvm design pattern if you like this section the multiple section that i've added please go and rate and review the course on udemy and i really appreciate your rating and rating reviews always help to provide and add more content provide more updates and thank you so much for your continuous support wow that was a very long tutorial and hopefully you have enjoyed it if you want to support my work then the best way would be to check out my courses on udemy i have a lot of different courses which can benefit you you can see core data in ios course mastering rx swift codes passive income for developers if you want to know how to earn more money as a software developer this course is for you i have a swift ui course which is more than 23 hours and more and then combine course mvvm design mvvm ios development course in sift ui firebase course rx5 core so everything you can imagine in ios i have created a course on it and i am continuing to add more and more content more and more courses on ios development so if you want to support then the best way would be to check out the links in the description of the youtube and use those links to purchase the course because if you use those links then i get to keep a little bit more revenue that will help to create and update new courses thank you so much for your continuous support
Info
Channel: azamsharp
Views: 1,641
Rating: undefined out of 5
Keywords: SwiftUI, ios development, swiftui mapkit, swiftui mapkit current location, swiftui 2.0, swiftui tutorial, swiftui tutorials
Id: Rhni99ZrLd4
Channel Id: undefined
Length: 66min 11sec (3971 seconds)
Published: Thu May 06 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.