RORK LABJP
MAX — Rork Max generates native Swift for every Apple platform, from iPhone to Vision ProNATIVE — It reaches native capabilities like AR/LiDAR, Metal 3D, Dynamic Island, Live Activities, and HealthKitPUBLISH — Publish to the App Store in two clicks; Rork Max is $200/monthEXPO — Standard Rork builds iOS and Android together via React Native (Expo) and is free to startPROMPT — Describe your app idea in plain English and Rork generates deployable, store-ready codePRICE — Standard Rork's paid plans start at $25/month: build with it first, then consider Max for native featuresMAX — Rork Max generates native Swift for every Apple platform, from iPhone to Vision ProNATIVE — It reaches native capabilities like AR/LiDAR, Metal 3D, Dynamic Island, Live Activities, and HealthKitPUBLISH — Publish to the App Store in two clicks; Rork Max is $200/monthEXPO — Standard Rork builds iOS and Android together via React Native (Expo) and is free to startPROMPT — Describe your app idea in plain English and Rork generates deployable, store-ready codePRICE — Standard Rork's paid plans start at $25/month: build with it first, then consider Max for native features
Articles/Dev Tools
Dev Tools/2026-06-21Intermediate

Reclaiming the Pre-Submit Checks You Lose When Publishing Without Xcode

Rork Max's two-click publishing skips the Xcode Organizer, making it easy to miss usage strings, version bumps, and Bundle IDs. Here is a quick pre-submit self-audit you can run yourself, with how to read the generated files.

Rork433Rork Max179Info.plist5Indie Development15Release

The first time I used Rork Max's two-click publishing, the convenience came with a slight unease. The step where I used to open the archive in Xcode's Organizer and eyeball the contents before submitting was gone entirely. Submission got faster, but with it vanished my chance to confirm "what I just sent."

Most of those skipped checks existed to prevent oversights rather than bugs. A single missing usage string, a forgotten version bump, a Bundle ID left over from a previous app. In the Xcode era, these small drifts would catch my eye before submission. Two-click does not pass through there, so you need to reclaim the self-audit as your own step. This time I will lay out a short pre-submit self-audit, along with where to look in the generated artifacts.

Why noticing after submission costs more

What makes oversights dangerous is that the build succeeds. It compiles, the two-click submit completes, and on the surface nothing looks wrong. It snags hours later at review, or worst case in a user report after release. The longer the distance from submission to discovery, the more the fix round-trip swells.

In my sense, spending a few minutes on a pre-submit self-audit pays for itself if it prevents even one review-rejection wait. Missing usage strings in particular are easy to fail review on, and they are exactly the kind of mistake you can detect mechanically before submitting. The trick is refusing to begrudge the last few minutes.

Are all the usage strings present

iOS requires a string explaining why you use a device capability—camera, location, and so on (a Purpose String). If the config Rork generates lacks this string while the feature is implemented, the app crashes at runtime or gets flagged at review.

Before submitting, check that the features you use and their usage strings line up one to one. For Expo-based Rork, check the config file; for Swift-native Rork Max, check the Info.plist.

# List usage-string keys from the Rork (Expo) generated config
# Look at both app.json and app.config.* to be safe
grep -REo 'NS[A-Za-z]+UsageDescription' app.json app.config.* ios/ 2>/dev/null | sort -u
 
# For Rork Max (Swift), read the Info.plist directly
plutil -p ios/*/Info.plist 2>/dev/null | grep -i "UsageDescription"

Match the listed keys against the capabilities your app actually uses. For example, if you save photos but NSPhotoLibraryAddUsageDescription is absent, that is a hole. I make a habit of adding the matching string whenever I add a feature, yet I still print this list once right before release and look at it. Implementation and config live in separate files, so one moving without the other is bound to happen.

Misplaced version and Bundle ID

What grows when you ship your second app and beyond is leaving the version unchanged and reusing the Bundle ID. With Xcode's Organizer the version showed large on the submit screen, so you noticed; with two-click it is easy to miss in the flow.

There are two things to check: the display version (the number users see) and the build number (the internal number you increment within a version). App Store Connect will not accept a resubmission with the same build number.

# Check the display version and build number at once
# Expo: version and ios.buildNumber in app.json
grep -E '"version"|"buildNumber"' app.json
 
# Swift native: CFBundleShortVersionString and CFBundleVersion in Info.plist
plutil -p ios/*/Info.plist 2>/dev/null | grep -E "CFBundleShortVersionString|CFBundleVersion|CFBundleIdentifier"

The Bundle ID is where the previous app's value tends to linger when you base a project on a template or a past project. As an indie developer, when I built similarly structured apps back to back, the Bundle ID stayed as the previous one and the submission stalled against the App Store Connect registration. Before submitting, always look once to confirm this is a value unique to this app.

Fold the self-audit into one command

Typing these by hand every time means you skip them exactly when you are busy. I fold the pre-submit checks into a single script and always run it before pressing publish.

#!/usr/bin/env bash
# presubmit-check.sh — mechanically check the minimum before publishing
set -euo pipefail
 
echo "== Usage strings =="
grep -REo 'NS[A-Za-z]+UsageDescription' app.json app.config.* ios/ 2>/dev/null | sort -u \
  || echo "(config not found; check the path)"
 
echo "== Version / Bundle ID =="
grep -E '"version"|"buildNumber"' app.json 2>/dev/null || true
plutil -p ios/*/Info.plist 2>/dev/null \
  | grep -E "CFBundleShortVersionString|CFBundleVersion|CFBundleIdentifier" || true
 
echo "== Checklist =="
echo "[ ] usage strings present for every capability used"
echo "[ ] display version bumped from last time"
echo "[ ] Bundle ID is unique to this app"

The benefit of a script is that the audit drops out of the "do it / skip it" decision. Once it is part of the publish flow, you do not miss it even in a hurry. Even running several apps in parallel at Dolice Labs, I share this one script across all of them, so audit quality stays consistent even on a new app.

What two-click publishing removed is the effort, not the need to verify. Reclaim the eyeballing you lost as a mechanical self-audit on your side. Before your next Rork Max release, try printing the usage-string list once. Just knowing there are no holes should lighten the hand that presses publish.

Share

Thank You for Reading

Rork Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

Dev Tools2026-06-17
Spotting the 30% of Bugs Rork Can't Fix Itself — A Hand-Fix Workflow Built Around Export
Rork resolves roughly 70% of the bugs it hits on its own; the remaining 30% needs your hands. Here is the criteria I use to decide whether to keep re-prompting or export and fix it myself, plus working code for the fixes.
Dev Tools2026-06-17
Why Your Rork Max Native Swift Widget Freezes After Day One — Designing the TimelineProvider Refresh Budget
Native Swift home screen widgets generated by Rork Max stop rotating after the first day unless you understand the TimelineProvider refresh budget. Here is how reloadPolicy, App Groups, and deep links fit together in a real app.
Dev Tools2026-06-15
Drawing the Line Between Rork Max's Swift Output and the Expo Build
Rork Max now generates native Swift, while the standard Rork keeps producing Expo (React Native) apps. Here is how to split responsibilities between the two engines inside a single app business, viewed from real maintenance cost.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →