Developing and debugging Flutter apps for iOS without a Mac

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 Travis CI — completely free! (as long as your project is on a public GitHub repository).
Building the app with Travis CI
First, you need to get your project on a public GitHub repository or create a new one and get it on GitHub.
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 adddraft: true
todeploy:
, and it will be published as a draft on GitHub instead.
Installing and running the app
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).
Cydia Impactor is a GUI for working with mobile devices. You can use this tool to install IPA files on iOS.www.cydiaimpactor.com
- Plug in your iOS device to your computer
- Run the Impactor executable
- Click “Xcode”, then “Revoke Certificates”
- Now, drag
app.ipa
to the Cydia Impactor window (or use Device > Install Package…) - 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
Make sure libimobiledevice
and ideviceinstaller
are installed (the latter isn’t used but Flutter will complain if it isn’t present):
On Windows, download libimobiledevice
here, and ideviceinstaller
here. (Click on the latest commit under History, then artifacts, binaries are located under win7-x64\bin
). 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 libimobiledevice ideviceinstaller
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.
Download this file to your flutter
folder (Click on “View raw” and press Ctrl+S). Then apply it: (this was tested with the beta
branch)
$ 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)
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!
Using an IDE (VS Code):
- 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!
Using the command-line:
- Run
flutter attach
. This will wait until the app is launched and start debugging as if we’d usedflutter 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!
Credits
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!