Skip to main content

Flutter iOS Specifics

On iOS, Apple's XNU kernel security policies prohibit dynamic loading and execution of unsigned executable memory pages (MAP_JIT restrictions). To enable instant over-the-air hot updates while maintaining strict App Store compliance, the Shorebird/TkushPatch iOS engine uses a hybrid AOT + interpreter architecture (patch artifact).

1. iOS Architecture: App.framework, diff_base, and patch artifact​

iOS Delivery Lifecycle
  1. Base Release: Compiles the IPA with tk-ota-push release -p ios and submits to TestFlight or App Store.
  2. Patch Creation: Compiles code changes with tk-ota-push patch -p ios.
  3. Activation: Flutter runtime verifies the digital signature and loads updated code on app launch.

What Happens During tk-ota-push release -p ios (Publisher.releaseIos)​

  1. The CLI compiles the application in release mode (flutter build ios --release or flutter build ipa --release if --artifact ipa).
  2. It deterministically resolves the Runner.app bundle (in build/ios/archive/Runner.xcarchive for an IPA or build/ios/iphoneos/ for a standard build) and verifies Frameworks/App.framework/App.
  3. It saves a baseline reference copy in .ota_ios_release_cache/<version>/:
    • Runner.app (intact signed bundle)
    • App (Mach-O baseline AOT binary)
    • supplement/ (linking table files: App.*.link, App.*_table.json, App.dd_resolution.tsv)
  4. It runs aot_tools dump_blobs with analyze_snapshot_arm64 on App to extract diff_base (Dart snapshot blobs), and seals diff_base on the OTA server.

What Happens During tk-ota-push patch -p ios (Publisher.patchIos)​

  1. Anti-Crash Cache Hash Verification: the CLI computes the SHA-256 of .ota_ios_release_cache/<version>/diff_base and compares it to the baseSha256Hash locked on the server. On divergence (iOS HASH MISMATCH), execution aborts immediately to protect against runtime crashes (Segfault) on iOS devices.
  2. Dart Kernel Compilation (app.dill): runs flutter build ios --release --no-codesign.
  3. ELF Snapshot Generation (out.aot): executes gen_snapshot_arm64 with --deterministic --snapshot-kind=app-aot-elf and aligned DWARF flags (--dwarf-stack-traces, --resolve-dwarf-paths, --save-debugging-info=..., --strip).
  4. Linking (aot_tools link): links the baseline App binary and the new out.aot snapshot into patch artifact. Unchanged Dart functions continue to execute at full native speed on ARM64 hardware, while modified or newly introduced Dart functions are executed by the embedded interpreter.
  5. Signed Bundle Restoration: restores .ota_ios_release_cache/<version>/Runner.app into build/ios/iphoneos/Runner.app (since --no-codesign had stripped codesigning).
Preserving .ota_ios_release_cache/<version>

On iOS, aot_tools link requires the baseline Mach-O App binary and accompanying supplement/ files to generate valid dispatch tables for patch artifact. Preserve or archive the .ota_ios_release_cache/<version>/ folder in CI/CD throughout the production lifecycle of that release.

2. iOS Artifact Formats (.ipa vs .app) and Export Methods​

The CLI supports direct generation of signed .ipa archives via --artifact ipa, --export-method, and --export-options-plist:

CLI FlagSupported ValuesUsage
--artifact ipaipa (or default ios)Runs flutter build ipa --release and extracts Runner.app from build/ios/archive/Runner.xcarchive.
--export-methodapp-store, ad-hoc, enterprise, developmentForwards --export-method=<method> to flutter build ipa.
--export-options-plistPath to .plist fileForwards --export-options-plist=<path> to flutter build ipa for custom Xcode export options.

iOS Command Examples​

# iOS Release targeted for TestFlight / App Store Connect
tk-ota-push release -p ios --artifact ipa --export-method app-store

# iOS Ad-Hoc Release for internal distribution to registered test iPhones (UDID)
tk-ota-push release -p ios --artifact ipa --export-method ad-hoc

# Publishing an iOS patch to the active Release
tk-ota-push patch -p ios -m "Fix biometric verification issue"

3. iOS Native Integrity Safeguard (NativeIntegrityScanner.scanIosApp)​

Just as on Android, an iOS OTA patch cannot modify Swift/Objective-C native code or Apple-signed system frameworks.

NativeIntegrityScanner.scanIosApp(Directory appDir) (lib/src/cli/native_integrity.dart) computes a deterministic SHA-256 fingerprint over:

  • Info.plist
  • The main Mach-O executable binary located at the root of Runner.app
  • All files located under Frameworks/, strictly excluding Frameworks/App.framework (which contains Dart code).

If a modification to Info.plist, a CocoaPod framework, or Swift native code is detected during patch, the CLI aborts and instructs you to publish a new Store Release.

4. Apple Compliance (App Store Review Guidelines)​

TkushPatch's iOS design aligns with Apple App Store Review Guidelines:

  • No executable Mach-O code is downloaded or mapped with PROT_EXEC post-installation.
  • Unchanged functions execute native machine instructions signed by Apple in App.framework/App during initial App Store submission.
  • Modified functions in patch artifact are executed strictly by the interpreted virtual machine within the C++ Flutter engine, without JIT compilation.
  • All patches are signed via digital signature and validated by the Rust engine (patch_verification: strict).