In App Purchases Tutorial (Consumable) - Swift 5, Xcode 12, 2020 iOS Development

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] what is going on guys welcome back to another swift video in today's video we're going to do a deep dive on consumable in-app purchases and we're going to be building the app you see here so basically we're going to have an app where the user can purchase and store diamonds and of course they can purchase different quantities so let's go ahead and we're going to buy a thousand because we're super loaded let's go ahead and hit that button to confirm we'll see the transaction goes through and more importantly we'll go and see that our actual account goes up we close the app let's switch to dark modes make sure that looks nice and good to come back you'll see that the amount is persisted so we are indeed saving the newly added and purchased diamonds and it works in all these different quantities we'll look at creating the ui and all that good stuff so as always let's get started by absolutely destroying that like button i'm gonna be annoying and say it twice hit that like button it helps out video engagement youtube algorithm all that good stuff helps me make more videos for all of you hit subscribe while you're at it if you're a returning viewer get xcode ready get excited let's talk about some in-app purchases all right we're going to begin by opening up xcode and creating a new project we're going to stick with an app template and i'm going to go ahead and call this consumable iaps make sure your language of course is swift lifecycle ui kit and interface storyboard go ahead and continue we will save it to our desktop looks good looks good and once xcode is ready go ahead and expand your window to give yourselves a little more room to work let's pick a simulator i'll stick with the 12 pro max since i've got it booted already hit that run button so it gets nice and ready for us and let's see we should see an open empty app here just like so and let's get into it so we're going to need essentially two things in this uh project uh a ui where the user can go and basically see how many uh diamonds they already have purchased basically that are saved and then of course go and initiate more purchases and then we also need a class that's going to handle basically cueing up those purchases so our view controller will be where our ui is and we're going to need another object like mentioned so let's go ahead and create a new file and we're going to do this from bare bone scratch so select swift file and i'm going to go ahead and call this uh let's call this iap manager for in-app purchase manager let's go drag this up and let me just stub this out and then we'll go and set up the ui quickly since it's fairly simple but basically this is going to be a final class iap manager we're going to have a shared instance on this which is going to make this a singleton if you're not familiar with singleton i've got a video on that so go ahead and take a look at that and let's see we're also going to need to initiate in-app purchases so let's go ahead and import story kit and we'll see how to set this up in a moment and let's go back to our view controller so what i'm going to do here is you can set up your ui any different way but we're going to set up a table view and we're going to like i showed you in the beginning going to be allowing users to purchase diamonds in the quantities of 500 1000 hundred and five thousand and at the top here we're gonna show how many diamonds the user currently has uh purchased and that's gonna persist between app opens and closures so we're gonna go and create a table view on here so i'm going to say let's table view is a ui table view and this is going to be a very very basic table view nothing fancy going on here we're just going to create it in this anonymous closure we're going to go ahead and return it and we definitely want to spell it correctly because that's slightly important you want to go ahead and register a cell and give it an id of cell i'm not going to do any custom cells or any of that stuff here since we want to keep this nice and simple let's go ahead and add this as a sub view let's assign its delegate and let's assign its data source and let's also give it a frame of view dot bounce so it takes up the entirety of the screen let's not forget to conform to the delegate and data source protocols up here sometimes auto complete let's throw in some random code so make sure you get the right one up there so once you have those implemented it's going to give you an error because there are two minimum functions you need go ahead and hit fix and it'll stub it out for you and let me just move these down here make it a little cleaner for a number of rows remember say return models dot count don't worry we haven't created this yet for models here we're going to say let's sell equals table view and we're going to dq a reusable cell with a identifier and an index path identifier will be cell because that's what we registered up above here we're going to say cell here we're going to say text label dot text we're going to assign to something and text label rather cell dot image view dot image is going to be a ui image and i grabbed a system image before i thought i did at least i believe it is called suit diamonds dot phil i grabbed this from sf symbols it's just a diamond shape just so it looks nice and uh professional let's give it a tint color uh let's go to system blue and let's create that models up here and run our app to make sure we're in business so models is going to be an array of models and i'm going to come up here and create this array of models rather create a struct 4 model which is going to be what we put in the models array and a model is basically going to have a title on it and it's going to have a handler which is going to be a closure that takes no parameter and returns void and instead of doing it like this and creating it out here let's say this is an array of models go ahead and create it like that and here we'll configure our models and i know i'm going through this kind of quickly don't worry i'm going to review all of it but basically we're going to say let's just append a model in here one at a time the first one is going to be 500 diamonds the next and then this thing is going to be a closure we're going to leave that empty and go ahead and copy and paste that three more times and just update this number so what did i say 500 a thousand 2500 and 5000 and i think we should be good to go here we just want to update this to use the title from the model so here we're going to say the model is a model let's get it with the index path dot row and here we can say this is the title i think we're in business go ahead and hit command r to build and run and you should see your table view here hopefully i didn't forget anything next up we'll look at how we actually go ahead and uh prompt the purchase so looks like we don't see our image i might have spelt this wrong so let's go ahead and open up sf symbols and let's look for diamonds in here let's see it's suit.dimind so it's not plural let's drop that s let's run that one more time and awesome looking good so we've got our diamond we've got our quantities here and we select it nothing's happening at the moment but we're going to kick off a purchase so when we select it we want to implement did select row at index path we want to deselect that given row at the index path with an animation and then we want to get the model and just kick off its handler so i'm going to copy and paste that and here we'll say models.handler and add two parentheses to kick it off so what else do we need to do so we need to set up the iap manager here and there's going to essentially be two things that we need to uh do here one is going to be fetch the products from the app store and we're going to set up a debug file in our project so we can test it locally on the simulator and we also need a way to kick off a purchase so first let's create a function called fetch products we're going to have an array on here which is going to hold those products which is of type sk product and it's going to be an empty array by default and it's a product not a discount let's get rid of that and let's see in here what we want to go ahead and do is say request is going to be an sk product request and this gets uh created with product ids whoops you want this one here product ids i will fill that out in a second we're going to say request.delegate itself and request dot start now we want to conform to two protocols up here sk product request delegate and sk payment transaction observer and there are two functions we want to implement here the first one is product requested finish we're going to say self.products equals response dot products just like that and then here we want to implement updated transactions this one right here and this is where we handle the actual transaction once it gets gets once it gets kicked off so it's actually quite simple we'll implement it in just a moment but let's see what else do we need to do in here we do need apparently something else because it's complaining so the reason is complaining is the class that conforms to these and needs to be of type ns object and we need to add that up there because the reason it needs to be of ns object is because apple has not updated these protocols yet to be non-objective-c supportive in other words they're still bridged with objective c hence the ns on here so just make sure you add that and you'll see that error go away now when our app launches we want to kick off fetching the products right away so we're going to go to app delegate and to get this window you hit command shift o to search your project for files and in application did finish launching we're going to say iap manager shared dot fetch products just like that and that'll fetch your products as soon as your app launches you'll be good to go and kicking off purchases so the user doesn't have to wait and now let's actually fill in the product ids so you can just hard code them in but what i like to do and what i recommend you guys do as well is create an enum of product and in here each of your cases can serve as a product with a given id so i'm going to say here string and case enterable and we're going to say diamond underscore 500 and this is going to be we can just leave it as is but you can specify your own custom id here but i'm just going to leave it like that since we'll just use this as the id itself go ahead and copy and paste that and just change up the values here and now what you can do is in this array rather this actually needs a set not an array this parameter you can say product dot all cases and you can say compact map dollar zero dot raw value so i'm not mistaken and you can wrap this whole thing into a set and that should be good so basically what you're saying is take all of these cases in the enum um get them get all of them and then convert them all just to the raw value which in this case will just be the case so anytime you want to add a new product in your app you can just add a case here and everything will just magically work which is really nice it makes your app really extendable so now that we have this set up basically this is going to go to the app store and try to get the products that we are running in a debug environment and we haven't set up the app store nor is it supported in the simulator so what i'm going to go ahead and do is bring in a new file and that new file is actually new for xcode 12. it's called a store kit configuration file and you don't need this to be checked but just go ahead and create it and you can actually create all of your products in here and you can test live in the simulator now it's important that your product ids do match so i'm just going to copy this first one and when we come back to this file we can hit at the bottom left here this plus and we can hit add consumable product and we're gonna want four of them so go ahead and hit that three more times just like that all right and then let's go ahead and paste in our id so this is 500 500 diamonds and this one is going to be a thousand a thousand diamonds this one will be whoops let's not select them all it's not what we want to do this one's going to be 1500 unless i'm mistaken and this uh this name i'm filling up here is just a reference name it's not the actual name that's gonna show up in the table view just be mindful of that it says 25 here we're going to say 2500 diamonds and each of these products actually has associated metadata which we're not going to fill out for now since we hard coded in our table view the names however you probably do want to fill this stuff out and when you do fetch the products from the app store instead of hard coding your models like we do here you want to actually use the title and the description returned from the app store since that's basically something you can control remotely and that also supports all the different languages assuming you supply them so now that we have this file set up let's go ahead and make sure everything is saved we can actually run it and see that our products do come back and let's see how we can do that so in our iap manager let's go ahead and let's print out here response dot products dot count and i'm gonna say products returned put a colon and just stick that in right there and one thing that's really important to do when you're testing this on a simulator is hit this list hit edit scheme and you want to actually supply that store kit file right here so it says store kit configuration we're going to say configuration.storekit which is the file we just created go ahead and close that and i know there was quite a bit of setup so go ahead and hit this play button let's make sure it's working and we'll uh review that in just a moment so we should see print down here that we returned three products so we should have four so something's up so we did 500 1025 and 5000. i'm 99 sure i made a typo in here so let's see we've got 500 a thousand 2500 and this one should be 5 000 actually not 15 i had a feeling i was typing that incorrectly go ahead and hit command r one more time and you should see now four products so now when we click on any of these you want to kick off the actual purchase so for that we're going to go back to this iap manager and we're first going to implement this and we're also going to need to create a function called purchase and this purchase is going to take a product which will be our enum for product just like that and in here in this function all we're going to want to do is given the parameter of transactions we're just going to want to do a for loop on these so we're going to say transactions for each and in here we're going to switch on dollar zero and dollar zero just represents the given transaction that we're iterating over and its transaction state and you'll see an error here you can just click on this and hit fix and it'll go ahead and stub all of these out for you and let's go ahead and clear all of these and change them all to breaks for now and we're going to need to implement purchase here in a moment let's just leave it there for now and in this function what we're going to do is we're going to first make sure that the user can make purchases so we're going to say guard sk payment queue defaults whoops actually not default to take that back can make purchases else we're going to return we're also going to make want to make sure that we can find the product in this products array with the given id so here we're going to say guard let store kit product is going to be products plural first where dollar zero dot product identifier equals product dot raw value so this product here that we're passing in i feel like i'm saying it weird just to specify not the plural version is what we're passing in which is our enum here so we're going to try to pull out of the array the store get product then the first one that matches the id all ids have to be unique so we don't have to worry about duplicates and then here we can go ahead and do is we can say that we want to create a payment request which is a sk payment with a given product which is our store kit product that we just pulled out we can then say sk payment queue defaults and we can say add observer we want to add self as the observer and then what we want to go ahead and do is say sk payment queue we can actually copy and paste this and we can actually add the payment request now and what this will do is this will kick off the payment and you'll see the bottom sheet pop up on your simulator like a normal in-app purchase so go ahead and hit command-r to build and run and let's just click on one of these and actually nothing is happening and the reason nothing is happening is because i never hooked up these handlers in these models so on this one we're going to say iap manager shared and here we're going to say purchase and the first one is going to be diamonds 500. let's go ahead and just copy and paste these it would just change up the products that we're passing in control i to fix up your indentation there this one's going to be a thousand this one will be 2500 and this one will be 5 000. go ahead and hit command r to build and run and let's say we try to purchase 500 diamonds we click on that and it looks like there it goes a little slow so you might want to show a spinner while it's loading and it looks like this popped up here so we have 500 diamonds we have the price which is 99 cents if you're wondering where that price is coming from it's coming from our configuration file here here um you'll also notice that uh we're not showing any description or anything here either that's because we never set up this localized information here but the cool thing is is that it's working now the next thing that we want to do is once a user purchases these we want to save it to device so we know how many uh how many actual diamonds they have and then we also want to show it up here and we're going to use a header to do that so i am going to go back to the view controller and here we're going to create a computed property and this is going to be my diamonds count which is going to return an integer and we're going to return user defaults where we're going to save basically the number of diamonds we have and we're going to say integer for key diamond count and if this is a nil for whatever reason it's going to go ahead and return 0 and here i'm going to create another function that's going to say set up header and here we're going to create a header and add it to our given table view so here we're going to say this is a ui view we're going to say table view dot header view table header view is going to be our header just like that and our header is going to have two things in it it's going to first have an image view and this image view is going to be a standard image view with a given image and once again we're going to stick with that system item and rather system image and i believe once again it was called suits dot diamond singular dot fill let's go ahead and add it as a sub view to our header we're going to want to add a frame to it in a moment but before we do that let's go ahead and create a label and this label will be essentially the label that shows our account whoops this is going to show the count of diamonds we have at the moment so here we're going to say header add sub view label here we're going to say text alignment is center so it just looks a little nicer labeled.txt is going to be our my diamond count diamonds now let's go ahead and give this stuff some frames so the frame for the header is just going to be zero zero view.frame.size.width and then just paste that again in here and let's see we're gonna give our image a size as well so let's give this a frame of uh let's see let's make this a hundred by a hundred from the top we'll say it's ten and the x's we want this to be centered so we're gonna say the frame of the width of the frame minus a hundred divided by two and the label will give this guy a frame as well and this is going to be uh 10 120 view dot frame.size.width minus 20 and 100 and i believe we should be good to go so let me just give this a tint color also so it looks like the ones in our table view i think we went with system blue and let's also bump up the font size and the label just so it doesn't look totally ugly we'll say this is system font of 24 with a other 25 with the weight of bold and before you actually run it like i did there make sure you call this function at the bottom of view to load what is it called set up header just like that go ahead and hit command r and you should see a header up here now just like that nice and big and whenever we select one of these and not purchase it we should update basically this header and that would also imply that we update our user defaults and add in the number of diamonds we purchased so how do we do that how do we make that magic happen so what i'm going to do is we're going to go back to the iap manager and we're going to add a parameter to this purchase method and this is going to be called completion and it's going to be an escaping closure that takes in a parameter of integer and returns void and what i'm going to go ahead and do is we're going to take this type and we're going to create it here as a private var whoops private var and it's going to be called completion of the same type and it's just going to be optional in this case and whenever we call purchase we're going to say self self.completion equals completion and whenever we're done with the purchase we're just going to go ahead and call that completion handler and we need to pass in the number of diamonds that's associated with it so what i'm going to do here on this enum is create a computed property again called count and here we're going to switch self and we're just going to go ahead and we're going to return the number of diamonds associated with each of these products this is going to be an integer this is going to be 500. let's just paste that over and over and just change up this value here 2500 and that'll be 5 000. and let's see so now we can actually say we want to first get the product that's being purchased here and pass in its count so what i'm going to say is let's effect product equals our product and we're going to create it with the raw value of the transaction payment product identifier for able to create a product we're going to create the uh rather call the completion handler with product dot count and the last thing we need to do here is uh end each transaction so here we're going to say sk payment sk payment queue whoops sk payment queue defaults and we want to say finish transaction dollar zero and i believe we also need to call remove transaction um looks like we don't actually we just need to say remove observer and that'll be self and we're just gonna ignore these other cases we're just going to stick with purchase here for now and that's all we need to do here in the uh iap manager we just need to add that parameter for the completion handler here so we're going to do it as a trailing closure and what do we need to do in here we need to say week self and we're going to say count in and basically what we want to do in each of these closures is first get the current count of the diamonds that we have and this is going to be self dot my diamonds and if we're not able to get it we're going to say zero then we're going to want to say new count is current count plus count and this count is what we just purchased and now we're going to want to update our user defaults with this new count so we're going to say standard we're going to want to set new count for the same key so let's be lazy and copy and paste this key and absolute final thing i promise is what you need to do is update the header so we're going to say set up header and we just want to make sure that we do all of this on the main thread so we don't run into any issues so go ahead and just wrap that in there and actually we're just going to be lazy once again and copy and paste this you can probably make one function so it's not redundant but you can copy and paste this in front of each of these calls and you should be good to go i went through that very quick so let's see if i made any mistakes and if i didn't we'll review all of it so go ahead and hit command r to build and run and let's see if we're in business so we've got zero diamonds to start we're gonna hit 500 it's going to tell us it's a dollar we're going to purchase it because we are loaded and we see that we've purchased it and we see this is now 500 diamonds so let's uh let's actually go ahead and close the app let's reopen it and you'll see we still have 500 diamonds so looking looking good so let's be uh let's be a baller now and buy 5 000 because we're loaded and not sure why this is also 99 cents i guess whoever made this app is pretty dumb that they priced these the same but let's go ahead and create this and now you'll see we're at 5500 so uh there you have it that's how you can create this and if you change this to dark mode with command shift a you'll see that everything hopefully still looks pretty pretty nice and good um and let's just try the other ones just for the sake of being uh complete here so you'll notice it doesn't actually update until we click out of this uh alert and that alert is a system alert that gets shown when a purchase goes through so you might want to update this to update before this alert gets dismissed it's up to you i think i prefer it this way so you know you're not really messing with the order of operations from the apple side of things but that's how you do it basically so let's uh let's do a quick review and then we'll uh we'll wrap this video up so there are two things that are going on like i mentioned in the very beginning here our view controller is roughly a hundred lines of code and what do we have in here we first have a struct which represents our model with a title and a handler and this is what we're using for our table view rows we've got a table view pretty simple we've got an array of our models so now in view to load we set up our models by appending one in at a time with a name and this is just the name we want to show and the handler basically kicks off a purchase operation and once that operation is completed it returns the count of how many diamonds were just purchased we go ahead and save that into user defaults and we re-create the header so it updates the ui and we basically do that redundantly over and over here you could probably get away with uh putting this title into the products uh enum that we have in the other file and just do a for loop over it so it's not so redundant but anyways here we add the table view we set its protocols we give it a frame we set up the header initially here we just returned the number of rows set up a basic cell and did select we just kick off the handler for the model for this computed property which returns the number of diamonds we return the number that is saved in user defaults now one thing to keep in mind is the way consumable purchases work if you delete the app and come back it's going to start again at zero so the way that we restore consumable purchases is quite interesting because you'd either need to store it on a remote server or not store it at all and that's how we would that's how we would support basically restoring of purchases which we have not implemented here but just a nice call out and in setup header all we do is create a view with a diamond image in it we tack in a label and set the labels text to be the number of diamonds we have and then assign it as our table's header so moving on to the iap manager this file looks a little longer once again only about 100 lines a little shy of it so here what we've got going on is we create this class we make sure it's ns object because these protocols require it to be objective c bridging we conform to these protocols of course don't forget to import storekit up here and we have a completion on here so when the transaction completes we can call back to the caller we have an array of products we have an enum of products with the associated diamond counts we've got a fetch function which we call in the app delegates so the products get fetched from the app store as soon as your app launches next up we have a callback for that product fetch so we can save the products once we get them and this purchase function is where the magic gets kicked off we make sure the user can make purchases and in a real world scenario what this is doing is this is checking if the user has an apple account set up on their device aka they're signed in with their apple id next up we get the product from the products array based on the raw value which should be the product id then we save the completion parameter that was passed in make sure it's escaping so we can actually go ahead and save it if it's not you're going to run into an error we create a payment request and kick it off and last but not least right in here we went ahead and on the updated transactions we for loop and switch the state and in the purchased case we get the count from the product enum call it in the completion handler finish the transaction and remove the observer so that's about it quickly looking at the configuration file this just has mock data locally in xcode so you can test all this stuff in the simulator this was new for xcode 12 so if you're on a older version and don't see it that's why and the absolute last thing i'll mention is in a real project you want to make sure you come here and for your target come to this second tab here and you want to go ahead and hit this little plus capability and make sure you add in in-app purchases now what this will do is it'll add the in-app purchase entitlement to your project so when you submit it to the app store you're not going to run into any issues so there you have it a bit of a longer video than i intentionally intentionally that i initially intended this to be so hopefully it was helpful nice and thorough if you have any questions don't hesitate to leave them down below if you haven't done so already make sure you absolutely destroy that like button as per usual hit subscribe while you're at it for daily swift uploads hit the bell icon so you get notified when i do upload thanks for watching i'll catch you guys in the next video you
Info
Channel: iOS Academy
Views: 6,042
Rating: undefined out of 5
Keywords: swift 5 tutorial, swift 2020, swift, swift 5, swift tutorial, swift for beginners, swiftUI 2020, swift programming, swift basics, swift apps, make iPhone app, swift make first app, swift in app purchases, consumable in app purchases, set up in app purchases, in app purchase tutorial, subscription in app purchases, swift 5 in app purchases, in app purchase swift iOS, iOS swift in app purchases, how to create in app purchase, in app purchases tutorial, 2020 swift purchases
Id: q7iBq-GMNd4
Channel Id: undefined
Length: 35min 4sec (2104 seconds)
Published: Sun Dec 06 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.