Skip to content

Publishing to the App Store

iPhone and iPad. Harder than Android, stricter review, and it needs a Mac.

Apple changes this process regularly. Where these steps differ from what you see in App Store Connect, trust Apple.

Read this before planning an iOS release

The iOS side of these apps is not finished. Some things must be fixed in the code before an iOS build can be submitted at all — and two of them cause the app to crash on the user's phone, not merely fail review.

AppiOS stateWhat is missing
Staff appClosest to readyBundle identifier still needs setting
Parent appNeeds fixingCamera and microphone permission text missing
Driver appNot readyNo permission text at all, and no background location capability

Missing permission text crashes the app on iOS

Android asks for a permission and carries on if refused. iOS terminates the app immediately if it requests a capability without a matching explanation string in Info.plist.

The parent app requests camera and microphone on Android, but its Info.plist has no NSCameraUsageDescription and no NSMicrophoneUsageDescription. On an iPhone, the moment a parent opens a feature that uses the camera or the microphone, the app closes.

This must be fixed before any iOS release.

The driver app cannot work on iOS as it stands

Its Info.plist has no location permission text, so it will crash the first time it asks for location. It also has no background location capability (UIBackgroundModes), which is the app's entire purpose — iOS suspends it the moment the driver's screen turns off.

Treat iOS driver support as development work, not a publishing task.

Fix these first

1. Bundle identifiers. They are still Flutter's placeholder, com.example.schoolErpParentApp. Apple rejects com.example.*. Set a real one — ideally matching the Android ID. See building.

2. Display name. It currently reads "School Erp Parent App" — machine-generated, with "Erp" instead of "ERP".

3. Permission text. Every capability an app uses needs a plain-English reason in Info.plist. Apple shows your sentence to the user, and reviewers read it:

xml
<key>NSCameraUsageDescription</key>
<string>Used to take a photo for your child's profile and to join live classes.</string>

<key>NSMicrophoneUsageDescription</key>
<string>Used so your child can speak during a live class.</string>

Write what the user gains. "This app needs camera access" gets rejected; "used to take a photo for your child's profile" does not.

What you need

  • A Mac with Xcode. There is no way around this
  • An Apple Developer Program membership — $99 per year, and access stops when it lapses
  • The .ipa from building
  • A privacy policy at a public address
  • Screenshots at Apple's exact required sizes

Step 1: Create the app in App Store Connect

Register your bundle identifier, then create the app entry: name, primary language, bundle ID, and an SKU (any internal code).

The name must be unique across the entire App Store. Common names are long gone — have alternatives ready.

Step 2: Upload a build

From a Mac:

bash
flutter build ipa --dart-define=API_ORIGIN=https://erp.stmarys.edu.in

Upload the result with Xcode or Transporter. It takes a few minutes to appear in App Store Connect after processing.

Step 3: App Privacy

Apple's equivalent of the data-safety form. Declare, per app:

AppDeclare
Parent appLocation · Camera · Microphone · Contact info · Identifiers
Staff appLocation · Contact info · Identifiers
Driver appPrecise location, including background · Identifiers

Answer honestly. Apple cross-checks against what the app actually requests, and a mismatch means removal later rather than rejection now.

Step 4: Push notifications need one extra key

For the parent app, notifications on iPhone need an APNs authentication key from your Apple Developer account, uploaded into Firebase under Project Settings → Cloud Messaging.

Without it Android notifications work perfectly and iPhone users get nothing — see push notifications.

Step 5: TestFlight before submitting

Send the build to TestFlight and install it on a real iPhone. Confirm it opens on your server, logs in, loads photos, and does not crash on any screen that uses the camera or location.

TestFlight review is much lighter than App Store review, so this is the cheap place to find problems.

Step 6: Submit

Provide the store listing, screenshots, and — critically — reviewer notes.

Apple will reject an app it cannot log into

Every screen behind the login is invisible to the reviewer. Give a working test account with sample data in the review notes, and say which app it is for.

This is the most common rejection for school software, on both stores.

Review usually takes a day or two. Rejections come with a reason and you resubmit — there is no penalty for being rejected, only lost time.

Why iOS apps get rejected

ReasonFix
Crashes on launch or on a permission promptMissing Info.plist permission text
"Guideline 2.1 — need a demo account"Put test credentials in reviewer notes
Vague permission wordingSay what the user gains, not what the app needs
App is "just a website in a wrapper"Emphasise native features: notifications, biometric login, camera
Background location not justifiedExplain the bus-tracking feature in the notes
Privacy policy link brokenPublish it at a permanent address

A reasonable plan

If iOS is not urgent:

  1. Launch on Google Play first — cheaper, faster, and most school parents are on Android
  2. Fix the iOS gaps above
  3. Submit the staff app first, since it is closest to ready
  4. Then the parent app, once camera and microphone text is added
  5. Treat the driver app on iOS as a development project of its own