How to Quit a React Native App on macOS

Project Source Code

Get the project source code below, and follow along with the lesson material.

Download Project Source Code

To set up the project on your local machine, please follow the directions provided in the README.md file. If you run into any issues with running the project source code, then feel free to reach out to the author in the course's Discord channel.

This lesson preview is part of the Building React Native Apps for Mac course and can be unlocked immediately with a \newline Pro subscription or a single-time purchase. Already have access to this course? Log in here.

This video is available to students only
Unlock This Course

Get unlimited access to Building React Native Apps for Mac, plus 70+ \newline books, guides and courses with the \newline Pro subscription.

Thumbnail for the \newline course Building React Native Apps for Mac

We're going to take a small break from adding more features to our app. We're going to spend the next lessons polishing a little bit and preparing it for release. Most importantly, we have traveled the happy path so far. It looks like everything is working. But there are certain details that we haven't paid too much attention with. And now is a good time to discuss them. So among the things that we need to do to release our app, one of them, and this is different from releasing iOS apps, is that your app needs to have a quit button . This just needs to be in there because otherwise it won't pass the app review when you send it to the app store if you want to release your app to the app store. So we're just going to add a close app method. It shouldn't be too complicated. I'm going to go back into Xcode into my building apps native Objective-C file. And here I'm going to add another external method. This one I'm going to call the close app. And it's not going to take any parameters whenever you call it, the app is going to close. So now with that in place, I can go back into my Swift code. Again very similar to the previous functions. I'm going to go and create a function. The name is the same. And then I'm going to do this very funny thing. I'm going to call this patch queue main async and my code. So what's happening here? It turns out whenever you develop native functionality on macOS or iOS, you need to use certain queues. Anything that has to do with the UI of your application, you need to run on the main queue in order to keep the UI consistent and all the operations updating your UI without messing ups on the UI detailed, everything needs to run in a single queue in a single thread. So that's what we're doing. We're calling the dispatch queue.main and then we're saying we want to queue this piece of code to run at some point. After the OS is done updating the UI of our app or doing any other operation, run this code. Now this is important because if you don't use this and you try to do some UI operation, Xcode is just going to explode. It's not going to compile your app. Luckily it does say to you most of the time what's the error? It tells you you're trying to do a UI operation on a non UI thread. So in order to solve this, this is what you need to do. You need to reach into the main queue and queue your code to be run. Now how do we close our app? So we're going to grab our app delegate instance. This might not be 100% necessary but this is the way I chose to do things. Basically I'm just going to grab the app delegate the main file of our application which contains the initialization logic and that's the object that can actually close the application. So I'm going to take this app delegate and this is just type safety again. This exists on Swift. It could be an optional value but it won't be. Otherwise our application won't be running. And I'm going to call the close app method. Great. So now I need to go into my app delegate and it doesn't have any close app method. Right? Even though there is another function that's part of the application delegate protocol, I'm just going to wrap that because you might want to do something else whenever your application is closing. So I'm just going to create the close up function and I'm going to call NS app terminate with an else and there. Right? It doesn't matter to us who terminates the app, we just want to terminate it. And you will also notice that this time we don't need the objective CE decor ator because we're actually calling the code from Swift itself. Right? So this is just a plain Swift function. Let's try to run our application. Great. This is just the keychain operator. Great. Great. Great. Great. So now we can go back into our native module wrapper. And once again here, I'm just going to add the new function that we added. It doesn't take any parameters. It doesn't return anything. And in here, I'm just going to add it. Say my native module close up. Great. So what we can do now is I'm just going to put. A button somewhere. It doesn't really matter where. So I'm just going to do it on my books container. Here I'm going into. Yeah, it's not going to be too pretty, but I'm just going to put it in there. So the title is going to be quit. And I have my own press, my module. I need to import that. And I'm just going to call close up. Now another detail to pay attention to is that sometimes you might be able to bind directly like this into your prop. But sometimes this props pass values into the functions. And if your function takes a parameter or it doesn't take any parameter at all, and then this prop tries to call it with a parameter, then your application is going to crash. So sometimes it's just better to wrap your functions, your applications like this, right? Independently of how you think they're going to work. Just to make sure that everything works correctly. And let me try to save this. Okay, it's not very pretty. I can modify it later, but if I click on it, then the application should quit. (upbeat music)