Multiple Sheets in a SwiftUI View | Continued Learning #7

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
what's up everyone i'm nick this is swiffle thinking where we cover all things swift and swift ui related and in this very fun video we're going to look at presenting multiple different sheets from a single view in our swift ui application now if you were with me in the swift ui boot camp i already did a whole video on how to use the sheet modifier the basics of how to use sheets and in that video i discussed how you should never use conditional logic in the closure of your sheet and now the reason i'm doing a whole video on this specific issue is because it is probably the most common issue that i've seen on stack overflow from people who are learning swift ui and the issue is very simple that people use a sheet modifier they try to add some conditional logic in the sheet and then when they go to present a second or third screen it's showing the wrong screen so in this video i'm gonna first walk you through that exact problem so if you've experienced it before or even if you've never experienced uh you will know what not to do and then we're gonna look at three different ways to very easily solve for this in our app all right welcome back everyone i'm in our xcode project and like we always do let's right click the navigator create a new file this one will of course be a swift ui view and let's call this multiple sheets boot camp go ahead and click create and click resume on the canvas to make sure we're all connected and let's start out this video by setting up our screen here let's add a v stack with maybe some spacing of 20 open the brackets and inside the v stack we're going to add two buttons let's do button open the parentheses let's use the title string protocol and action approach the title let's put button one on the action click enter and then i'm just going to copy this paste it again and this time i'll make it button two clickers try again on the canvas make sure we're connected we got our two buttons and the whole point of this video is to show multiple sheets from one single screen so when we click button one we want to present the sheet and go to screen one and then when we click button two we still want to go to a sheet but we want to go to screen number two instead of screen number one and the reason i'm going over this is because i've seen so many people have problems with this so let's start out by just addressing the problem and to do that we're first going to create a model at the top here let's create a struct and we'll call this uh random model why not let's make this conform to identifiable and then we'll open the brackets and to conform to identifiable we need an id so we'll say let id and we'll set it equal to a random id so uuid open and close parenthesis dot uuid string just going to create a random id for each model and then very basic let's just add a title so we'll say let title of type string all right now in our view let's create and and at the top here we'll create an at state var selected model of type random model and we'll set this equal to start to a random model and we'll give it a title of starting title why not and when we click button one we want to update the selected model to a new model so we'll say selected model equals random model and we'll just say one and then when we click button two we'll say selected model equals random model and this time we'll make the title 2 and then we want to present a sheet because after all this video is all about presenting sheets so i'm going to add a dot sheet modifier we're going to use the is presented and content and i did an entire video in the swift ui boot camp on sheets so i'm going to assume that you already know how the basics of a sheet work and what we're going to go through now is just more advanced ways we can use this sheet modifier because it is a little tricky to use so if you're not familiar with this sheet and this is presented a little logic here i will link my original video in the caption below so you can get familiar with the basics of a sheet first but if you are familiar definitely keep on going here and as you know we need an is presented boolean so let's create an at state var show sheet of type bool and we'll set this equal to false and we'll bind it with the money sign show sheet and then lastly we need some content to present and i'm going to create a new screen for this content so at the bottom underneath this struct i'm going to create another new struct for a second screen this will say struct let's call it next screen why not we'll make it conform to view open the brackets and every view we know needs a body and we'll open the brackets again i'm going to keep this really simple because i don't really care how these screens look i just want to go through the sheet logic with you guys so let's just add a text here let's just leave it a blank string for a second and we'll give it a dot font of large title and when we are showing the sheet we want to present the selected model so in this next screen i'm going to pass in as a variable we'll say let selected model of type random model and then the text will actually be the selected model dot title alright so this should not be anything new to you guys we're just creating a very basic screen here we're just with some text and the text will be whatever the random model title is so either one two or starting title and in the content we're going to present a next screen open the brackets open the parentheses and selected model and now of course i can pass in the selected model here and i'll pass this in and the last thing we need to do is actually toggle the show sheet so when we click button one we're gonna update the selected model and then we're going to say show sheet.toggle when we click button 2 we're going to update the selected model and then show sheet dot toggle so if you've never done this before you would probably expect that when we click button 1 the selected model is now going to say 1 instead of starting title and then we're going to show the sheet and when we click the show next screen it's going to show us a selected model which hopefully will have the title of one and if i run the simulator and i click on button one you'll see that it still says starting title because it does not work that's what i'm highlighting here this approach is very very close but it actually does not work and i want to note that if i run it one more time and i click maybe button two it doesn't work and if i scroll wipe it down and then click it again it will work on the second time so this really throws some people off because it seems like it's working some of the time but it doesn't work all of the time and the problem here is that the content for this next screen is being created as soon as this sheet modifier is added onto the screen so when this v stack is drawn onto the screen we draw this sheet and that's at the very beginning as soon as we load the screen and we know that when we load the screen before we click any button the selected model actually says starting title and that's why when this content is created it still says starting title so again if i start the simulator one more time and i click on button two it's still going to say starting title that's because this content was created before we actually clicked on the button and i'm going to show you one more way that does not work so you don't have to copy me here but i've seen a lot of people try to get around this problem by adding some if let some conditional logic into this content so i could do maybe at state var selected uh index of type int and we'll set it equal to zero and when i click button one we'll say selected index equals one and then for bond two we'll do selected index equals two and then for the content instead of just the next screen we could do something like if selected index is equal to one next screen with a random model and we'll give it one and then we can say else if selected index is equal to two and i can copy this and put this here and we can do number two and then i can do else so if it's not one or two we just do a next screen with a selected model random model and we'll say starting title so this time we have some conditional logic inside the sheet so that hopefully if we update the index to number two it's going to present us the next screen number two so i'm going to try again on the simulator quick let's reload it this is not going to work i'm doing this on purpose just to show you guys if i restart the simulator and i click on number two it still shows the starting title so even though we tried changing the selected index to two and then hopefully adding some conditional logic and presenting this number two this does not work either and this is why in the first sheet video i kind of touched on the concept that i would avoid adding any logic inside this she closure whenever possible because again this content is executing and it's being created as soon as the sheet is onto the screen so when we first load our screen right now the index is actually zero so it's not one it's not two and we're going into this else closure here so that's why we see the starting title at the bottom and now that we've reviewed a couple different ways how this does not work let's just jump into the solutions and again i have seen this question and people trying to execute something like this so so many times on stack overflow and udemy because you know this seems very logical but of course it does not work so i'm going to delete all of our conditional logic in here let's put our next screen back i'm going to delete this selected index we're not going to actually use it and up here as well and we're going to go over three different ways to get this to actually work i'm going to put at the top here just a little comment the first way we're going to do is use a binding the second way we're going to use multiple dot sheets and the third way we're going to do it is use the item approach all right so let's first start with the binding and right now again this is the first way that we did it we tried to update the selected model show the sheet and the selected model right now is not updating on this next screen so if i click the resume button i click on number two it still says starting title which is where it started here but what i could do is in the next screen instead of having this be a constant let's selected model equal random model i can make this binding so that if this variable changes this state variable it also gets updated in the next screen so we can do instead at binding var selected model of type random random model and then all we need to do to update that we just need the money sign to bind to the selected model so that simple we were very close the first time if i click resume on the canvas and i click on button two what do you know it does now work and all we had to do was make this selected model binding so that was a nice easy fix and definitely something i recommend doing in your apps if you need to so that was the number one here but a lot of times making this variable binding might ruin other things in this view so if this view had a lot of complex logic in it and for some reason you needed a specific model you couldn't use a binding model maybe because you're using other components that required this model to be static so that it doesn't change well then this binding approach would not work so let's look at other ways that we can solve this and the next we're going to look at is using multiple sheets and when we do this we actually don't need this to be binding anymore so we're going to change this back to let and this is going to throw an error so i'm going to get rid of the money sign here and this time when we click on button 2 we're going to add our own sheet for button 2. so we'll do say dot sheet and we'll use the is presented and then create a second boolean for this sheet specifically so at state var show sheet 2 of type pool equals false this will be money sign show sheet 2 and then the content here the content for number 2 is always going to be this random model so we're going to add next screen open the parentheses and the selected model we're just going to create it right here we'll say random model open the parentheses two so when we're using this approach we actually don't need to update the selected model at all and comment it out here as well and of course when we click on button two we want to show sheet number two so show sheet2 dot toggle and i'm going to resume the canvas here this is not going to work real quick but i just want to point something out so when i click on button 2 it should show sheet 2 toggle and then present this screen but if i click on button 2 nothing is actually happening right now and some of you might also run into this error with sheets and the problem is that you can only have one sheet modifier per view hierarchy so right now this sheet is in the child hierarchy of this sheet okay so this sheet is on this bracket here and the second sheet is now a child of this master parent container and the way swift ui sheets work is that you can only have one sheet per hierarchy so the fact that this one is in the parent container of this one it cancels it out so this is the only working sheet in our view right now but of course this is not what we wanted to do we wanted to present multiple sheets so i'm going to highlight this master sheet here and comment it out and on button number one i'm just going to add dot sheet money sign show sheet let's use the first one and then here we will do next screen open the parentheses random model and the title will say one so now we can actually use two different sheets because they are the same level they're not parent child of each other so while this one was in that parent container the container on this one has nothing to do with the container on this one so if i click resume now we can see that if i click either of these they will work 100 of the time so if i click button number two it's always gonna show me two if i click one it's always gonna show one because these sheets are totally separate now and and this is working so this is another great solution to the problem creating two sheets all you have to do is make sure that they're not in the same hierarchy of each other so if you had like one button on the top left to go to a profile and one button on the top right to go to settings you could do it like this and it would save you a lot of time and effort just to put two different sheets as long as they are not in the parent child hierarchy okay so that's number two down and now we're going to jump into the third way and the reason this third way could be better for some cases is because while this sheet and sheet works we have to create a new at state variable for each one so if we had like a hundred different items or 100 different possible sheets this could be really really time consuming and annoying and i wouldn't want to create show sheet a whole bunch of times this is great if we have two or three but if we need to do like five or ten it would just get annoying so what i'm going to do is actually delete these two sheets that we just added because we're not going to use those anymore for this third effort here and where we have this bottom master sheet on the v stack i'm going to make a new dot sheet and this time we're going to use the item and content completion so normally we use the is presented and then we toggle a show sheet boolean but this time we're going to use the item content but this time instead of updating a show sheet boolean for these presented we need to bind to some kind of variable that conforms to identifiable and is optional so if i scroll up when we created this random model we made it identifiable we gave it an id and now this selected model let's just make this random model optional by giving it a question mark and we don't even need the starting title anymore so i'm just going to set it equal to nil for now and we're going to bind to directly to the selected model so we'll do money sign selected model and because we're binding to the selected model we no longer need the show sheet booleans at all because there is no more is presented so i'm going to delete these while we're at it we can delete this showsheet.toggle we can delete this showsheet.toggle and i'm just going to actually delete this bottom sheet here because we're not using it and then of course we need a view to show when we update it so we're going to press enter here so just like we do on the for each loops i'm going to delete this a little bit of code here and just put a model in so when we click on the selected model it's going to provide us with the new model that has just been selected so that's this model here and the code in here just going to be next screen open the parentheses and we'll just pass in that model and finally of course when we click on button one we just need to update that selected model click on button to update to number two and so now using this item completion i can resume my canvas and you can see how clean and nice and clean and short our code is here and if i click on button number two it should hopefully show us number two and that's because anytime you update this selected model now so all we need to do is set this selected model to anything and it's going to present us another screen and this is actually super handy because it's pretty scalable so for example if i added in here a four each and we did maybe data or zero dot less than 50 click enter let's make this the index and i'm just going to take this button code put it here in the 4-h loop let's delete the second one let's make the button title have button and then we'll do the backslash open close parenthesis index so we can see all the indexes and then when we have the selected model we'll say random model and instead of instead of just saying one for now let's just put in the index so we'll say uh backslash open close parentheses index it's not perfect but you're going to get the gist here and finally this is not this is going off the screen so let's put the whole thing in a scroll view open the brackets i'll cut this put it inside and now you can see that if i click on any of these number 36 we can go to screen number 36. so this is super scalable because now we have all these different possible sheets we can go to if i click on number 10 it goes to 10 if i click on number four it goes to number four it works and it works every time so this will become very useful if maybe you had like a list of profiles or something and you wanted to pass in a user instead of this just model well you could have that profile view and then pass in a user for all of the different users all right everyone that's it for this video if you have never run into that sheet problem you might be just scratching your head here kind of wondering why i went into this in so much detail but i have seen this problem over and over and over again as people try to make their applications so i just really wanted to touch on a couple different ways to handle presenting multiple sheets from a single view i hope this video was helpful i hope this helps someone out there so that you don't post it on stack overflow because i've seen it on stack overflow a thousand times and i've seen people struggling just scratching their head why is this not working well here's the solution all right guys thank you all for watching as always i'm nick this is swivel thinking and i'll see you in the next video
Info
Channel: Swiftful Thinking
Views: 2,505
Rating: undefined out of 5
Keywords: SwiftUI, Learn SwiftUI, SwiftUI Multiple Sheets, SwiftUI sheet not working, SwiftUI how to use sheets, SwiftUI sheet error, Multiple sheets SwiftUI, many sheets SwiftUI, SwiftUI sheets don't work, How to use sheets in SwiftUI, SwiftUI two sheets, SwiftUI many sheets, SwiftUI multiple sheets don't work, How to add multiple sheets in SwiftUI, SwiftUI sheet with many destinations, SwiftUI how to show different sheets, Different sheets in SwiftUI, SwiftUI .sheet not working
Id: 8rCtYoG9JIM
Channel Id: undefined
Length: 22min 23sec (1343 seconds)
Published: Mon Apr 05 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.