The Complete Guide to Publishing a Flutter App on the Apple App Store
A detailed guide for first-time app publishers. Even if you've never deployed an app before, that's fine. Follow this guide from start to finish and your Flutter app will be live on the App Store.
1. Enrolling in the Apple Developer Program
Why Is This Required?
Apple requires anyone who wants to publish apps on the App Store to enroll in the Apple Developer Program. This is Apple's process for verifying developer identity and maintaining app quality and security. Without enrollment, you simply cannot publish to the App Store.
Cost
- $99 USD per year — must be renewed annually.
- If you don't renew, your apps will be removed from the App Store.
Enrollment Steps
Step 1: Prepare an Apple ID
If you already have an Apple ID, you can use it. If not, create one at the Apple ID creation page.
Note: Some developers keep separate Apple IDs for personal and development use, but for your first time, using your existing Apple ID is perfectly fine.
Step 2: Go to the Apple Developer Website
Visit Apple Developer Programs and click the "Enroll" button.
Step 3: Identity Verification (Two-Factor Authentication Required)
For security, Apple only allows Apple IDs with Two-Factor Authentication (2FA) enabled to enroll in the Developer Program. If you haven't set this up yet:
- On your iPhone or Mac, go to Settings > [Your Name] > Sign-In & Security > Two-Factor Authentication.
- Turn on two-factor authentication.
- Register a trusted phone number.
Step 4: Choose Individual or Organization
- Individual: For solo developers. Your name will appear as the "seller" in the App Store.
- Organization: For companies or groups. Requires a D-U-N-S number.
If you're an independent developer, choose "Individual." Registering as an organization requires business registration documents and a D-U-N-S number, and the review takes longer.
Step 5: Identity Confirmation
For individual registration, Apple may ask you to verify your identity. Recently, this is often done through the Apple Developer app on iPhone or iPad:
- Install the "Apple Developer" app from the App Store.
- Sign in with your Apple ID.
- Follow the in-app registration flow, which may include photographing your ID.
Note: Identity verification typically takes 1–3 days, though it can complete the same day. Weekends and holidays may take longer.
Step 6: Payment
Once identity verification is complete, pay the $99 fee using a payment method linked to your Apple ID.
Step 7: Confirm Account Activation
After payment, account activation can take up to 48 hours. Once active, you'll be able to log in to App Store Connect.
Tip: To check if your Developer Program enrollment is complete, visit Apple Developer Account and look at the "Membership" section. If it shows "Active," you're in.
2. Registering Your App in App Store Connect
Why Is This Required?
App Store Connect is Apple's web portal for managing apps. Everything happens here: entering app information, managing builds, submitting for review, and checking revenue. Before uploading a build, you need to "register" your app here first.
Understanding the Bundle Identifier
The Bundle ID is your app's unique identifier. It must be globally unique and cannot be changed once set.
- Format: Reverse domain notation (e.g.,
com.yourcompany.yourapp) - Example:
com.example.justqr
Warning: The Bundle ID can never be changed after registration. Choose carefully. The convention is to use your domain name in reverse. If you don't have a domain,
com.yourname.appnameworks fine.
App Registration Steps
Step 1: Access App Store Connect
Log in to App Store Connect.
Step 2: Create a New App
- Click "Apps" in the left menu.
- Click the "+" button > "New App" in the top left.
Step 3: Enter Basic App Information
Fill in the following:
| Field | Description |
|---|---|
| Platform | Select iOS |
| Name | The app name displayed in the App Store (max 30 characters). Must be unique |
| Primary language | Select your language (e.g., English) |
| Bundle ID | The Bundle ID you registered (must be registered in the Developer portal first to appear in the list) |
| SKU | An internal management ID. Any alphanumeric string works (e.g., justqr_v1) |
| User access | Select "Full Access" |
Tip: Your app name has a significant impact on App Store search. Choose a name that reflects your app's core function — avoid overly generic names or ones that overlap with existing apps.
Step 4: Register the Bundle ID in the Developer Portal First
To select a Bundle ID in App Store Connect, you must register it in the Apple Developer portal first:
- Go to Apple Developer - Identifiers.
- Click the "+" button.
- Select "App IDs" and click Continue.
- Select "App" as the type.
- Enter a description for your app.
- Under Bundle ID, select "Explicit" and enter your Bundle ID.
- Check any necessary Capabilities (e.g., Push Notifications).
- Click Continue > Register.
Your Bundle ID will now appear in the dropdown when creating an app in App Store Connect.
3. Configuring Signing in Xcode
Why Is Code Signing Required?
iOS apps must be code signed to run on a device. Code signing certifies that "this app was made by a verified developer and hasn't been tampered with." Without signing, neither installation nor App Store upload is possible.
Key Concepts
Before setting up signing, understanding a few concepts will make things much easier:
- Certificate: A digital certificate proving "I am an Apple-recognized developer." There are two kinds: Development and Distribution.
- Provisioning Profile: A file that bundles together a certificate, an App ID, and (for development) a list of test devices. Think of it as a permit that says "this developer can run this app on this device."
- Team: The developer (or organization) enrolled in the Developer Program.
Setting Up Automatic Signing in Xcode (Recommended)
The iOS portion of a Flutter project is configured through Xcode. With automatic signing, Xcode handles certificates and Provisioning Profiles for you.
Step 1: Open the iOS Project in Xcode
From your project root in the terminal:
open ios/Runner.xcworkspace
Warning: Open
Runner.xcworkspace, NOTRunner.xcodeproj. The.xcworkspacefile ensures CocoaPods and other dependencies load correctly.
Step 2: Navigate to Project Settings
- In the Xcode file navigator on the left, click the "Runner" project (the blue icon at the top).
- Select "Runner" under the TARGETS section.
- Click the "Signing & Capabilities" tab.
Step 3: Set Your Team
- Confirm that "Automatically manage signing" is checked.
- In the Team dropdown, select your Apple Developer account.
- If it's not listed: Go to Xcode menu > Settings (or Preferences) > Accounts and add your Apple ID.
- Once a Team is selected, Xcode will automatically generate or download the required Provisioning Profile and certificate.
Step 4: Verify the Bundle Identifier
In the "General" tab, confirm that the Bundle Identifier matches exactly the Bundle ID you registered in App Store Connect.
To change the Bundle ID in a Flutter project, edit this file:
ios/Runner.xcodeproj/project.pbxproj
You can also edit it directly in Xcode's General tab.
Step 5: Verify Distribution Signing Settings
Check that the Release configuration is set correctly:
- Click the "Build Settings" tab.
- Type "signing" in the search bar.
- Confirm that Code Signing Identity is set to "Apple Distribution" for the Release configuration.
- With automatic signing enabled, this is usually configured automatically — no manual adjustment needed.
Tip: Keeping "Automatically manage signing" checked lets Xcode resolve most signing issues on its own. Highly recommended for beginners.
Note: If you see signing-related errors, try the following:
- Remove and re-add your Apple ID under Xcode > Settings > Accounts
- Fully quit and restart Xcode
- Delete the
ios/Podsfolder andios/Podfile.lock, then runpod installagain
4. Building a Release IPA with flutter build ipa
Why Do We Need a Release Build?
During development, you run the app in Debug mode. Debug mode includes developer tools like slow animation overlays, which makes the app slower and larger. When submitting to the App Store, you need an optimized Release build with all of that stripped out.
Pre-Build Checklist
Check the following before building:
1. Verify App Version and Build Number
Check the version in pubspec.yaml:
version: 1.0.0+1
1.0.0is the version name — what users see.+1is the build number — must always be higher than the previous submission, even for the same version name.
Warning: A build number that has been uploaded once cannot be reused. Increment it with every new build. Example:
1.0.0+1→1.0.0+2→1.0.1+3
2. Verify App Icon
A missing app icon will result in rejection. Check that all required icon sizes are present in ios/Runner/Assets.xcassets/AppIcon.appiconset/. The flutter_launcher_icons package makes this easy.
3. Verify Minimum iOS Deployment Target
Check the minimum iOS version at the top of ios/Podfile:
platform :ios, '13.0'
Setting this too low (e.g., 11.0) can cause compatibility issues with newer libraries. Setting it too high reduces the range of supported devices. 13.0 or higher is recommended at this point.
Running the Build
Run the following command in your terminal:
flutter build ipa --release
This command:
- Compiles your Flutter code into native iOS code.
- Optimizes for Release mode (tree shaking, AOT compilation, etc.).
- Generates an
.ipafile — the file you'll upload to the App Store.
On success, you'll see:
Built IPA to build/ios/ipa/YourApp.ipa
Specifying a Custom Export Method
By default, flutter build ipa builds for App Store distribution. If you need fine-grained control over export options, you can use an export options plist:
flutter build ipa --release --export-options-plist=ios/ExportOptions.plist
For a first-time build, the default command is all you need.
Troubleshooting Build Errors
Error: "No signing certificate"
# Double-check signing settings in Xcode.
# Or open Keychain Access, delete any expired certificates, then regenerate in Xcode.
Error: "Module not found" (CocoaPods related)
cd ios
pod deintegrate
pod install --repo-update
cd ..
flutter clean
flutter build ipa --release
Error: "Minimum deployment target" related
# Raise the minimum iOS version in ios/Podfile
# platform :ios, '13.0' or higher
5. Uploading the Build
Why Upload?
The .ipa file needs to be uploaded to Apple's servers before you can submit it for review in App Store Connect. There are two main ways to do this.
Method 1: Upload via Xcode (Distribute App)
This is the most intuitive method if Xcode is installed.
Steps
-
Open
ios/Runner.xcworkspacein Xcode. -
From the top menu, select Product > Archive.
- If this menu item is grayed out, change the build target to "Any iOS Device" (not a simulator).
-
When archiving is complete, the Organizer window opens automatically.
- If it doesn't, open it manually via Window > Organizer.
-
Select the archive you just created and click "Distribute App".
-
Choose "App Store Connect" as the distribution method.
-
Select "Upload" (not Export).
-
Review the options:
- "Include bitcode" may no longer appear in recent Xcode versions.
- "Upload your app's symbols" is recommended (needed for crash report analysis).
-
Select "Automatically manage signing" for signing options.
-
Click "Upload" and wait for it to complete.
"Upload Successful" will appear when done.
Note: If you already have an
.ipafile fromflutter build ipa, using Transporter below is simpler than going through Xcode's Archive flow again.
Method 2: Upload via the Transporter App (Recommended)
Transporter is a free app from Apple that lets you upload .ipa files with simple drag and drop.
Steps
-
Search for "Transporter" in the Mac App Store and install it.
-
Launch Transporter and sign in with your Apple ID.
-
Locate the
.ipafile generated byflutter build ipa:
ls build/ios/ipa/
-
Drag and drop the
.ipafile into the Transporter window. -
Transporter will verify the file. If there are no issues, click "Deliver".
-
Wait for the upload to complete.
Tip: Transporter shows upload progress and provides clear error messages when something goes wrong — often clearer than Xcode's messages. Recommended for first-timers.
Method 3: Command-Line Upload (xcrun altool / xcrun notarytool)
You can also upload directly from the terminal:
xcrun altool --upload-app --type ios \
--file build/ios/ipa/YourApp.ipa \
--apiKey YOUR_API_KEY \
--apiIssuer YOUR_ISSUER_ID
This method is mainly used in CI/CD pipelines and isn't recommended for your first deployment.
What Happens After Upload
After the upload completes, Apple's servers run automatic validation (Processing). This typically takes 5–30 minutes. You'll receive an email with the result when it's done.
- Success: The build will appear in the "TestFlight" tab in App Store Connect.
- Failure: A specific error reason will be sent by email.
Note: It's completely normal not to see the build in App Store Connect immediately after uploading. Wait for Processing to finish.
6. Filling In App Information in App Store Connect
Why Does App Information Matter?
Everything users see in the App Store — the app name, description, screenshots, and more — is entered here. This information isn't just for display; it's also subject to review. Inaccurate or inappropriate information is a common reason for rejection.
Field-by-Field Guide
When you open your app in App Store Connect, you'll see multiple sections. Here's a walkthrough of each.
1) App Name and Subtitle
- App name: Max 30 characters. Used when your app is searched in the App Store.
- Subtitle: Max 30 characters. Displayed in small text below the app name. Use it to summarize the core function in one line.
2) Description
- Max 4,000 characters.
- Clearly explain what the app does and why it's useful.
- The first three lines matter most — they're visible in the preview.
- Naturally including keywords helps with search visibility.
3) Keywords
- Max 100 characters, comma-separated.
- Enter words users are likely to search for.
- No need to repeat words already in your app name.
4) Screenshots
Screenshots are critical for review and are required. There are specific size requirements:
| Device | Required | Resolution |
|---|---|---|
| iPhone 6.9-inch (iPhone 16 Pro Max, etc.) | Required | 1320 × 2868 px |
| iPhone 6.7-inch (iPhone 15 Pro Max, etc.) | Required | 1290 × 2796 px |
| iPhone 6.5-inch (iPhone 11 Pro Max, etc.) | Optional | 1242 × 2688 px |
| iPhone 5.5-inch (iPhone 8 Plus, etc.) | Optional | 1242 × 2208 px |
| iPad Pro 13-inch | Required (if iPad app) | 2048 × 2732 px |
Note: Screenshot requirements can change with Apple policy updates — always check App Store Connect's current guidance. Recently, only the 6.9-inch and 6.7-inch sizes have been required.
Screenshot tips:
- You can register a minimum of 3 and a maximum of 10 screenshots.
- Take screenshots in the simulator using
Cmd + S(in the Xcode simulator). - Overlaying descriptive text on screenshots improves conversion rates. Use Figma or Canva.
- Screenshots must reflect the actual app. Using unrelated images will result in rejection.
5) App Preview Video (Optional)
You can upload a 15–30 second video showing the app in use. Not required, but effective for showcasing core functionality.
6) Category
Select a primary and optional secondary category:
- Primary category: Choose the one that best matches your app's core function (e.g., Utilities, Productivity)
- Secondary category: Optional, but worth setting for additional discoverability.
7) Privacy Policy URL
This is required. Apple requires a privacy policy URL for all apps.
- Must be a hosted web page with a valid URL.
- Even if your app collects no personal data, you still need a page that explicitly states that.
- You can host it for free on GitHub Pages, Notion, or a personal blog.
Warning: Without a privacy policy, you cannot even submit for review. Prepare this in advance.
8) Age Rating
Apple's questionnaire automatically determines your age rating based on your answers:
- Does the app contain violent content?
- Does the app contain adult content?
- Does the app include gambling elements?
- Does the app include user-generated content?
Most utility apps receive a "4+" rating. Answer honestly — false answers can lead to rejection.
9) Pricing and Availability
- Price: Choose free or paid. If paid, select a price tier.
- Availability: Select the countries and regions where your app will be available. All countries are selected by default.
10) App Review Information
- Contact information: Your name, email, and phone number for Apple to reach you during review.
- Sign-in information: If your app requires login, you must provide test account credentials for the review team.
- Notes: Any notes you want to pass along to the review team — for example, instructions for accessing a specific feature.
7. TestFlight Beta Testing
Why Use TestFlight?
TestFlight is Apple's official beta testing tool. It lets you distribute your app to a small group of testers before the official App Store release to catch bugs and gather feedback.
TestFlight testing is not required, but strongly recommended for these reasons:
- You can catch issues on real devices before submitting for review.
- You can test across a range of iPhone and iPad models.
- If you get rejected, fixing and resubmitting takes days — catching problems early saves time.
Internal vs External Testing
| Internal Testing | External Testing | |
|---|---|---|
| Audience | Team members (max 100) | General users (max 10,000) |
| Apple review | Not required | Brief beta review required |
| Invitation method | Email or public link | |
| Time to deploy | Immediately | Beta review takes 1–2 days |
For an independent developer, internal testing is usually sufficient.
TestFlight Workflow
Step 1: Upload a Build
If you've already uploaded a build in Section 5, you'll see it in App Store Connect under the TestFlight tab.
Step 2: Answer the Export Compliance Question
Once a build is processed, you'll see a "Missing Export Compliance" warning. This relates to US export regulations.
- Most apps fall under: "No, this app uses only standard encryption."
- Apps that use HTTPS-only communication qualify for exemption.
You need to answer this question for TestFlight distribution to be activated.
Tip: To avoid answering this every time, add the following to
ios/Runner/Info.plist:
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
This declares that your app doesn't use encryption that requires export compliance documentation. For typical apps using only HTTPS, setting this to false is appropriate.
Step 3: Add Testers (Internal Testing)
- In the TestFlight tab, go to the "Internal Testing" section.
- Click the "+" button to create a new group.
- Add testers by their Apple ID email.
- An invitation email will be sent to each tester.
Step 4: Testers Install the App
- Testers install the "TestFlight" app from the App Store.
- Tapping the link in the invitation email allows them to install your app through TestFlight.
Step 5: Review Feedback
Testers can submit feedback with screenshots from within TestFlight. You can view this feedback in App Store Connect.
8. Submitting for Review
Review Submission Steps
Once all information is entered and your build is ready, submit for review.
Step 1: Select a Build
In App Store Connect, open your app, then open the version page:
- Click the "+" button next to the "Build" section.
- Select one of your uploaded builds.
Step 2: Confirm All Required Information
If you see "Complete the following items before submitting this version" at the top of the page, complete each listed item.
Step 3: Submit for Review
Once everything is complete, the "Submit for Review" button becomes active. Click it to begin the review.
Review Timeline
- Results typically come within 24–48 hours.
- It can be as fast as a few hours.
- Reviews slow down around the end of the year (especially late December).
Review Status Meanings
| Status | Meaning |
|---|---|
| Waiting for Review | In the review queue |
| In Review | Review in progress |
| Pending Developer Release | Approved — developer must click the release button |
| Ready for Distribution | Approved and live |
| Rejected | Submission rejected |
Common Rejection Reasons and How to Handle Them
Apple's review is more thorough than you might expect. Get ahead of these common issues.
1) Bugs or Crashes
Reason: The app crashes during review or core features don't work.
Fix: Test thoroughly across multiple devices and iOS versions. TestFlight is useful here.
2) Incomplete App Information
Reason: Screenshots don't match the actual app, descriptions are inaccurate, or the privacy policy URL is broken.
Fix: Use current screenshots of the latest app version, and verify that your privacy policy URL is accessible.
3) Login-Required App Without Test Credentials
Reason: The app requires login but no test account was provided.
Fix: Always fill in test account credentials (username/password) in the "App Review Information" section of App Store Connect.
4) Minimum Functionality Requirement (Guideline 4.2)
Reason: The app is too simple or is just a thin wrapper around a website.
Fix: The app must make meaningful use of native functionality and provide value beyond simply displaying web pages.
5) Privacy-Related Issues (Guideline 5.1)
Reason: Insufficient explanation of personal data collection, or missing App Tracking Transparency prompt.
Fix: If you collect personal data, explain why clearly. If you use tracking features, implement the ATT framework.
6) Payment-Related Issues (Guideline 3.1)
Reason: The app bypasses Apple's in-app purchase system for digital content.
Fix: Digital content purchases must use Apple's in-app purchase system (StoreKit).
What to Do When Rejected
- Read the rejection reason carefully: Find the specific reason in the "Resolution Center" in App Store Connect.
- Make the necessary fixes: Correct the app or metadata based on the reason.
- You can ask questions or appeal: Send a message to Apple's review team from the Resolution Center.
- Resubmit after fixing: Upload a new build if code changes were needed, or resubmit with the existing build if only metadata was changed.
Tip: Rejection is common. Don't be discouraged — understand the reason, fix it, and most submissions pass on the next attempt.
9. Common Mistakes / FAQ
Common Mistakes
Mistake 1: Forgetting to increment the build number
Symptom: "Redundant Binary Upload" or "Build number already used" error
Fix: In pubspec.yaml, increment the number after + in version: 1.0.0+1. Build numbers cannot be reused.
Mistake 2: Missing app icon
Symptom: Receiving a "Missing App Icon" warning email after upload
Fix: Prepare all required icon sizes, including 1024×1024. The flutter_launcher_icons package generates them all automatically.
# Add to pubspec.yaml
dev_dependencies:
flutter_launcher_icons: ^0.14.0
flutter_launcher_icons:
android: true
ios: true
image_path: "assets/icon/app_icon.png"
dart run flutter_launcher_icons
Mistake 3: Missing or inaccessible privacy policy URL
Symptom: "Submit for Review" button is inactive, or submission is rejected
Fix: Host a privacy policy page at a valid, accessible URL. GitHub Pages is a free option.
Mistake 4: Incorrect screenshot dimensions
Symptom: "Invalid screenshot" error
Fix: Refer to the screenshot dimensions table above. Taking screenshots in the simulator with the correct device model selected produces the right dimensions automatically.
Mistake 5: Submitting without testing the Release build
Symptom: Works fine in Debug mode but crashes in the Release build
Fix: Release builds behave differently from Debug builds (tree shaking, AOT compilation, etc.). Always test the Release build on a real device or through TestFlight before submitting.
Mistake 6: Missing permission usage descriptions in Info.plist
Symptom: Rejected because camera, photo library, or other permissions are used without a usage description
Fix: Add usage descriptions for each permission in ios/Runner/Info.plist:
<!-- Camera usage -->
<key>NSCameraUsageDescription</key>
<string>Camera access is required to scan QR codes.</string>
<!-- Photo library access -->
<key>NSPhotoLibraryUsageDescription</key>
<string>Photo library access is required to save QR code images.</string>
<!-- Photo library add-only access -->
<key>NSPhotoLibraryAddUsageDescription</key>
<string>Permission is needed to save generated QR codes to your photo album.</string>
Warning: Permission descriptions must include a specific, user-understandable reason. Vague explanations like "Required by this app" are grounds for rejection.
FAQ
Q: Do I really have to pay $99 every year?
A: Yes, annual renewal is required. If you don't renew, your apps are removed from the App Store and you can't upload new apps. Users who already downloaded your app can continue to use it, but they won't receive updates.
Q: Can I publish an iOS app without a Mac?
A: Currently, a Mac is required. Xcode — which is needed for building and signing iOS apps — only runs on macOS. As a workaround, cloud Mac services (e.g., MacStadium, or GitHub Actions with a macOS runner) exist, but for your first deployment, using a physical Mac is strongly recommended.
Q: How long does app review take?
A: Usually 24–48 hours, but it can be as quick as a few hours or as long as a week or more. Reviews slow down significantly during the holiday season at the end of the year.
Q: If I'm rejected, do I have to start over?
A: No. After fixing the issue, you can resubmit for review from the same app version. Only upload a new build if code changes were required.
Q: Do I have to pay $99 even for a free app?
A: Yes. The Developer Program fee is the same regardless of whether your app is free or paid. It's an annual membership fee to maintain your developer status, unrelated to app sales.
Q: Does every update go through review?
A: Yes, all updates require review. However, updates are typically processed faster than initial submissions.
Q: Is TestFlight testing mandatory?
A: No. But testing the Release build on a real device before submission is very important. TestFlight is the easiest way to do that.
Q: If it works in the simulator, will it work on a real device?
A: Not necessarily. There are meaningful differences between the simulator and real devices — the camera, GPS, and sensors can't be tested in the simulator, and performance characteristics differ. Always test on a real device when possible.
Q: Will my app go live on the App Store immediately after approval?
A: When submitting, you can choose "Automatic release" or "Manual release." With automatic release, your app goes live as soon as review passes. With manual release, you need to click a "Release" button yourself after approval. Choose manual release if you want to time the launch to a specific date.
Full Process Summary
Here's the entire App Store publishing process at a glance:
1. Enroll in Apple Developer Program ($99/year)
|
2. Register an App ID (Bundle ID) in the Apple Developer portal
|
3. Create a new app in App Store Connect
|
4. Configure signing in Xcode (set Team and verify Bundle ID)
|
5. Build with: flutter build ipa --release
|
6. Upload the .ipa file via Transporter or Xcode
|
7. Fill in app information in App Store Connect
(screenshots, description, privacy policy, etc.)
|
8. (Optional) Beta test with TestFlight
|
9. Submit for review
|
10. Review approved → Live on the App Store!
It looks complex at first, but once you've done it, it gets much easier. For updates in particular, you only need to repeat steps 4–6 and 9, which saves a lot of time.
Good luck with your first app launch!