Developing and debugging Flutter apps for iOS without a Mac

Gabriel Rodríguez
Jan 10, 2019 · 6 min read

Update: Flutter 1.17.0 now uses XCode instead of libimobiledevice to list devices. At the moment, you can downgrade to Flutter 1.12.13+hotfix.9, or use the new Codemagic feature that allows you to remote control a Mac VM, and run a virtual device there (

It is possible to hot reload and hot restart your Flutter app on your iOS devices without having to use a Mac just like you can with Android devices! Here’s how:

Get a debug build of your app running on your iOS device

You could do that with a Mac (or Hackintosh, or VM), but since we don’t have access to a macOS machine we can use one remotely via Codemagic or Travis CI — completely free! (as long as your project is on a GitHub, Bitbucket or GitLab repository).

Codemagic is recommended as it requires less setup and builds pretty fast

First, create an account or sign in to

Then, click the settings (gear) icon next to your app. Scroll down and click on “Build”. Make sure Mode is set to Debug, and select iOS under Build for platforms.

By default, Codemagic will test your app. Disable this feature unless you want to use it. (Thanks to Near Cz for the feedback!)

After that, build the app (Start your first build).

New: now Codemagic lets you remote control the macOS virtual machine it uses to build your app. From there, you can run a simulator, test your app, and configure it from XCode. See

Codemagic will send you an .app file via email.

Rename it so that it ends with .zip.

Extract it, and you’ll get a folder called

Create a folder called Payload and place there.

Finally, compress the folder called Payload — this will be your IPA file (you may rename it to .ipa).

To continue, skip to Installing and running the app.

Note: the free version of Travis CI only supports public GitHub repositories.

You’ll need to create an account on Travis CI and let it access your GitHub account.

Then, create .travis.yml on the root of your project with the following contents:

You’ll need to have the Travis command-line tools installed: (if the command below isn’t found, install RubyGems from

Then, setup deploying to GitHub releases:

When prompted for a file to upload, type build/ios/iphoneos/app.ipa.

Make sure your .travis.yml ends like this:

Now, push the changes to your GitHub repo:

Now, your app will be built and it will be added to your GitHub releases. Wait a bit for Travis to notice that you’ve added .travis.yml; when it starts you can track the progress of your build. When it’s done, download your app.ipa from your project’s GitHub releases.

Note: If you don’t want to publish your .ipa file you can add draft: true to deploy:, and it will be published as a draft on GitHub instead.

To install the IPA file, you need to download Cydia Impactor from the link below.

If you are running Windows, you need to install iTunes first. (Make sure to install the non-Microsoft store version: under “Looking for other versions?” select Windows, then scroll up and download).

Edit: a previous version of this article suggested installing the drivers bypassing iTunes installation. Apparently, that doesn’t work. (thanks to Andreas Opferkuch for pointing it out)

Update: Cydia Impactor seems to be broken at the moment. If you have a developer account, you may follow Weisser Zwerg’s tutorial (thanks for sharing!) to sign and install the app. If you have a jailbroken device, you may use AppSync unified and ideviceinstaller. There are alternative tools to Cydia Impactor, but I can’t guarantee they’re malware-free, so use them at your own risk.

  • Plug in your iOS device to your computer
  • Run the Impactor executable
  • Click “Xcode”, then “Revoke Certificates
  • Now, drag app.ipa (or the ZIP file you created) to the Cydia Impactor window (or use Device > Install Package…)
  • You will be prompted to enter your Apple ID email and password. If it’s protected with two-factor authentication or you get an error message, you will need to create an app-specific password and use it instead of your password. See (thanks to Near Cz for pointing it out!)
  • On your iOS device, go to Settings > General > Device Management (or Profiles & Device Management), tap your Apple ID email you just used to sign in, then Trust.
  • Hooray! Our app is now installed.

Preparing your machine

Make sure libimobiledevice and ideviceinstaller are installed (the latter isn’t used but Flutter will complain if it isn’t present):

On Windows:

The previous link didn’t have binaries anymore, thanks to Andreas Opferkuch for sharing an alternative one!

Download imobiledevice binaries from here. You also need a “which” binary, which you can download here. Add these binaries to flutter\bin (or any other location, but make sure it’s in your PATH ).

On Arch/Manjaro/Antergos:

On Ubuntu/Mint/etc:

You might also need to install these packages (thanks João Matheus):

Modify Flutter

When detecting devices, Flutter checks whether you’re running macOS before searching for iOS devices. It also checks for XCode. Let’s remove those checks.

Note: it’s not working with the current stable (1.17.0) version. In the meantime, you can use Flutter 1.12.13+hotfix.9 instead.

Apparently, now Flutter uses XCode utilities instead of libimobiledevice, so the patch will not be as straight-forward. In the meantime, use an older version, or help contribute with the patch or another solution (fork, or a way of undoing the specific commits with the changes). I’ll update the article once this gets solved.

We’ll apply these changes to Flutter

Download this file to your flutter folder (Click on “View raw” and press Ctrl+S). Then apply it: (this was tested with the stable branch on late April to early May)

Then rebuild the Flutter tool:



Preparing your project(s)

Make sure there’s a folder inside your project called build. If it’s not present, create it!

Running and debugging

Here comes the good part!

  • Open the command palette (Ctrl+Shift+P), and select “Debug: Attach to Flutter process”.
  • Open the app, and wait for Flutter to sync files.
  • You can now hot reload and hot restart as usual!

Tip: If hot reload doesn’t work, hot restart first!

  • Run flutter attach. This will wait until the app is launched and start debugging as if we’d used flutter run.
  • Open the app, and wait for Flutter to sync files.
  • You can now hot reload by pressing r and hot restart by pressing R!

Thanks to Yegor Jbanov for their post:

Have any questions or feedback? Please leave a comment!

If you liked this, don’t forget to clap, it’ll be greatly appreciated!

Flutter Community

Articles and Stories from the Flutter Community

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store