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 (https://blog.codemagic.io/remote-access-to-virtual-mac-build-machine/)

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

Recommended: Building the app with Codemagic

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

First, create an account or sign in to codemagic.io.

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 https://blog.codemagic.io/remote-access-to-virtual-mac-build-machine/

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 Runner.app.

Create a folder called Payload and place Runner.app 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.

Alternative: Building the app with Travis CI

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:

os: osx 
language: generic
before_script:
- brew update
- brew install --HEAD usbmuxd
- brew unlink usbmuxd
- brew link usbmuxd
- brew install --HEAD libimobiledevice
- brew install ideviceinstaller
- brew install ios-deploy
- git clone https://github.com/flutter/flutter.git -b beta --depth 1
script:
- flutter/bin/flutter build ios --debug --no-codesign
cache:
directories:
- $HOME/.pub-cache
before_deploy:
- pushd build/ios/iphoneos
- mkdir Payload
- cd Payload
- ln -s ../Runner.app
- cd ..
- zip -r app.ipa Payload
- popd

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

$ gem install travis # Makes sure to have the Travis CLI installed

Then, setup deploying to GitHub releases:

$ cd your_project
$ travis setup releases

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

Make sure your .travis.yml ends like this:

deploy:
provider: releases
api_key:
secure: #your api key will be here
file: build/ios/iphoneos/app.ipa
skip_cleanup: true #important or your built app would be deleted
on:
repo: #your repo will be here

Now, push the changes to your GitHub repo:

$ git add .travis.yml
$ git commit
$ git push

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.

Installing and running the app

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 https://support.apple.com/en-us/HT204397. (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

Install dependencies

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:

$ pacaur -S libimobiledevice ideviceinstaller-git

On Ubuntu/Mint/etc:

$ sudo apt install libimobiledevice6 ideviceinstaller

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

$ sudo apt install libimobiledevice-utils libusbmuxd-tools

Modify Flutter

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)

$ cd flutter
$ git apply ios.diff

Then rebuild the Flutter tool:

Linux:

$ bin/cache/dart-sdk/bin/dart --snapshot=./bin/cache/flutter_tools.snapshot --packages=./packages/flutter_tools/.packages ./packages/flutter_tools/bin/flutter_tools.dart

Windows:

bin\cache\dart-sdk\bin\dart --snapshot=.\bin\cache\flutter_tools.snapshot --packages=.\packages\flutter_tools\.packages .\packages\flutter_tools\bin\flutter_tools.dart

Preparing your project(s)

Running and debugging

Using an IDE (VS Code):

  • 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!

Using the command-line:

  • Open the app, and wait for Flutter to sync files.
  • You can now hot reload by pressing r and hot restart by pressing R!

Credits


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

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

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