This post documents my first real interaction with Flutter, Dart, Android Studio, Xcode, and iOS development, starting from cloning an existing Flutter repository all the way to running the app on a real iPhone.
It is intentionally long, explicit, and honest. If you want a clean tutorial, this is not it. If you want a real-world reference you can redo from scratch and debug when things go wrong, this is.
1. Context & Goal
I did not start this project to learn Flutter in isolation.
The real goal was:
- Take an existing Flutter app from GitHub
- Build and run it for Android (already working)
- Compile and run it for iOS
- Eventually share it with testers (students)
Hardware & constraints:
- macOS (Apple Silicon)
- Physical Android device available
- iPhone available
- No Apple Developer paid account initially
2. The Repository
The starting point was an existing Flutter repository:
cd ~/development
git clone https://github.com/Cyfamod-Technologies/school-app-flutter.git
cd school-app-flutter
At this point:
- Android version already ran
- iOS/macOS had never been built on this machine
3. First Run: macOS Desktop (Sanity Check)
Before touching iOS, I verified the Flutter toolchain by running the macOS desktop target:
flutter config --enable-macos-desktop
flutter pub get
flutter run -d macos
What happened
- The app built successfully
- A desktop window opened
- The UI rendered
- A connectivity warning appeared (from app logic, not Flutter)
Key lesson
Running on macOS does not mean iOS. Flutter supports multiple targets from the same codebase, but each platform is a separate build pipeline.
4. Understanding the Tools (Critical Mental Model)
Before continuing, this mental model is essential:
- Flutter: Orchestrator (decides what to build)
- Dart: Application language
- Android Studio: SDK manager & Android tooling
- Android SDK + Java: Required for Android builds
- Xcode: Required for any iOS/macOS build
- CocoaPods: iOS dependency manager
Flutter does not replace Xcode. It uses it.
5. Running on iOS Simulator
Step 1: Launch the simulator
open -a Simulator
Verify Flutter sees it:
flutter devices
Step 2: Run the app on iOS
flutter run -d "iPhone 16e"
Result
- iPhone simulator opened
- App launched
- Login screen worked
Key lesson
The iOS simulator is excellent for learning and UI work, but it does not enforce Apple’s distribution rules.
6. Attempting to Run on a Real iPhone
This is where most first-time iOS developers hit the wall.
Initial error
The app identifier "com.example.myApp" cannot be registered
No profiles for 'com.example.myApp' were found
What this actually means
-
com.example.*is a placeholder bundle identifier - Apple requires globally unique bundle IDs for real devices
Fix: Set a unique Bundle ID
In Xcode:
open ios/Runner.xcworkspace
Then:
- Select Runner → Signing & Capabilities
- Change Bundle Identifier from:
com.example.myApp
to something unique, e.g.:
com.yourname.schoolapp
- Enable Automatically manage signing
- Select your Apple ID as the Team (free account is enough)
7. Installing on a Real iPhone (Debug Build)
With the bundle ID fixed:
- Plug in iPhone via USB
- Unlock and Trust This Computer
- Enable Developer Mode on the iPhone
Run from Xcode:
- Select the iPhone as destination
- Click ▶️ Run
Result
- App installed on the phone
- App launched successfully
Important discovery
When the USB cable was removed, the app stopped opening.
This is expected behavior with free Apple IDs.
8. Debug vs Standalone vs Distribution (The Big Confusion)
Debug build (what free Apple ID gives you)
- Installed via Xcode
- Tied to the Mac
- Often requires USB / debugger
- Expires after ~7 days
Standalone distribution (what users expect)
Requires paid Apple Developer account:
- TestFlight
- App Store
- Ad Hoc distribution
There is no workaround for this. This is an Apple platform rule, not a Flutter issue.
9. Why Running on a Real iPhone Still Mattered
Even though the simulator worked:
- Real device exposed Apple’s signing model
- Validated the project is technically viable
- Proved the app can run on actual hardware
- Surfaced distribution constraints early (good thing)
The simulator is for learning. The real device is for validation.
10. Cleaning Up (Pausing Safely)
Since iOS distribution was blocked by policy (not code):
Safe actions:
- Shut down simulators
- Close Xcode
- Remove the app from the phone
- Disconnect USB
Keep installed:
- Flutter
- Xcode
- Android SDK
- Java
This allows resuming later without reinstallation.
11. Troubleshooting Reference (What Broke & How It Was Fixed)
❌ "dart is damaged and can’t be opened"
Cause: macOS Gatekeeper quarantine
Fix:
xattr -dr com.apple.quarantine ~/development/flutter
❌ Android SDK found but Flutter can’t accept licenses
Cause: Missing cmdline-tools
Fix:
- Install Android command-line tools
- Ensure:
~/Library/Android/sdk/cmdline-tools/latest/bin/sdkmanager
❌ JAVA_HOME invalid / sdkmanager fails
Cause: Homebrew Java not registered with macOS
Fix:
sudo ln -sfn /opt/homebrew/opt/openjdk@17/libexec/openjdk.jdk \
/Library/Java/JavaVirtualMachines/openjdk-17.jdk
❌ iOS app won’t install on real phone
Cause: Placeholder bundle ID
Fix: Set a unique bundle identifier in Xcode
❌ App stops working when USB is unplugged
Cause: Free Apple ID limitations
Fix: Requires paid Apple Developer account for distribution
12. Final Takeaways
- Flutter is powerful, but platform rules still apply
- iOS development is as much about policy as code
- The simulator is enough to learn
- Real devices are required to ship
- Apple’s $99 fee is not optional for real distribution
Most importantly:
Hitting these problems early is a sign you’re doing real development, not toy tutorials.
13. What I Would Do Next (If Starting Again)
- Learn UI & logic on iOS Simulator
- Validate once on a real iPhone
- Decide early whether TestFlight is required
- Budget Apple Developer account if yes
- Ship calmly
This document exists so I can redo this entire process from scratch without guessing, and so other developers can avoid losing days to the same hidden traps.
Top comments (0)