Test Your FlutterFlow App On A Local iPhone

The video walks viewers through the complete workflow for testing a FlutterFlow‑generated app directly on an iPhone using a Mac. It begins by explaining why local device testing is essential for native features such as camera, AR, and push notifications that the web emulator cannot emulate. The presenter then sets up the development environment: installing a Flutter version manager (Puro, with a brief mention of FVM), installing Homebrew and Git, and using the FlutterFlow CLI to export project code. After downloading the code, the guide shows how to select the correct Flutter version (3.10.4) with Puro, run flutter pub get, and configure Xcode (opening runner.xcworkspace, setting a development team for signing). The tutorial demonstrates connecting the iPhone via USB (or wirelessly), verifying the device with `flutter devices`, and launching the app with `flutter run -d <device-id>`. It also covers using QuickTime to mirror the device screen. Finally, the presenter illustrates the rapid iteration loop: making a UI change in FlutterFlow, re‑exporting the code, running `flutter pub get` again, and redeploying to the phone, highlighting the speed advantage over full App Store/TestFlight cycles. Troubleshooting tips (e.g., re‑opening Xcode for signing, using the correct project ID, handling wireless connection quirks) are interspersed throughout.
Chapters
So it can be handy for us to be able to test FlutterFlow, not just through the web browser emulator that we have just from Lightning Bolt up here, and also not just through using CodeMagic to deploy it all the way to the App Store, but to be able to deploy locally to our device so we can get some faster iteration of seeing exactly what it's going to look like when we're just running on native. This can be important if you're using things like native functionality like the camera or something fancier like augmented reality or, Firebase push notifications only work when you're on the device and don't work when you're on the, when you're in the web emulator. In fact, it won't even work when you're running the emulator as you might be provided through Android Studio or the, or iOS Xcode as well. You really want to get up onto your device. How can we go about that relatively easily on your computer? Now I'm going to assume for a minute that we're working off a Mac. And if you're looking to be developing for mobile, I recommend having a Mac. Handy, even if it's not the primary way that you use FlutterFlow. And that's because it is only from Mac that you're gonna be able to deploy to your iPhone. And it is a pretty convenient environment for making a lot of the other tools we're gonna be discussing today work as well. And that's because Macs are built on this Linux operating system or Unix operating system predates Linux. And the, and that's gonna make it give us more access to things we can do on the command line as we go. Hopefully not too much. We're trying to make this low-code, not like complete crazy code. So let's talk about how we would go about this. In order for us to be able to run locally, FlutterFlow is built on top of a framework called Flutter. And in order for us to be using that, we need to actually get Flutter onto our local system. That means we'll need to get, download a version of Flutter that will work properly. And this gets a little tricky because there are multiple versions of Flutter that are all out there. And if we look at this, we'll see that there have been lots and lots of versions and they and their friends at Google like to keep on releasing new features, and they're not all cross-compatible. And when you look inside Flutter, you will see that there's a specific version of FlutterFlow that they're using. This is here, it says 3.10.4. Hopefully you're able to see that. Okay. And the, and you're going to want to deploy your app onto that version of Flutter. And then this is going to change over time too. So you want to be able to handle a changing set of rules about which version of Flutter we're going to be using. Up until maybe 6 weeks ago, as of this recording, it was running on, I think, 3.7, and now it's 3.10, which was a major change. And then, of course, other changes will happen in the future. So rather than downloading Flutter directly to our computer so we can run it, we're going to get a version manager. And one that's been around for a while and that's pretty popular is called FVM, the Flutter Version Manager. Got a whole bunch of stars over on GitHub, and it, it's pretty solid. I was using it for a while, and then more recently I was introduced to something called Puro, which actually I'd recommend using 'cause I think it's much easier to work with. Where you can go to puro.dev and it gives you some instructions. And the first thing you can do is say, let's curl it. You'll notice there are instructions as well for Windows and Linux, but we're gonna be focusing on the Mac instructions right now because that's a, I find easier place for us to be testing out on our phones. So let's do a little copy here. We'll copy to clipboard and we'll do a paste over to a terminal. And by the way, if you don't know how to bring up a terminal, you can do it by going, by pressing Command Space and typing terminal. I see it gives us a terminal to work with. And then, then, then this guy will show up right here. Cool. So here we are. Let's, let's try running that. It will download the package, it'll install it, and then you'll find that usually you don't get to access PuTTY right away. You're going to need to go to terminal and say, make a new window. Oh yeah, fine. And then you'll find that the, the, the changes it's made in your environment only really take effect on the second time you load the terminal as opposed to the first. Now you'll also see in the instructions, it talks about Flutter itself really wants to use something called Git, which is a version control system. And if you don't currently have Git installed, an easy way to install is gonna be using Homebrew. And Homebrew is a different can of wax, but it's also very easy to install. If you go to brew.sh, there's a little installer script and you can run that again in that same terminal and then follow the instructions that Pyro says of accessing Git as well. You'll find that Homebrew opens you to a whole universe of packages that can be very convenient for your developer journey as you start moving up the ladder of code, because now you're trying to actually run things on your computer instead of having it all run through these third-party services. So once we have this installed, you'll find we have the, we have puro, and we can do --help to find out more about it. And we can do puro ls to find out what versions we have installed. Now I've already installed version 3.10.4. And I gave it a nickname of FF. And the way we do that underneath the quick start here is I say puro create. I just called it FF 3.10.4, and I can just give it a different name. Let's call it Flutter Flow 3.10.4. Oh, it's also puto is not a thing. Puro is. All right. And it goes and grabs all that stuff for us. Npm puro use flutterflow. Oh, okay. We don't currently have a, a project. This actually requires us to be inside a Flutter project, which actually brings up a really good point. How do we actually work with a Flutter project? Right? So let's talk about the easiest way to get a Flutter project onto your environment, which is to be using something called FlutterFlow CLI that is available on pub.dev. I'll put the link to it on the, on, on the description on the video. So in FlutterFlow CLI, we have, you can see it gives us instructions as to how to install it. And I would recommend that you do just that. And we'll just do dart pub paste and dart pub global activate flutterflow-cli. Yes, it looks a little Greek. Yes, it's just the way these things work. You press enter and it will install the command line interface. That's what CLI stands for, for FlutterFlow. And this is really convenient because when you're in Flutter, assuming that you have one of these paid plans, and this doesn't even require the highest end paid plans, it provides you with the ability to download your code, right? So you can say, I want to download your code, I want to view it. We don't need to do it this way. There's actually an easier way to get it onto your Mac. And that's going to be through using the FlutterFlow CLI. So at this point we can say flutterflow, and I always like to end things with --help as a way to start to explore how these things work. And it will ask for a token that we will need. In order for us to work, and then only has one subcommand, which is called export code. Export code is what allows us to download all this code that we have from FlutterFlow onto our local Mac. And that's a really cool, convenient thing. So you don't have to just say, I'm going to download it when, like, the zip file that you download the website. You don't need to go through the ceremony of going through your GitHub repository, although both those can be good things. This sort of provides you with an easy and frankly kind of repeatable shortcut because one of the things you can do in the terminal also is you can press the up key and it remembers like the recent things you did. So things you want to do over and over, we can just apply this way. So now we've got the— now we have FlutterFlow installed and we can, and by the way, if FlutterFlow for some reason isn't coming up, do the same trick I just did, which is to open up a new terminal window. And by the way, the Mac is telling us that we can do that with a Command+N. So if you just do Command+N, it will bring up a new terminal window as well. And at that point, you should have FlutterFlow available to you. Let's clean up a little bit. Great. Okay, so now we have FlutterFlow, and to do it, we're going to need a couple things to make it work. Let's go back up. For that, we're going to need the API token. For that, we go back over to FlutterFlow, and we go, hey, say FlutterFlow, here's information about me, my account over on FlutterFlow, and I'm going to move this over., and I can click on my name. And on my name, I have, ooh, look at that API token. And now we can go look at it. Ooh, very scary. Now I'm going to change API token. It's not going to be very useful for you, but this is where you find it. You go under FlutterFlow, you click on your name, you scroll down, you find your API token. And this will work if you have either of the two paid plans, either the $30 version or the $60 version. And so I can say, flutterflow -t and then paste that token because this button here copies it to the clipboard. And that means I can do Command+V and it will paste it over here. Export code. And it'll tell me that export -code, not underscore. So important distinction. And now it needs to know the project. So project. So what project are we talking about here? And I go back over here to my projects and I go to tiered test. Now up here, you see where it says test-pkha, right? This business where it usually has a name of your project followed by a dash and then some other bit of business. That other bit of business, that's project ID. So I paste that in and test dash because in fact, doesn't just want the code, wants the whole thing. Let's see. See test. Test. Test. Ah, okay. So the problem here is because I have a, I have a file in this directory that's also called test, which is competing for attention here. In this case, I'm just gonna make a directory called flutter_flow. And now in here, I'm going to do the same thing and, like, just tell it to go export test. And boom. Go. LSL. And you see this directory here called test. And I say cd test. And by the way, if I want to do take a look at this over in, over in Finder. By the way, you can do that from the command line by just saying open dot. You can see down here, I've got my Android assets, whatever. See, all these things are in the top level of my Flutter package. Now, if you are into Flutter, you start to recognize some what you're looking at here. And if I were just doing an ls -l, you'll see here I have the README, the Android, the README and the Android and all that good stuff. What do we do with this? So, so now we have installed Puro. We have a version of Flutter. We have the FlutterFlow CLI and we've downloaded the, the code onto our machine. Now at this point, let's see if we can get this thing to run. So we can say flutter— actually at this point it might be helpful for to say puro, to say puro --help because puro will allow us to have different packages, have, have different environments, different Flutter projects we're working on, have different versions. This is not super useful if all you're doing is one package with FlutterFlow, but can become important, particularly if you start to have older Flutter packages and newer Flutter packages, what have you. And this is where the use thing comes in. If I say, uh, puro ls, then I can say puro use flutterflow and it will tell me I'm using the environment flutterflow. And now I can do flutter version. And it should confirm for me that's using version 3.10.4, which is the exact same thing as we have over here in our FlutterFlow web interface. Cool. Great. So the next thing we want to do is try to run it. And so we can say flutter help, and this becomes, okay, how do we want this thing to run? And this is going to be where we start to get into just a little bit more work that's gonna take us outside the realm of just being in Flutter. Now we can run this thing in Android, but one of the great things about running this in macOS, to my, my opinion, is that we can run it on iOS and I could run it on my nice iPhone here. So we'll save Android for another day. We're gonna talk about how to do this with iOS. Here, I will go to Xcode. Now, if you don't currently have Xcode, you should get it. And you probably already had to get an Apple developer account in order to be able to think about deploying your stuff onto iOS. In, in, in FlutterFlow anyway. At that point, once you have that, it should be free download off of the app of the Mac Store, Apple Store. And I can just click on the Apple Store icon down here and I can look for Xcode. And of course I already have Xcode installed and you can download it and then you run it locally on your machine. It'll want to do a certain amount of setup. We'll leave that for other people in other videos. So you want to make sure this thing has been installed in order for you to be able to work with this. Now, the other thing we're going to have here is it's going to require us to take a look at our, you know, we can take a look at our organizer. Let's see, devices, I think. Yep. Okay. And now we have my phone. Yep. It's called Raymond's iPhone and here it is right here on camera. And it will, it knows that currently I am locked and now it knows that I'm not. And now it's actually connecting. You can see that sort of it's gonna keep track of these things. This is important because the way FlutterFlow works by talking to Flutter works by talking to Xcode. The way Xcode works is then gonna go talk to actual device. And you're gonna want to make sure that through Xcode you have connected your, your phone to your, that you connect your phone to Xcode so that we can build this whole bridge all the way through. Otherwise, you will have access to things like emulators that'll be available to you directly through the Flutter command line, but that's not nearly as helpful for the purpose of your testing. Now, one more thing about this, you see those strings on me, there's a little bit of setup that you'll need to do, and you can go look this up to, to configure your phone to work wirelessly with Xcode and to sort of establish that kind of trust. Okay. Otherwise it works easier if, if it's just plugged in via a wire like this one. Now I've got my phone. Great. It's here. I've got my Flutter SDK going on here. Let's do a— the first thing we wanna do is say flutter pub get, and that will install the dependencies associated with our Flutter package. They're usually pretty quick. It's not actually a huge amount of code and I can do flutter help and flutter devices is pretty handy because it tells me all the devices I'm talking to right now. So we've got 2 connected devices. Very exciting. Cool. So you can see here that it shows 2 connected devices, which are the macOS desktop and the Chrome web browser, and then one that's wirelessly connected, and that's my, that's my phone. That's over here. Now it's giving some guff about like getting symbols and all that, but I don't actually think that matters that much. We will find out though, won't we? And this thing doesn't seem to agree that's waiting for— I'll try it again. Now this can happen, like the wireless device thing can be a little bit persnickety, but right now it seems to be working. But if it's not working, I recommend just sort of plugging it in with a wire to just go right back into your Mac or what have you. Let's, let's take the next step here. Let's try to do flutter run -d, and here we can say please run on particular guy, whatever the name is. By the way, you can also choose the, the ID here and that should work fine. And here. Yeah. So it doesn't like that. So we're going to plug it in just like this. We're now going to do a Flutter devices. It shows up right here at the top. This just leads to slightly more reliable work. So I would, I would recommend checking it out. Okay. And then doesn't like Raymond iPhone 2 Mobile. Okay, fine. So let's just use the ID because there's something wrong with whatever I've set up there. Okay. And here, paste. And now it says downloading the iOS tools. Excellent. Now we're starting to actually work with this stuff. And let's just step back and see how well it does for itself. Now it's launching on my phone in what it calls debug mode. It's signing using a default signing. It's pod install. It requires a development team in order for it to work. Okay. This happens. So when it happens, what you want to do is say, ls -l, cd ios, and in here we have runner.xcworkspace. Want to open runner.xcworkspace. And when you do, you'll just run up and you'll open it up here in Xcode. And then we go over here where it says runner. We click Signing and Capabilities. It requires a development team. Yep. No problem. We'll just pick a personal team here. No problem. So once you— Apple's big into signatures. So let's go back over to here and we will go back and try to run it again using that particular ID. All right. So it's going to run directly onto my phone. I got plugged into the wire. So they're not dealing with the wireless and whether or not the wireless is going to work. Now, the other thing I can do here is I can bring up QuickTime. And I can do that here, but I'm just going to go here and say QuickTime from the launcher. I don't know, you pick one of these guys. And the file, I'm going to go to create new movie recording. It's not a screen recording. And hey, there's me. And you can scroll down here. So initially it has camera, it has microphone, and here it has screen. Screen, I can pick Raymond's iPhone 2. Yep. And this is actually my phone right there. See, so my phone is currently displaying. And now we'll be able to see it show up directly onto, and that should make it more visible for you as well. Gotta tell you, this is not gonna win land speed records for it to open up. If it hangs on you, and I don't know if it's doing that for me right now, but I'm going to try it again. I can just do Ctrl+C to make it stop. So Ctrl+C and then run like this. Okay. Automatically signing. Right. Build. You also keep track on top here of what program it's running under the covers. Right now it's running LLDB. And this right here is the way it will look. It's got the same thing up here on my device. You know, if I, if I change orientation, it keeps up with me and it gives me a little notification every time that I press the button. I can also, over here it has commands that are frankly more interesting if you're editing the Flutter using more of a local dev environment where you're running it through FlutterFlow. You just sort of go through this whole cycle. Okay, so now we have the app up and it's running on my phone. We've gone all the way from having it in FlutterFlow to being on my phone. But you want, you can go make a change in FlutterFlow and then you want it to get reflected back over here. Let's just say for the sake of argument, I wanna change this text and have it say, instead of saying, I don't know, like instead of having it say state change, I want it to say YouTube. And let's say my, my, even my change is as simple as that. Now I can come back over to here and I can say, stop this. And I'm going to say FlutterFlow. Remember I had my directory called test and that directory, that test directory is my FlutterFlow here. But what I want to do now is re-export whatever I have from FlutterFlow into here. So how do I do that? And I'm going to do that using the FlutterFlow command again. Remember we installed that FlutterFlow command line program. And the other trick we can use here is that thing I told you about history. Right where I keep on pressing the up key and it remembers other things I've run in the past, including lots of attempts we've made to make this thing work just quite properly. Yeah, here we go. Now FlutterFlow -t, that was my token that I have, the one that's about to be invalidated at the end of this video. You have the ability where we give it the command of exporting the code, please export to test and go. And put it into the test directory. If I go to cd, use the version on the disk. Whenever you see this kind of thing here, usually you wanna say please use the version on the disk. And actually it's best practice to close up just like I just did, close up Xcode when you are making changes through FlutterFlow or through Flutter. So I will say cd flutter, da da da da da, actually cd test. And then I will go and just do flutter pub get one more time just to make sure it has all the proper dependencies. I'll say flutter run. In fact, flutter devices. I forgot the ID of the device. Now, of course, I could also use the up key just like we talked about. If I'll say flutter run -d, because remember we gotta pick a device to go on here. And then, oh, that's actually not the thing we wanted to copy, is it? So let's copy the ID here. This thing with the, starts with zeros, ends with an E. Copy, paste. Uh-huh. And we run that. Here's QuickTime over here. And here's my home screen. You can see what it's all about. And da da da da da, no. See, it gave us the same problem again. This is gonna happen. And there's some other ways of solving this problem, but one of the easiest ways to solve this problem is just to run, just to just say open ios/runners.xcworkspace. If you tell it to run this, open this, it'll open it up in Xcode. And then you can say, pick the team. By the way, the whole keep thing on disk might have also helped with that, but it's not best practice. Best practice is just to fix it when you, when it comes back around. Because now all you need to do is say, you know, run the Flow, fix it on the, on the workspace, and then say, let's just go and run it again. And it will deploy it onto your device. And bring it on up. Here it is. Test. That guy down there. We're just waiting for this thing to get booted and to sign and to install. And when it does, it will come on up. See, loading it right onto my phone. See, now it says YouTube. So that's all it takes for you to go make changes in FlutterFlow and for it to cycle all the way around. I'm not gonna say this is as easy as just running it inside the web simulator. Because Web Simulator is there to allow you really fast feedback for things that are as trivial as like little UI changes like this one. But where it really pays its rent is going to be when you're changing things that relate to native things like, like push notifications, like using things that are going to be native functionality, what have you. And you get to have that cycle very quickly without having to go all the way to the App Store, all the way to TestFlight and back. You can have it locally running right off of your computer and you're able to do that from soup to nuts. Twice, just like we've done here in about half an hour. I hope this was helpful. This is hard stuff we do on the daily over at StateChange. And I'm looking forward to more ideas for more videos. So if you have thoughts, please put them in the comments and I appreciate you getting to watch today and then look forward to learning with you. Talk to you soon.










