Building an iOS app is hard work, but submitting it to the App Store can feel like a whole different battle. Recently, I went through the process of publishing PaisaFlow, a privacy-focused expense tracker tailored for the Indian market.
While the coding part was straightforward, the submission process threw several curveballs—from bundle ID confusion to screenshot automation and encryption compliance.
If you are about to hit that “Submit for Review” button, read this first. Here is a breakdown of the specific issues I faced and how you can avoid them to get your app approved faster.
1. The Bundle ID Trap: App vs. Extensions
One of the first errors I encountered happened during the archiving process. My project includes the main app and a Widget extension. When I tried to upload the build, I saw two different bundle IDs listed (com.paisaflow.app and com.paisaflow.app.widget), which made me worry I had to register the widget separately in App Store Connect.
The Mistake:
I initially tried to archive the Widget Extension scheme, thinking I needed to upload it individually.
The Fix:
You only need to list the Main App Bundle ID in App Store Connect.
- In Xcode, ensure your Scheme is set to the main application (e.g.,
BudgetApp), not the WidgetExtension. - When you archive the main app, Xcode automatically embeds the widget extension inside it.
- You do not need to register the widget’s bundle ID separately in the App Store Connect portal.
2. Validating “Privacy-First” Features (Face ID)
PaisaFlow uses Face ID to lock the Credit Card Vault. Even though the code was working perfectly in the simulator, I risked an immediate crash on real devices.
The Issue:
I missed a critical key in the Info.plist. Without this key, the OS terminates your app immediately upon a Face ID request, which is an instant rejection during App Review.
The Fix:
If you use Face ID (via the LocalAuthentication framework), you must add the NSFaceIDUsageDescription key to your Info.plist.
- Key:
NSFaceIDUsageDescription - Value: A clear explanation of why you need it.
- Example: “PaisaFlow uses Face ID to securely unlock your Credit Card Vault.”
3. The Screenshot Struggle: Automation is Key
App Store Connect requires screenshots for multiple device sizes (6.5″ and 6.7″). Taking these manually for every screen, in both Light and Dark modes, is a nightmare.
My Approach:
Instead of manual capture, I set up an automated UI Test in Xcode (XCUITest).
- Dummy Data Seeder: I created a
DummyDataSeeder.swiftthat runs only when a specific launch argument is passed (-UITest_SeedDummyData). This populates the app with realistic data (e.g., “HDFC Infinia” cards, “Swiggy” transactions) so the screenshots don’t look empty. - Keyboard Issues: A common mistake is taking screenshots with the keyboard covering half the UI. In my tests, I added code to explicitly dismiss the keyboard before the test snapped the picture.
- Light Mode Enforcement: I realized halfway through that my simulator was stuck in Dark Mode. I added a flag to force
ThemeManager.shared.currentTheme = .lightduring tests to ensure consistent marketing images.
4. Export Compliance & Encryption
When submitting, Apple asks a scary question: “Does your app use encryption?”
The Reality:
PaisaFlow uses SwiftData, secure Keychain storage, and HTTPS. Technically, this is encryption.
The Answer:
- Question: Does your app use encryption? Yes.
- Exemption: Does your app qualify for exemptions? Yes.
- Reason: Select “Standard encryption algorithms instead of, or in addition to, using or accessing the encryption within Apple’s operating system.”
Because we rely on standard iOS frameworks (Keychain, HTTPS) rather than custom proprietary encryption, we are exempt from submitting heavy export documentation to the US government.
5. Privacy Policy & Support URL (The “No Website” Problem)
You cannot submit an app without a Privacy Policy URL and a Support URL. Since PaisaFlow is an offline-only app, I didn’t have a dedicated website.
The Quick Fix:
You don’t need to buy a domain or build a website just to launch.
- Notion: I created two simple public Notion pages—one for Privacy Policy and one for Support.
- Content: The policy simply states: “PaisaFlow does not collect, store, or transmit any user data. All financial information is stored locally on your device.”
- Submission: I used these public Notion links in App Store Connect. Apple accepted them without issue.
6. App Privacy Labels (The Questionnaire)
Filling out the “App Privacy” section in App Store Connect can be confusing for local-only apps.
The Confusion:
The questionnaire asks if you collect “Contact Info” or “Financial Info.” Since my app lets users input this data, do I say “Yes”?
The Solution:
- Technically, the data never leaves the device, so you could say “No Data Collected”.
- However, for transparency, I selected “Financial Info” and “Contacts”.
- Crucial Step: For every data type, I answered “No” to:
- Is this data used to track the user?
- Is this data linked to the user’s identity?
Since there is no user account or server, the data is not linked to an identity.
7. The iPad Screenshot Block
When I first tried to submit, App Store Connect demanded iPad screenshots. I hadn’t optimized the UI for iPad yet.
The Fix:
I changed the TARGETED_DEVICE_FAMILY in Xcode Build Settings from 1,2 (iPhone, iPad) to just 1 (iPhone). This removed the requirement for iPad screenshots and allowed me to submit an iPhone-only app.
Conclusion
Submitting an app is less about code and more about configuration and compliance. By automating my screenshots and understanding the nuances of Apple’s privacy questionnaire, I was able to move from a “Processing” build to “Ready for Sale” smoothly.
PaisaFlow is now live. If you are looking for a privacy-first way to track expenses, give it a try!